In this post I will be explaining what DHCP snooping is and why it is useful to implement this within your network. Afterwards, we’ll dive into configuring DHCP snooping by using an example topology.

DHCP snooping is a layer 2 security feature aimed towards providing protection against rogue DHCP servers in your network. That’s it. Nothing more, nothing less. It uses a mechanism of trusted and untrusted sources. By default every port is untrusted and you manually configure ports which should be trusted. You should at least have one port in the trusted state, namely the port where your legitimate DHCP server resides behind.

Before we continue, let’s freshen up our knowledge about the basic steps within the DHCP negotiation process:

  • A client will fire off the DHCP negotiation process by sending a DHCP DISCOVER message.
  • The DHCP server replies with a free ip address through the DHCP OFFER message
  • The client will upon receiving this offer, send the request for an ip address, called the DHCP REQUEST message
  • When the DHCP server agrees on the contents of the request, it will send a DHCP ACKNOWLEDGE.

A good acronym to remember this order is:
D(iscover) O(ffer) R(equest) A(cknowledge), or DORA! dora

Some things will change when you implement DHCP snooping. For instance, when a client sends the DHCP DISCOVER message, a switch with DHCP snooping enabled will only forward this broadcast message onwards to trusted ports. This inherently means that rogue DHCP servers will never get the initial DHCP DISCOVER message, meaning that they can’t answer to that message and interfere with the DHCP process.

A switch with DHCP snooping enabled, will also keep track of successful DHCP negotiations. Upon receiving a DHCP ACKNOWLEDGE, the switch will update the new lease in the so called DHCP snooping binding table. The binding table offers very little added value for DHCP snooping, other than knowing out which interface to sent a DHCP release once a processed DHCP lease is to be released. The binding table is also being used for other security mechanisms, like Dynamic Arp Inspection and IP Source Guard.

Let’s explore the way DHCP snooping works and experiment with a few things! We’ll be using the following topology and first set up a basic infrastructure upon which we’ll be activating DHCP snooping.

DHCP Snooping - initial

This topology has the following properties:

  • The middle ‘Router’ is the DHCP server.
  • The ‘Left’ and ‘Right’ switches are DHCP snooping enabled
  • The ‘Rogue DHCP Server’ will try to interfere with the legitimate ‘Router’ DHCP server
  • The PC’s will request an IP address through DHCP, whereas the ‘Spoofed PC1’ will be used to experiment with mac address spoofing.

We will be mainly focussed on altering configuration on the left side of the topology, but I’ve built two DHCP scopes just to have fun and explore other technologies as well. In this case, multiple DHCP scopes on one Cisco router with subinterfaces for the different VLANs. The emulation software I’m using to build this topology is Cisco VIRL.

Basic Topology Configuration

The basic configuration without DHCP snooping is as follows:

Router:

ip dhcp pool SERVER1
 network 192.168.1.0 255.255.255.0
 default-router 192.168.1.1 
 lease 0 0 5
!
ip dhcp pool SERVER2
 network 192.168.2.0 255.255.255.0
 default-router 192.168.2.1 
 lease 0 0 5
!
interface GigabitEthernet0/1
 no ip address
 duplex auto
 speed auto
 media-type rj45
!
interface GigabitEthernet0/1.100
 encapsulation dot1Q 100
 ip address 192.168.1.1 255.255.255.0
!
interface GigabitEthernet0/2.200
 encapsulation dot1Q 200
 ip address 192.168.2.1 255.255.255.0

Left:

vlan 100
!
interface GigabitEthernet0/1
 description SERVER1
 switchport access vlan 100
 switchport mode access
 media-type rj45
 negotiation auto
!
interface GigabitEthernet0/2
 description DHCP Server
 switchport trunk allowed vlan 100
 switchport trunk encapsulation dot1q
 switchport mode trunk
 media-type rj45
 negotiation auto
!
interface GigabitEthernet0/3
 description ROGUE
 switchport access vlan 100
 switchport mode access
 media-type rj45
 negotiation auto
!
interface GigabitEthernet1/0
 description SPOOFPC
 switchport access vlan 100
 switchport mode access
 media-type rj45
 negotiation auto

Right:

