DHCP Snooping – Filter those broadcasts!

I had a specific requirement recently and I wanted to test it’s behaviour. In particular the feature is DHCP snooping. Let’s quickly go over the DHCP process at a high level to see how it works:

DHCP

Let’s take the following simple diagram to show what’s going on. We have a switch with two hosts connected. We also have a DHCP server. I’m using generic names as I’ll be testing this on different switches. Assume all devices are in the same vlan.
dhcp_snoop1

Host1 has just booted and needs an IP address. It’ll send a DHCP DISCOVER packet which is a broadcast. This broadcast gets sent to all ports in the vlan:
dhcp_snoop2

The DHCP server will then send an DHCP OFFER to host 1. It does this via unicast using the destination MAC as the layer 2 destination:
dhcp_snoop3

Host1 then send a DHCP REQUEST via broadcast. Why broadcast? This is because it may have received offers from multiple DHCP servers and is essentially telling all of them that they are accepting an offer some one of them.
dhcp_snoop4

Finally, the DHCP server acknowledges that Host1 has accepted it’s offered IP with a DHCP ack. This is unicast again:
dhcp_snoop5

Now, depending on bootp options, the offer and/or ack might actually be broadcast. The behaviour is also slightly different when using DHCP helpers, but we are mainly concerned with the DHCPDISCOVER and DHCPREQUEST packets which are always broadcast.

DHCP Snooping

In the above example, there was nothing stopping Host 2 from providing IP addresses via DHCP. This might either be malicious activity, or merely someone doing something wrong and either configuring a device wrong, or plugging in a device which should not be there.

DHCP snooping was created to prevent this from happening. DHCP’s main concern is making sure that DHCPOFFERS only come in via trusted ports. In our example port 1 connected to the DHCP server should be a trusted port. Port2 and port 3 connected to Host 1 and Host 2 respectively should never have DHCPOFFER packets on ingress. But here is the kicker. A DHCPOFFER is in response to an event. That event is a DHCPDISCOVER. That DHCPDISCOVER is a broadcast.

It stands to reason that if a DHCPOFFER cannot ever ingress port2 and port3, those ports should never have DHCPDISCOVER packets replicated to them to begin with, regardless of whether those packets are broadcast. All other broadcasts should go through, but these specific DHCP ones should not.

So is this what we actually see in the real world? I’ll test this on the devices I have available to see what behaviour I see.

Cisco Catalyst IOS

My config is as follows:

ip dhcp snooping vlan 1-4094                                                                           
ip dhcp snooping 

interface FastEthernet0/1                                                                              
 switchport access vlan 10                                                                             
 switchport mode access                                                                                
!                                                                                                      
interface FastEthernet0/2                                                                              
 switchport access vlan 10                                                                             
 switchport mode access        
!
interface FastEthernet0/24                                                                             
 switchport access vlan 10                                                                             
 switchport mode access                                                                                
 ip dhcp snooping trust     

DHCP snooping enabled with fa0/24 being the trusted port going towards my server.

I have host1 and host2 connected with the following MAC addresses:

  • 78:2b:cb:e4:e3:88
  • 00:26:5a:ef:85:33

I’ll now listen on fa0/24. I should see both DHCPDISCOVER broadcasts coming though:

$ sudo tcpdump -i eth1 -n port 67 and port 68
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
11:45:45.204815 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 78:2b:cb:e4:e3:88, length 300
11:45:48.733826 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:26:5a:ef:85:33, length 300

That’s exactly what I see.

If I now move the capture point over to fa0/2, I hope to see no broadcasts at all. If not, this would mean the device is not replicating those broadcasts out untrusted ports:

$ sudo tcpdump -i eth1 -n port 67 and port 68
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes

Silence. That’s just what I wanted to see.

Juniper EX

Config is as follows:

[email protected]> show configuration interfaces ge-0/0/2           
unit 0 {
    family ethernet-switching {
        port-mode access;
        vlan {
            members vlan_test;
        }
    }
}

{master:0}
[email protected]> show configuration interfaces ge-0/0/3           
unit 0 {
    family ethernet-switching {
        port-mode access;
        vlan {
            members vlan_test;
        }
    }
}

{master:0}
[email protected]> show configuration interfaces ge-0/0/4           
unit 0 {
    family ethernet-switching {
        port-mode access;
        vlan {
            members vlan_test;
        }
    }
}


[email protected]> show configuration ethernet-switching-options    
secure-access-port {
    interface ge-0/0/4.0 {
        dhcp-trusted;
    }
    vlan all {
        examine-dhcp;
    }
}

ge-0/0/4 is now my trusted DHCP server port. If I listen on that port, I should see both devices broadcasts:

$ sudo tcpdump -i eth1 -n port 67 and port 68
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes

11:58:02.539119 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 78:2b:cb:e4:e3:88, length 300
11:58:05.809947 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:26:5a:ef:85:33, length 300

What about when listening on the untrusted port?

$ sudo tcpdump -i eth1 -n port 67 and port 68
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
11:58:55.342651 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 78:2b:cb:e4:e3:88, length 300

I hear the broadcast come through. There is only one MAC as I’ve had to disconnect the host in order to listen via wireshark.

Conclusions

  • IOS switches filter the initial DHCPDISCOVER broadcast packets. Junos switches do not.
  • Both devices DO drop DHCPOFFER packets coming in on untrusted ports.
  • Cisco is a bit more intelligent in it’s behaviour.

Not filtering the broadcast initially doesn’t break DHCP snooping. But it’s completely unnecessary. Why send a request out a port that you would filter a reply? I’ve seen switches reload and suddenly all devices on the switch try to get their IPs back. All devices receive all these broadcasts when only the trusted port should receive it. Filtering ensures less broadcasts on the network and also prevents badly configured devices from replying to a packet it should never have received.

© 2009-2020 Darren O'Connor All Rights Reserved -- Copyright notice by Blog Copyright