Sunday, March 31, 2013

DHCP Snooping and Option 82

This is yet another one of those topics I always passed over.  "DHCP snooping", I'd say to myself, "is too simple to bother with".  I've also never put it into production, so I've absolutely never set it up.  Figured this was as good a time as any.  When I write about these topics I like to learn all aspects of them, so I'll delve into the problems created by DHCP option 82 as well.

We'll start out really simple on this one just to get the feature working.

One VLAN (100), one subnet.  R1 will be the DHCP server, R3 will be the DHCP client.  SW1 will be running DHCP snooping.  Once again, I tend to use GNS3 for diagrams (probably obvious from the icons), but this cannot actually be labbed in GNS as the 16-port switch that can be inserted in the 3725 doesn't have the capacity to perform DHCP snooping.  I'm using real 26xx series routers and 3560 switches.

First we'll start without snooping.

interface FastEthernet0/0
 ip address

ip dhcp pool DHCPSERVER

interface FastEthernet0/1
 switchport access vlan 100
 switchport mode access

interface FastEthernet0/3
 switchport access vlan 100
 switchport mode access

interface FastEthernet0/0
 ip address dhcp

And the outcome?

*Mar  2 18:28:21.315: %DHCP-6-ADDRESS_ASSIGN: Interface FastEthernet0/0 assigned DHCP address, mask, hostname R3

OK great, we were assigned  Of interesting note, but will only briefly be touched on in this document, are the mentions of "pool class" and "circuit id" - these fields are part of Option 82, which will be discussed later.

We'll turn on DHCP snooping next, but first let's consider why we'd want to turn it on.  There are four primary reasons:
- Prevent rogue DHCP servers from answering before the real DHCP server(s).  Rogue DHCP servers would likely be interested in handing out a malicious default gateway that could intercept information before handing it off to the real default gateway.
- Prevent a malicious "client" from requesting hundreds of addresses and using up the entire pool; a DOS-style attack, where new clients would be unable to get an address.
- IP Source Guard (discussed later)
- Dynamic ARP Inspection (discussed later)

ip dhcp snooping
ip dhcp snooping vlan 100  ! you need to turn it on on the specific VLANs you want it on.

interface Fa0/1
  ip dhcp snooping trust  ! don't forget to trust the port your DHCP server is connected to
  ip dhcp snooping limit rate 5 !  DHCP packets allowed per second (keep low to avoid DOS)

Should work great right?

R3(config-if)#no ip address dhcp
R3(config-if)#ip addr dhcp

[wait 60 seconds]

R3(config-if)#do show ip int fa0/0 | i DHCP
  Internet address will be negotiated using DHCP

Uh-oh, no IP address.  We also have no output on R1, so we're going to have to enable the debug to find out what's going on.

R1#debug ip dhcp server packet
*Mar  2 19:11:28.969: DHCPD: inconsistent relay information.
*Mar  2 19:11:28.969: DHCPD: relay information option exists, but giaddr is zero.

Wait what?  giaddr?

Defined in RFC 2131, the giaddr is used in DHCP relay scenarios to indicate which pool/subnet the DHCP server should assign the address from.  There's really no need for it here, as we're not using a relay.  However, option 82 has been set by the snooping process on the 3560.  Option 82?  Option 82 is used in provider networks to give extra information to the DHCP server regarding where a device is located.  The details of Option 82 aren't key to this post, or, as best I can tell, to the CCIE R&S.  However, if a router sees Option 82, by default, it expects the giaddr to be non-zero as well. 

So now we have two options:
- Tell the switch not to set Option 82
- Tell the router to ignore Option 82

For the first option, we can globally disable the setting of Option 82 with:

no ip dhcp snooping information option

R3(config-if)#no ip address dhcp
R3(config-if)#ip addr dhcp
R3(config-if)# Mar  2 20:11:27.989: %DHCP-6-ADDRESS_ASSIGN: Interface FastEthernet0/0 assigned DHCP address, mask, hostname R3

Or we can turn that option back on:

ip dhcp snooping information option

And disable the check for zero gi-addr on the DHCP server:

ip dhcp relay information trust-all

This command instructs the DHCP server that blank giaddr is acceptable, even if option 82 is set.

Let's make this trickier and add a dhcp relay.

We've stuck VLAN 101 on the back end of R3.  R3 will relay DHCP requests from VLAN 101 back to R1.  Here's the relevant added config:

ip dhcp pool DHCPSERVER101

router eigrp 1    ! R1 has to have a route back to R3's interface on VLAN 101