vlan 200
!
interface GigabitEthernet0/1
 description DHCP Server
 switchport trunk allowed vlan 200
 switchport trunk encapsulation dot1q
 switchport mode trunk
 media-type rj45
 negotiation auto
!
interface GigabitEthernet0/2
 description SERVER2
 switchport access vlan 200
 switchport mode access
 media-type rj45
 negotiation auto

Rogue DHCP Server:

ip dhcp pool ROGUE
 network 192.168.1.0 255.255.255.0
 default-router 192.168.1.3
!
interface GigabitEthernet0/1
 ip address 192.168.1.3 255.255.255.0
 duplex auto
 speed auto
 media-type rj45

To configure DHCP Snooping on both the Left and Right switches, you’ll implement the following lines:

Left:

ip dhcp snooping vlan 100
ip dhcp snooping
!
Interface GigabitEthernet0/2
ip dhcp snooping trust

Right:

ip dhcp snooping vlan 100
ip dhcp snooping
!
Interface GigabitEthernet0/1
ip dhcp snooping trust

On the routers, I’ve also configured the following line:

ip dhcp relay information trust-all

This will ensure a fully working DHCP solution with DHCP snooping using Cisco switches and routers. The last configuration line will need some explaining:

By default, Cisco switches will include relay information, also called DHCP Option 82. Once a Cisco switch receives a DHCP message from a client, it will include details of where the request came from, in the form of a Circuit ID and a Remote ID, where the Circuit ID is the actual port from which the request came from, and the Remote ID contains the MAC address of the switch. This information is useful, so other switches in the broadcast domain know if a DHCP message is meant for them to process or not, by looking first at the Remote ID, containing the Switch’s MAC address.

If the above line is not present on the Router acting as a DHCP server, DHCP leases will not be given. In addition to the standard operation of Option 82 messages, the Cisco implementation of a DHCP server does an additional check. All Option 82 messages contain a field named GIADDR. In this field, the IP address of a relay agent is stored when it is being used. This relay agent is needed when you have a DHCP server outside of the (V)LAN. In our setup, we’re staying in the local LAN, so we’re not using a relay agent. If a Cisco DHCP server sees that this address is not being used, it will not accept the request. When using a ‘debug ip dhcp packets’, this will look like the following:

*Oct 15 19:47:36.211: DHCPD: inconsistent relay information.
*Oct 15 19:47:36.211: DHCPD: relay information option exists, but giaddr is zero.

Coming to the conclusion of this short diversion, if you use the command ‘ip dhcp relay information trust-all’, the Cisco DHCP server will accept packets which contain Option 82 information where the GIADDR field is empty. Another way around this would be to disable the use of Option 82 on the DHCP Snooping switch with the command ‘no ip dhcp snooping information option’. I would suggest against this though, since having Option 82 information is beneficial to your network’s efficiency.

Finally, to show that DHCP snooping is enabled and is turned on, use the following command:

Left#show ip dhcp snooping 
Switch DHCP snooping is enabled
Switch DHCP gleaning is disabled
DHCP snooping is configured on following VLANs:
100
DHCP snooping is operational on following VLANs:
100
DHCP snooping is configured on the following L3 Interfaces:

Insertion of option 82 is enabled
   circuit-id default format: vlan-mod-port
   remote-id: fa16.3ead.1a03 (MAC)
Option 82 on untrusted port is not allowed
Verification of hwaddr field is enabled
Verification of giaddr field is enabled
DHCP snooping trust/rate is configured on the following Interfaces:

Interface                  Trusted    Allow option    Rate limit (pps)
-----------------------    -------    ------------    ----------------   
GigabitEthernet0/2         yes        yes             unlimited
  Custom circuit-ids:

Confirming DHCP Snooping operation

Now that we have everything set up, let’s take a look at what happens when we request an ip address. For the clients, I use the embedded Ubuntu Server images present within Cisco VIRL. They have a basic setup, for which the IP address should first be cleared:

