I’ve been enthralled with the security features for Catalyst switches. I’ve had to plug away at the theory and lab work recently, but have probably gone a little further down the rabbit hole in this area. I feel that solid knowledge of DHCP Snooping is needed as a foundation for other security features. Both IP Source Guard and Dynamic ARP Inspection rely on it, so if you’ve got your head around snooping, you’ll be in good shape.
Why do we need DHCP Snooping?
We need DHCP Snooping to prevent a man-in-the middle attack on our network. The potential exists for an attacker to pretend (spoof) to be the DHCP server and respond to DHCPDISCOVER messages before the real server has time to respond. DHCP Snooping allows switches on the network to trust the port a DHCP server is connected to (this could be a trunk) and not trust the other ports. It also maintains a list of DHCP address bindings by inspecting traffic flowing between clients and the DHCP server, which provides certainty around who the real hosts are. The binding information collected by DHCP Snooping is used by other security features like IPSG and DAI.
Our client connects to an untrusted port; all ports are untrusted by default. When the client machine sends a DHCPDISCOVER message with DHCP Snooping enabled, the switch will only send the DHCP broadcast message to trusted ports. In this case our distribution switch is acting as the DHCP server, but a DHCP server running external to the switch could also be used. A trusted port is the only port which is allowed to send DHCP Server responses such as DHCPOFFER.
Let’s jump onto SW1 and enable DHCP Snooping:
SW1(config)#ip dhcp snooping
We also need to enable it for our VLANs. In this case we’re only using VLAN 1:
SW1(config)#ip dhcp snooping vlan 1
Great so far! Now, we make Fa0/1 facing DSW1 a trusted port:
SW1(config-if)#ip dhcp snooping trust
It’s a good idea to enable rate limiting on the untrusted ports. This is specified in packets per second, and is used to prevent an attacker from hammering our DHCP server with so many requests that it exhausts all of the IP addresses it has to offer:
SW1(config-if)#ip dhcp snooping limit rate ?
<1-4294967294> DHCP snooping rate limit
SW1(config-if)#ip dhcp snooping limit rate 25
Let’s take a look at the DHCP Snooping config:
SW1#sh ip dhcp snooping
Switch DHCP snooping is enabled
DHCP snooping is configured on following VLANs:
Insertion of option 82 is enabled
Interface Trusted Rate limit (pps)
———————— ——- —————-
FastEthernet0/1 yes unlimited
FastEthernet0/24 no 25
Next we connect our client machine to Fa0/24 on SW1. We can see the DHCP binding has been captured by DHCP Snooping:
The DHCP Snooping binding table contains the MAC address, IP, lease time, lease type, VLAN ID and attached interface for each client.
DHCP Option 82
DHCP Option 82 has the potential to cause network engineers an awful lot of grief if we don’t keep it in check. When DHCP Snooping is enabled, DHCP Option 82 is inserted into DHCP packets as they pass through a switch. Option 82 contains information about the specific port a client machine is connected to. DHCP packets also carry a “giaddr” field which is set to 0.0.0.0 by default (a non-zero value). (EDIT: I originally said giaddr was a field in Option 82, however it is a field in the DHCP packet not Option 82 itself. Thanks to Bob for pointing this out.) Both of these things will show up in error messages if something is misconfigured. In the topology above, Option 82 isn’t a problem because DHCP Snooping isn’t enabled on DSW1 (only on SW1), so let’s add another switch:
In this topology, the ports facing our DHCP server, Fa0/2 on SW1 and Fa0/11 on SW2, have been configured as trusted ports. By default, SW1 will insert DHCP Option 82 into all DHCP packets it receives from the client. Also by default, SW2 will drop those packets as soon as it receives them. A switch with DHCP Snooping enabled will drop packets on untrusted ports that contain Option 82 or have a non-zero giaddr (e.g. 0.0.0.0). This is what is seen in debug on SW2 when SW1 sends a DHCPDISCOVER out port Fa0/2:
%DHCP_SNOOPING-5-DHCP_SNOOPING_NONZERO_GIADDR: DHCP_SNOOPING drop message with non-zero giaddr or option82 value on untrusted port
Remember that port Fa0/24 on SW2 is an untrusted port from DHCP Snooping’s point of view, so it drops the packets by default because Option 82 exists. That traffic never makes it to DWS1. There are several ways to get around this problem, although initially, I got myself very confused while I was labbing various topologies. (It took a Hawaiian vacation to straighten things out!) We’ll solve this problem by using one command on SW2 that will trust packets with DHCP Option 82 that are received on untrusted ports.
SW2(config)#ip dhcp snooping information option allow-untrusted
Because our DHCP server is a Cisco IOS device, it also needs to trust DHCP packets with option 82 set:
DSW1(config)#ip dhcp relay information trust-all
We’re pretty much done here. An alternative would be to make port Fa0/24 a trusted port, but this would expose us security-wise. We could also stop DHCP Snooping from inserting Option 82 in the first place (using #no ip dhcp snooping information option). We’ll leave it here for now, but I encourage you to lab this up yourself and play with the various combinations of inserting DHCP Option 82, trusting it, and not trusting it. You could also swap DSW1 for a router or use DHCP server from another vendor. I found Marko Milivojevic’s four part in-depth post on Understanding DHCP Snooping helpful when coming to grips with DHCP Option 82 in particular.