interface FastEthernet0/1
 no shutdown
 ip address
 ip helper-address  ! Relay VLAN 101 requests to the DHCP server

router eigrp 1   ! R3 has to advertise a route back to its interface on VLAN 101

SW2 is generally blank except for the creation of VLAN 101 and the appropriate access port assignments.

interface FastEthernet0/1
 no shutdown
 ip address dhcp

Once again, should be all peachy, right?

Not so fast....

SW1# *Mar  2 21:22:44.713: %DHCP_SNOOPING-5-DHCP_SNOOPING_NONZERO_GIADDR: DHCP_SNOOPING drop message with non-zero giaddr or option82 value on untrusted port, message type: DHCPDISCOVER, MAC sa: 0012.43c1.6f20

Now we have a condition where giaddr is set and option 82 isn't on the packet headed from R3 towards R1 via SW1.  The giaddr must be set; otherwise R1 wouldn't know which pool to assign from.  How to fix this?

We basically have to push the DHCP "trust boundary" downstream.  In this case, R3 now also needs to become a trusted port:

SW1(config)#int fa0/3
SW1(config-if)#ip dhcp snoop trust

...and then all is well:

R5(config-if)# *Jan  4 01:00:58.896: %DHCP-6-ADDRESS_ASSIGN: Interface FastEthernet0/1 assigned DHCP address, mask, hostname R5

This isn't really related to DHCP snooping, but here's a way to create a really nasty debugging task - by default, the "ip helper-address" command does a number of things, including relaying DHCP requests.  But did you know that the DHCP function can actually be disabled?

R3(config)#no service dhcp

R5(config-if)#no ip add
R5(config-if)#ip add dhcp

[wait 60 seconds] address.

The service dhcp needs to be enabled for ip helper-address to relay DHCP requests.

Now let's look at one last scenario:

VLAN 100 spans both switches.  It's on a trunk between SW1 and SW2.  Now let's setup DHCP snooping on both switches.  It's already enabled on SW1.

ip dhcp snooping vlan 100
ip dhcp snooping
R5(config-if)#no ip add
R5(config-if)#ip add dhcp
SW1#*Mar  2 22:11:23.017: %DHCP_SNOOPING-5-DHCP_SNOOPING_NONZERO_GIADDR: DHCP_SNOOPING drop message with non-zero giaddr or option82 value on untrusted port, message type: DHCPDISCOVER, MAC sa: 0019.2fb8.d552

We've seen this before.  Except this time, option 82 is set, and giaddr isn't.  We don't really care about option 82 in this topology, so we have two choices of how to deal with this problem:
- Stop SW2 from setting option 82 (As seen earlier)
   SW2(config)#no ip dhcp snooping information option- Tell SW1 to accept option 82 on untrusted ports
   SW1(config)#ip dhcp snooping information option allow-untrusted

In addition, the DHCP snooping process creates a database of IP address to MAC addresses that can be used for other security tasks, discussed below.  Since this database can be of some importance, you can optionally store it to flash, tftp, etc.  For example:

ip dhcp snooping database flash:/dhcp.txt
In the introduction I mentioned that IP Source Guard and Dynamic ARP Inspection were motivating factors for using DHCP Snooping.  Both of these features rely on the DHCP snooping database to function.

IP Source Guard will inspect traffic from hosts to be certain they're not spoofing their IP address or, optionally, MAC address.  As mentioned, it knows the MAC and IP information from the DHCP snooping database.  Enabling the feature is simple:

SW1(config-if)#ip verify source ! check IP addresses
SW1(config-if)#ip verify source port-security ! check IPs & MACs

If you don't want to rely strictly on the DHCP snooping database, you can make manual entries:

SW1(config)#ip source binding mac-address vlan vlan ip-address interface interface

Of important note, source guard can be used in a non-DHCP environment using the above command to populate the reference table, however, you must still enable dhcp snooping globally and on the specific VLAN in order for source guard to function!

Dynamic ARP inspection blocks "a variety of ARP-based attacks", according to the documentation.  The usage is simple.  Drop ARPs that shouldn't be coming based on the information seen in the DHCP snooping table. 