sudo ifconfig eth1 0.0.0.0
cisco@server-1:~$ ifconfig eth1
eth1 Link encap:Ethernet HWaddr fa:16:3e:5d:4e:40 
 inet6 addr: fe80::f816:3eff:fe5d:4e40/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:3485 errors:0 dropped:1025 overruns:0 frame:0
 TX packets:152 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:256677 (256.6 KB) TX bytes:41196 (41.1 KB

As seen, there isn’t an IPv4 address present now. Let’s request a lease:

cisco@server-1:~$ sudo dhclient eth1
cisco@server-1:~$

You won’t see a “succesful” message, only another terminal line. If you do a ifconfig again:

 cisco@server-1:~$ ifconfig eth1
eth1 Link encap:Ethernet HWaddr fa:16:3e:5d:4e:40 
 inet addr:192.168.1.2 Bcast:192.168.1.255 Mask:255.255.255.0
 inet6 addr: fe80::f816:3eff:fe5d:4e40/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:3565 errors:0 dropped:1025 overruns:0 frame:0
 TX packets:155 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:262827 (262.8 KB) TX bytes:41622 (41.6 KB)

Now we have an IP address. We can verify this on the ‘Left’ Switch by looking at the dhcp snooping binding table:

Left#show ip dhcp snooping binding 
MacAddress IpAddress Lease(sec) Type VLAN Interface
------------------ --------------- ---------- ------------- ---- --------------------
FA:16:3E:5D:4E:40 192.168.1.2 235 dhcp-snooping 100 GigabitEthernet0/1
Total number of bindings: 1

The following debug output, with some omitted parts will give insight into how the switch processes the complete DHCP process:

*Oct 15 20:33:11.212: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/1)
*Oct 15 20:33:11.212: DHCP_SNOOPING: process new DHCP packet, message type: DHCPDISCOVER, input interface: Gi0/1, MAC da: ffff.ffff.ffff, MAC sa: fa16.3e5d.4e40, IP da: 255.255.255.255, IP sa: 0.0.0.0, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3e5d.4e40
*Oct 15 20:33:11.213: DHCP_SNOOPING: message type : DHCPDISCOVER DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3e5d.4e40
*Oct 15 20:33:11.213: DHCP_SNOOPING: add relay information option.
*Oct 15 20:33:11.213: DHCP_SNOOPING_SW: encoding opt82 cid in vlan-mod-port format
*Oct 15 20:33:11.213: DHCP_SNOOPING_SW: Encoding opt82 RID in MAC address format
*Oct 15 20:33:11.214: DHCP_SNOOPING_SW: bridge packet get invalid mat entry: FFFF.FFFF.FFFF, packet is flooded to ingress VLAN: (100)
*Oct 15 20:33:11.214: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/2, vlan 100.

*Oct 15 20:33:13.224: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/2)
*Oct 15 20:33:13.228: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Oct 15 20:33:13.228: DHCP_SNOOPING: process new DHCP packet, message type: DHCPOFFER, input interface: Gi0/2, MAC da: fa16.3e5d.4e40, MAC sa: fa16.3e1d.38c2, IP da: 192.168.1.2, IP sa: 192.168.1.1, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3e5d.4e40
*Oct 15 20:33:13.228: DHCP_SNOOPING: message type : DHCPOFFER DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3e5d.4e40
*Oct 15 20:33:13.228: DHCP_SNOOPING: remove relay information option.
*Oct 15 20:33:13.229: DHCP_SNOOPING: direct forward dhcp replyto output port: GigabitEthernet0/1.

*Oct 15 20:33:13.229: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/1)
*Oct 15 20:33:13.230: DHCP_SNOOPING: process new DHCP packet, message type: DHCPREQUEST, input interface: Gi0/1, MAC da: ffff.ffff.ffff, MAC sa: fa16.3e5d.4e40, IP da: 255.255.255.255, IP sa: 0.0.0.0, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3e5d.4e40
*Oct 15 20:33:13.230: DHCP_SNOOPING: message type : DHCPREQUEST DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3e5d.4e40
*Oct 15 20:33:13.230: DHCP_SNOOPING: add relay information option.
*Oct 15 20:33:13.231: DHCP_SNOOPING_SW: encoding opt82 cid in vlan-mod-port format
*Oct 15 20:33:13.231: DHCP_SNOOPING_SW: Encoding opt82 RID in MAC address format
*Oct 15 20:33:13.232: DHCP_SNOOPING_SW: bridge packet get invalid mat entry: FFFF.FFFF.FFFF, packet is flooded to ingress VLAN: (100)
*Oct 15 20:33:13.232: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/2, vlan 100.

