Even though I always had a solid high level understanding of DHCP Snooping feature, I had no idea what happens ‘under the hood’. Until now. We’ve never been using this security enhancement (for whatever reason), but things are changing now. You’ll be surprised to find out that we’re deploying DHCP Snooping primarily to improve Cisco ISE Profiling. If you want to know more, read about Cisco IBNS 2.0 and Profiling Design Guide, specifically profiling using Device Sensor and Radius accounting. I might be able to cover this topic in detail sometime later (let me know if it’s of interest). Today, however, I’d like to concentrate on DHCP Snooping.
Let’s first have a look at normal/standard DHCP operation using the following setup.
For the sake of simplicity, this is flat Layer 2 network, where all endpoints (Client, Rogue and DHCP Server) belong to VLAN 10 (192.168.0.0/24). Now, let’s capture some traffic on ALL endpoints, while we’re refreshing DHCP lease on the Client.
Spend some time to analyze packet capture details.
- Frame #1 is Gratuitous ARP. It was sent by the Client before it requested IP address from DHCP server. It simply notifies other clients that it has no IP address just yet (this will reset ARP cache as well, in case remote endpoints has outdated MAC/IP binding for this client).
- Frame #2 is Broadcast DHCP DISCOVER message.
- Frame #3 is ARP check sent by DHCP server to confirm there’s no duplicate IP address exist for the one it’s about to offer.
- Frame #4 is DHCP OFFER sent by DHCP server to everyone in VLAN 10.
- Frame #5 is DHCP REQUEST sent by the Client to confirm its selection (still broadcast!)
- Frame #6 is DHCP ACK send by the DHCP server to confirm the lease (this one is also broadcast!)
- Frame #7 is Gratuitous ARP sent by the Client to let everyone know its current IP address
Please note, this view is identical on ALL endpoints due to Broadcast nature of all seven frames.
So, the outcome would be
By default, every endpoint overhears all DHCP packets within its Layer 2 domain (VLAN).
Rogue can silently sit and collect information about endpoints and their IP/MAC addresses. This information can be spoofed at later point.
Now, let’s configure DHCP server feature on our Rogue and refresh the lease on the Client.
Are you able to quickly see what’s changed? The order is pretty much the same as before, but this time our Rogue was the first to respond with DHCP OFFER (Frame #5), which was blindly accepted by the Client (Frame #6). So, this is how Man in the Middle works with Spoofed DHCP service. I have made my Rogue a gateway for everyone who accepts its DHCP OFFERS. Therefore I can eavesdrop on any unencrypted traffic (and even modify it) and then forward it to legitimate gateway without legitimate users even noticing.
Here’s DHCP Snooping comes into play.
Once enabled (per-VLAN) it tells switch to intercept EVERY DHCP packet and inject Option-82 into it, which it then uses to protect the environment from illegitimate DHCP servers. How does it work?
It’s very simple, yet many people are confused with Option-82. Take a look at the following screenshot
Agent Circuit ID and Agent Remote ID are very important for DHCP Snooping to work as it was designed! Agent Circuit ID contains the information that identifies the switch port where the Client connects. Agent Remote ID identifies the switch! Read it few times until you get it.
Execute ‘show ip dhcp snooping‘ on the switch to understand Circuit-ID and Remote-ID concept:
Switch DHCP snooping is enabled Switch DHCP gleaning is disabled -- omitted for brevity -- Insertion of option 82 is enabled circuit-id default format: vlan-mod-port remote-id: 5001.0001.0000 (MAC) Option 82 on untrusted port is not allowed -- omitted for brevity --
This information, coupled with DHCP Snooping engine, makes DHCP virtually unicast. Switches with DHCP Snooping enabled will control DHCP frames propagation in the following way.
- Client sends DHCP DISCOVER
- SW1 analyzes it and injects DHCP Option-82 where it stores information about itself (Remote ID) and port to which client is connected (Circuit ID)
- SW1 replicates this broadcast packet on EVERY trusted interface
- DHCP server receives DHCP DISCOVER packet and replies with DHCP OFFER
- It is important to understand that server can do whatever it wants with Option-82, but it MUST preserve it when it replies. Hence DHCP OFFER and DHCP ACK have Option-82 copied from DHCP DISCOVER and DHCP REQUEST respectively. And this is how SW1 knows that packet originated from itself!
- SW1 sees DHCP OFFER with Option-82, it checks Option-82 and compares Remote ID to its own
- If there’s a match, then SW1 strips off Option-82 from the packet and sends it via ONE port only (Circuit ID)
- If there’s no match, SW1 will forward this broadcast packet via all trusted interfaces
- If there’s no match and no other trusted interfaces, SW1 will discard DHCP OFFER
- Client will respond with DHCP REQUEST
- SW1 intercepts and adds Option-82, then forwards via all trusted interfaces
- DHCP server receives DHCP REQUEST and replies with DHCP ACK (inc Option-82)
- SW1 strips off Option-82 from the DHCP ACK and then forwards this packet to the Client over single interface
Do you now see how DHCP has suddenly become “unicast“? Switch will replicate DHCP packets via untrusted port ONLY if DHCP DISCOVER originated from the same port, hence Rogue will never ever see any DHCP packets except its own. Let’s have a look at packet capture. Same setup, same scenario, but now we configure DHCP Snooping on SW1:
SW1(config)#ip dhcp snooping vlan 10 SW1(config)#ip dhcp snooping SW1(config)#interface gi0/2 SW1(config-if)#ip dhcp snooping trust
Interface Gi0/2 was configured as TRUSTED because this is where our DHCP server connects (via SW2)
Packet capture is being executed on all endpoints, like the last time. However, the result is not identical anymore.
Here’s DHCP server’s view:
Pretty much same as before with only one difference that can be seen if we analyze any DHCP packet in detail:
DHCP Server sees Option-82 which was injected by the switch SW1. Now, let’s have a look at the Client:
Same packets as in the previous example with few minor differences – packet size differs. Let’s analyze the contents of any packet coming from the DHCP server, such as DHCP OFFER:
So, as I previously said… Client DOES NOT see DHCP Option-82 as it is stripped off by the switch (in fact, it is replaced by the padding to preserve original packet’s size – as sent by the server).
Right… now the interesting part of this conversation. Rogue. What does it see?
Rogue sees nout. Hence, it can’t spoof DHCP service. However, even if Rogue begins to maliciously send DHCP packets, those will be dropped because no DHCP packets without Option-82 (except DHCP DISCOVER) are allowed to be seen on untrusted ports.
This is very important concept to understand. I’ve seen many articles where people recommend disabling Option-82 using ‘no ip dhcp relay information option’, making DHCP snooping less effective. Why would you deploy a protection mechanism to then disable its critical component?
If DHCP Snooping is configured in a Layer 2 domain with multiple switches, such as in our example, then all UPLINKS and DOWNLINKS must be configured as ‘trusted’ interfaces. This bit is confusing, but only if you haven’t read this article carefully 🙂 Why would you make Gi0/0 on SW2 a trusted interface, if there’s no trusted DHCP server behind it?
It’s simple. If you don’t do this, SW2 will drop DHCP DISCOVER with Option-82 coming from SW1 because it simply doesn’t expect DHCP packets with Option-82 from untrusted interfaces. Untrusted interfaces (connected to endpoints) will always send DHCP DISCOVER without Option-82. Hence, uplinks and downlinks must be configured as trusted interfaces.
To make this solution complete, SW2 has to be configured as follows:
SW2(config)#ip dhcp snooping vlan 10 SW2(config)#ip dhcp snooping SW2(config)#int range gi0/0 - 1 SW2(config-if-range)#ip dhcp snooping trust
I hope this was helpful. Please note that DHCP Snooping is a critical component for many other security features which rely on IP/MAC binding database maintained by DHCP Snooping, such as Dynamic ARP Inspection (DAI), IP Source Guard and enhanced Cisco ISE Endpoint Profiling.
Update #1 (17/11/2018): I have faced one issue recently which I wasn’t able to understand at first. Basically, I configured DHCP Snooping on downstream access switch, but haven’t on the upstream core/distribution. All my DHCP packets have been silently discarded by an upstream switch. It took me a while (and some packet captures) to realize that DHCP relay configuration on SVIs didn’t like giaddr of 0.0.0.0 (set by DHCP snooping on downstream switch). This article suggests a genuine fix for the problem. Basically, there are two proper ways to do this
- Make all relays to trust giaddr 0.0.0.0 globally:
ip dhcp relay information trust-all
- Manually configure relay trust on SVIs with ip helpers:
ip dhcp relay information trusted