SW1(config-if)#ip arp inspection trust  ! need to trust other switches
SW1(config)#ip arp inspection vlan 100  ! turn the feature on globally for the VLAN
That's the basics for enabling it.




  1. What happens if you have two wifi access points, one hooked to each switch. Then someone roams between the two. If all wireless devices also send a DHCP renewal then I can see everything working just fine. But if they don't, is there a way to mark certain ports as "portable" between the switches? Stackable switches handle this, but our company doesn't have the budget for stackable switches...

  2. Great post...thanks for sharing your knowledge with us...

  3. I sandboxed ip dhcp snooping in a lab that used ip helper. I was not able to get the Rouge dhcp server to infect the lab. Question is - does the helper point the network to where it wants to get an address from and ignores any other packets from others?

  4. Hi,

    I tried 3 routers (R5 is dhcp server and the other 2(R1 and R3 on a different vlan as the dhcp server). RI acquires IP via DHCP whiie R3 has a static IP.

    The 3 routers are all connected on SW1(Layer 3 switch)

    I have enabled dhcp snooping first trusted port connected to dchp server R5. I can acquire IP even if option 82 is enabled on switches and on the router...

    Although I see this message on the debug ip dhcp server packet:
    *Sep 27 15:31:22.103: DHCPD: inconsistent relay information.
    *Sep 27 15:31:22.103: DHCPD: relay information option exists, but giaddr is zero.
    *Sep 27 15:31:23.871: DHCPD: inconsistent relay information.
    *Sep 27 15:31:23.871: DHCPD: relay information option exists, but giaddr is zero.
    *Sep 27 15:31:25.875: DHCPD: inconsistent relay information.
    *Sep 27 15:31:25.875: DHCPD: relay information option exists, but giaddr is zero.
    *Sep 27 15:31:30.443: DHCPD: DHCPDISCOVER received from client 0063.6973.636f.2d30.3031.332e.6333.6432.2e33.3838.302d.4661.302f.30 through relay
    *Sep 27 15:31:30.443: DHCPD: Sending DHCPOFFER to client 0063.6973.636f.2d30.3031.332e.6333.6432.2e33.3838.302d.4661.302f.30 (
    *Sep 27 15:31:30.443: DHCPD: unicasting BOOTREPLY for client 0013.c3d2.3880 to relay
    *Sep 27 15:31:30.459: DHCPD: DHCPREQUEST received from client 0063.6973.636f.2d30.3031.332e.6333.6432.2e33.3838.302d.4661.302f.30.
    *Sep 27 15:31:30.459: DHCPD: No default domain to append - abort update
    *Sep 27 15:31:30.459: DHCPD: Sending DHCPACK to client 0063.6973.636f.2d30.3031.332e.6333.6432.2e33.3838.302d.4661.302f.30 (
    *Sep 27 15:31:30.459: DHCPD: unicasting BOOTREPLY for client 0013.c3d2.3880 to relay

    It still gets the IP.

    One more thing, I removed the command ip dhcp snoop trust on the switchport connecting to dhcp server R5. I again asked for IP for R1, R1 still gets the IP address... Is this behaviour software version dependent?

    R1#sh ver
    Cisco IOS Software, C2600 Software (C2600-ADVENTERPRISEK9-M), Version 12.4(25d), RELEASE SOFTWARE (fc1)
    System image file is "flash:c2600-adventerprisek9-mz.124-25d.bin"

    R3#sh ver
    Cisco IOS Software, 3600 Software (C3640-JS-M), Version 12.4(25c), RELEASE SOFTWARE (fc2)
    System image file is "flash:c3640-js-mz.124-25c.bin"

    SW1#sh ver
    Cisco IOS Software, C3560 Software (C3560-IPSERVICESK9-M), Version 12.2(50)SE5, RELEASE SOFTWARE (fc1)
    BOOTLDR: C3560 Boot Loader (C3560-HBOOT-M) Version 12.2(44)SE5, RELEASE SOFTWARE (fc1)

    R5#sh ver
    Cisco IOS Software, 1841 Software (C1841-ADVIPSERVICESK9-M), Version 12.4(20)T, RELEASE SOFTWARE (fc3)
    System image file is "flash:c1841-advipservicesk9-mz.124-20.T.bin"

  5. This is very lazy test scenario, you need to add DHCP servers on SW1, SW2 and see you getting right DHCP IP from the Right DHCP Server, otherwise this is useless and not practical!

  6. Hi Jeff,
    I am confusing to this statement "We basically have to push the DHCP "trust boundary" downstream. In this case, R3 now also needs to become a trusted port:" you posted in the scenario 2 of the three, why the port f0/3 must be configured to "trusted port" ? From my understanding the "trusted port" will limit the dhcp offer message rather than discovery message, so at least the DHCP server should received DHCP discovery message from client even if the port f0/3 is a untrust port. Indeed, if I configured the port f0/3 as untrust port, the discovry packet from client was being dropped on the port f0/3 ingress direction. Just want to know why if dhcp relay is used, the port f0/3 must be configured as trusted port in this scenario. Please kindly advise.