*Oct 15 20:33:13.233: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/2)
*Oct 15 20:33:13.237: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Oct 15 20:33:13.237: DHCP_SNOOPING: process new DHCP packet, message type: DHCPACK, input interface: Gi0/2, MAC da: fa16.3e5d.4e40, MAC sa: fa16.3e1d.38c2, IP da: 192.168.1.2, IP sa: 192.168.1.1, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3e5d.4e40
*Oct 15 20:33:13.237: DHCP_SNOOPING: message type : DHCPACK DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3e5d.4e40
*Oct 15 20:33:13.237: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Oct 15 20:33:13.237: DHCP_SNOOPING: remove relay information option.
*Oct 15 20:33:13.237: DHCP_SNOOPING: direct forward dhcp replyto output port: GigabitEthernet0/1.

I have separated the output with an empty line for each new packet that has been processed, for clarity. There are a few things worth noticing: firstly the DHCP steps Discover, Offer, Request and Acknowledge. Secondly, I’ve marked one sentence stating that the packet has been sent to port Gi0/2, even though the preceding line states that the packet will be flooded to VLAN 100. Gi0/2 has been marked as a trusted port, so the DHCP packets destined for the DHCP server (Discover and Request), will only be sent out of Gi0/2.

To be entirely sure that it is not sent to any other port, witness the following example:

I’ve configured port Gi1/0 on the ‘Left’ Switch as a trusted port. This is the port towards the Spoofed PC. Watch what happens when I now request an IP address from PC1:

cisco@server-1:~$ sudo dhclient eth1

Debug output from ‘Left’:

*Oct 15 20:57:27.311: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/2, vlan 100.
*Oct 15 20:57:27.311: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet1/0, vlan 100.

Tcpdump output from Spoofed PC1:

cisco@server-3:~$ sudo tcpdump -i eth1 -nne port 67 or port 68
[sudo] password for cisco: 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
20:58:34.522489 fa:16:3e:5d:4e:40 > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 337: 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from fa:16:3e:5d:4e:40, length 295
20:58:36.548144 fa:16:3e:5d:4e:40 > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 343: 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from fa:16:3e:5d:4e:40, length 301
^C
2 packets captured
2 packets received by filter
0 packets dropped by kernel

So we know that when we configure a port as trusted, that packets will get forwarded to those ports. Now let’s see what happens when we remove the trust:

cisco@server-1:~$ sudo dhclient eth1

Debug output from ‘Left’:

*Oct 15 21:07:30.462: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/2, vlan 100.

Tcpdump output from ‘Spoofed PC1’:

cisco@server-3:~$ sudo tcpdump -i eth1 -nne port 67 or 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
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel

We see no more broadcast packets on ‘Spoofed PC1’. A clear result that packets are only forwarded to those ports that are configured as trusted.

Trying to interfere with the Rogue DHCP server

We know now that when we do not configure an interface as being trusted, DHCP DISCOVER packets will not be forwarded, thus a DHCP server will never receive the initial DHCP packet. Let’s explore what happens when we configure the interface towards the Rogue DHCP server as trusted as well.

Left(config)#int gi0/3
Left(config-if)#ip dhcp snooping trust

If we request an IP address from PC1, the following output can be seen on the ‘Left’ switch (some part omitted):

*Jan 18 19:41:12.118: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/1)
*Jan 18 19:41:12.118: DHCP_SNOOPING: process new DHCP packet, message type: DHCPDISCOVER, input interface: Gi0/1, MAC da: ffff.ffff.ffff, MAC sa: fa16.3eba.ff2c, IP da: 255.255.255.255, IP sa: 0.0.0.0, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:41:12.118: DHCP_SNOOPING: message type : DHCPDISCOVER DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:41:12.118: DHCP_SNOOPING: add relay information option.
*Jan 18 19:41:12.119: DHCP_SNOOPING_SW: encoding opt82 cid in vlan-mod-port format
*Jan 18 19:41:12.119: DHCP_SNOOPING_SW: Encoding opt82 RID in MAC address format
*Jan 18 19:41:12.120: DHCP_SNOOPING_SW: bridge packet get invalid mat entry: FFFF.FFFF.FFFF, packet is flooded to ingress VLAN: (100)
*Jan 18 19:41:12.120: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/2, vlan 100.
*Jan 18 19:41:12.121: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/3, vlan 100.
*Jan 18 19:41:14.122: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/2)
*Jan 18 19:41:14.126: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Jan 18 19:41:14.126: DHCP_SNOOPING: process new DHCP packet, message type: DHCPOFFER, input interface: Gi0/2, MAC da: fa16.3eba.ff2c, MAC sa: fa16.3e23.f458, IP da: 192.168.1.2, IP sa: 192.168.1.1, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:41:14.126: DHCP_SNOOPING: message type : DHCPOFFER DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:41:14.126: DHCP_SNOOPING: remove relay information option.
*Jan 18 19:41:14.127: DHCP_SNOOPING: direct forward dhcp replyto output port: GigabitEthernet0/1.
*Jan 18 19:41:14.130: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Jan 18 19:41:14.130: DHCP_SNOOPING: process new DHCP packet, message type: DHCPOFFER, input interface: Gi0/3, MAC da: fa16.3eba.ff2c, MAC sa: fa16.3e16.2a8f, IP da: 192.168.1.2, IP sa: 192.168.1.3, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:41:14.130: DHCP_SNOOPING: message type : DHCPOFFER DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:41:14.130: DHCP_SNOOPING: remove relay information option.
*Jan 18 19:41:14.131: DHCP_SNOOPING: direct forward dhcp replyto output port: GigabitEthernet0/1.
*Jan 18 19:41:14.131: DHCP_SNOOPING: process new DHCP packet, message type: DHCPREQUEST, input interface: Gi0/1, MAC da: ffff.ffff.ffff, MAC sa: fa16.3eba.ff2c, IP da: 255.255.255.255, IP sa: 0.0.0.0, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:41:14.131: DHCP_SNOOPING: message type : DHCPREQUEST DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:41:14.131: DHCP_SNOOPING: add relay information option.
*Jan 18 19:41:14.131: DHCP_SNOOPING_SW: encoding opt82 cid in vlan-mod-port format
*Jan 18 19:41:14.131: DHCP_SNOOPING_SW: Encoding opt82 RID in MAC address format
*Jan 18 19:41:14.132: DHCP_SNOOPING_SW: bridge packet get invalid mat entry: FFFF.FFFF.FFFF, packet is flooded to ingress VLAN: (100)
*Jan 18 19:41:14.132: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/2, vlan 100.
*Jan 18 19:41:14.133: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/3, vlan 100.
*Jan 18 19:41:14.135: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/2)
*Jan 18 19:41:14.138: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Jan 18 19:41:14.138: DHCP_SNOOPING: process new DHCP packet, message type: DHCPACK, input interface: Gi0/2, MAC da: fa16.3eba.ff2c, MAC sa: fa16.3e23.f458, IP da: 192.168.1.2, IP sa: 192.168.1.1, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:41:14.138: DHCP_SNOOPING: message type : DHCPACK DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:41:14.138: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Jan 18 19:41:14.138: DHCP_SNOOPING: remove relay information option.
*Jan 18 19:41:14.138: DHCP_SNOOPING: direct forward dhcp replyto output port: GigabitEthernet0/1.

The following happens:

  1. PC1 sends an DHCP DISCOVER
  2. Both the Rogue and legitimate DHCP Servers send an DHCP OFFER
  3. Since the legitimate DHCP server sends the DHCP OFFER first, PC1 gets it first in this case
  4. PC1 responds with an DHCP REQUEST to the first DHCP OFFER from the legitimate DHCP server
  5. The legitimate DHCP Server sends an DHCP ACK

Since the Rogue DHCP Server never got the DHCP REQUEST from PC1, it stopped communicating further.

With Cisco VIRL you can adjust the interconnections of virtual nodes to emulate latency and packet loss. I’ve adjusted the link from the ‘Left’ switch towards the legitimate DHCP server to have a latency of 10 ms (milliseconds). Now the output looks like this:

*Jan 18 19:49:32.159: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/1)
*Jan 18 19:49:32.159: DHCP_SNOOPING: process new DHCP packet, message type: DHCPDISCOVER, input interface: Gi0/1, MAC da: ffff.ffff.ffff, MAC sa: fa16.3eba.ff2c, IP da: 255.255.255.255, IP sa: 0.0.0.0, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:49:32.159: DHCP_SNOOPING: message type : DHCPDISCOVER DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:49:32.160: DHCP_SNOOPING: add relay information option.
*Jan 18 19:49:32.160: DHCP_SNOOPING_SW: encoding opt82 cid in vlan-mod-port format
*Jan 18 19:49:32.160: DHCP_SNOOPING_SW: Encoding opt82 RID in MAC address format
*Jan 18 19:49:32.161: DHCP_SNOOPING_SW: bridge packet get invalid mat entry: FFFF.FFFF.FFFF, packet is flooded to ingress VLAN: (100)
*Jan 18 19:49:32.161: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/2, vlan 100.
*Jan 18 19:49:32.162: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/3, vlan 100.
*Jan 18 19:49:34.161: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/3)
*Jan 18 19:49:34.162: DHCP_SNOOPING: binary dump of option 82, length: 20 data:
*Jan 18 19:49:34.164: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Jan 18 19:49:34.164: DHCP_SNOOPING: process new DHCP packet, message type: DHCPOFFER, input interface: Gi0/3, MAC da: fa16.3eba.ff2c, MAC sa: fa16.3e16.2a8f, IP da: 192.168.1.2, IP sa: 192.168.1.3, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:49:34.165: DHCP_SNOOPING: message type : DHCPOFFER DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:49:34.165: DHCP_SNOOPING: remove relay information option.
*Jan 18 19:49:34.165: DHCP_SNOOPING: direct forward dhcp replyto output port: GigabitEthernet0/1.
*Jan 18 19:49:34.167: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/1)
*Jan 18 19:49:34.167: DHCP_SNOOPING: process new DHCP packet, message type: DHCPREQUEST, input interface: Gi0/1, MAC da: ffff.ffff.ffff, MAC sa: fa16.3eba.ff2c, IP da: 255.255.255.255, IP sa: 0.0.0.0, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:49:34.167: DHCP_SNOOPING: message type : DHCPREQUEST DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 0.0.0.0, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:49:34.167: DHCP_SNOOPING: add relay information option.
*Jan 18 19:49:34.167: DHCP_SNOOPING_SW: encoding opt82 cid in vlan-mod-port format
*Jan 18 19:49:34.168: DHCP_SNOOPING_SW: Encoding opt82 RID in MAC address format
*Jan 18 19:49:34.169: DHCP_SNOOPING_SW: bridge packet get invalid mat entry: FFFF.FFFF.FFFF, packet is flooded to ingress VLAN: (100)
*Jan 18 19:49:34.169: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/2, vlan 100.
*Jan 18 19:49:34.170: DHCP_SNOOPING_SW: bridge packet send packet to port: GigabitEthernet0/3, vlan 100.
*Jan 18 19:49:34.171: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/3)
*Jan 18 19:49:34.175: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Jan 18 19:49:34.175: DHCP_SNOOPING: process new DHCP packet, message type: DHCPACK, input interface: Gi0/3, MAC da: fa16.3eba.ff2c, MAC sa: fa16.3e16.2a8f, IP da: 192.168.1.2, IP sa: 192.168.1.3, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:49:34.175: DHCP_SNOOPING: message type : DHCPACK DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:49:34.175: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Jan 18 19:49:34.175: DHCP_SNOOPING: remove relay information option.
*Jan 18 19:49:34.175: DHCP_SNOOPING: direct forward dhcp replyto output port: GigabitEthernet0/1.
*Jan 18 19:49:34.182: DHCP_SNOOPING: received new DHCP packet from input interface (GigabitEthernet0/2)
*Jan 18 19:49:34.185: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Jan 18 19:49:34.185: DHCP_SNOOPING: process new DHCP packet, message type: DHCPOFFER, input interface: Gi0/2, MAC da: fa16.3eba.ff2c, MAC sa: fa16.3e23.f458, IP da: 192.168.1.2, IP sa: 192.168.1.1, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:49:34.185: DHCP_SNOOPING: message type : DHCPOFFER DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.2, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3eba.ff2c
*Jan 18 19:49:34.186: DHCP_SNOOPING: remove relay information option.
*Jan 18 19:49:34.186: DHCP_SNOOPING: direct forward dhcp replyto output port: GigabitEthernet0/1.

The proces is much the same, except that we now see the DHCP OFFER from the legitimate DHCP server all the way at the bottom!

This experiment shows that requesting an DHCP address with multiple DHCP servers on the same segment result in a situation where the quickest DHCP server often will be the one to get to lease the IP address.

Experimenting with MAC address spoofing

We will set up ‘Spoofed PC1’ with the same MAC address as ‘PC1’ to see what happens when we request an IP address from ‘Spoofed PC1’.

cisco@server-3:~$ sudo ifconfig eth1 hw ether fa:16:3e:df:a4:4c

First let’s see what the current IP address of PC1 is by looking at the binding table:

Left#sh ip dhcp snooping binding
MacAddress IpAddress Lease(sec) Type VLAN Interface
------------------ --------------- ---------- ------------- ---- --------------------
FA:16:3E:DF:A4:4C 192.168.1.4 295 dhcp-snooping 100 GigabitEthernet0/1
Total number of bindings: 1

This shows IP address 192.168.1.4 give out over interface Gi0/1. When we now request an IP address from Spoofed PC1, the following will be shown:

Left#sh ip dhcp snooping binding
MacAddress IpAddress Lease(sec) Type VLAN Interface
------------------ --------------- ---------- ------------- ---- --------------------
FA:16:3E:DF:A4:4C 192.168.1.4 294 dhcp-snooping 100 GigabitEthernet1/0
Total number of bindings: 1

The IP address remained the same, but the interface is now changed to Gi1/0, the one going to Spoofed PC1. The following DHCP snooping debugging output shows what occured:

*Jan 18 17:40:25.471: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Jan 18 17:40:25.471: DHCP_SNOOPING: process new DHCP packet, message type: DHCPACK, input interface: Gi0/2, MAC da: fa16.3edf.a44c, MAC sa: fa16.3e08.096a, IP da: 192.168.1.4, IP sa: 192.168.1.1, DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.4, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3edf.a44c
*Jan 18 17:40:25.471: DHCP_SNOOPING: message type : DHCPACK DHCP ciaddr: 0.0.0.0, DHCP yiaddr: 192.168.1.4, DHCP siaddr: 0.0.0.0, DHCP giaddr: 0.0.0.0, DHCP chaddr: fa16.3edf.a44c
*Jan 18 17:40:25.472: DHCP_SNOOPING_SW: opt82 data indicates local packet
*Jan 18 17:40:25.472: DHCP_SNOOPING: remove relay information option.
*Jan 18 17:40:25.472: DHCP_SNOOPING: direct forward dhcp reply to output port: GigabitEthernet1/0

It’s interesting to see that packets are still incoming from PC1, but the DHCP snooping binding table will not be updated with the information from PC1. It will keep holding on to the information from the DHCP request of Spoofed PC1.

What happens when we release an IP address from a spoofed MAC address? The IP address has now been recorded as belonging to Gi1/0, the Spoofed PC1. If we now send a release from PC1, the following output can be witnessed:

*Jan 18 17:50:16.462: %DHCP_SNOOPING-5-DHCP_SNOOPING_FAKE_INTERFACE: DHCP_SNOOPING drop message with mismatched source interface, the binding is not updated, message type: DHCPRELEASE, MAC sa: fa16.3edf.a44c

We can see that the lease is still active, by looking at the output from our DHCP Server:

Router#sh ip dhcp binding 
Bindings from all pools not associated with VRF:
IP address Client-ID/ Lease expiration Type
 Hardware address/
 User name
192.168.1.5 fa16.3edf.a44c Jan 18 2018 05:56 PM Automatic

You might notice that this time the IP address 192.168.1.5 is being used. This is because I’ve been playing around with requesting and releasing IP addresses.

That’s it for the DHCP Snooping explanation. Thanks for the read and I hope you learned something by doing so!