In the previous blog post I explained and configured DHCP Snooping. This time I’ll configure both Dynamic ARP inspection and IP Source Guard. This is a logical follow up, because they share some attributes.
Both these technologies are part of the security toolbox for Layer 2 networks. They make use of the DHCP Snooping Binding Table, so that’s why I will be using our last topology to add on these two technologies.
I won’t be using the full topology this time. I will not be doing anything with the ‘Rogue DHCP Server’. The rest will be used to show how it fully works. This is the topology:
Dynamic ARP Inspection
As mentioned, I will be using the same configuration used in the post DHCP Snooping explained. While configuring, we’ll leave out bits of configuration to show how it works exactly.
This topology has the following properties:
- The middle ‘Router’ is the DHCP server.
- The ‘Left’ and ‘Right’ switches are DHCP snooping enabled and Dynamic ARP Inspection enabled.
First a bit of theory. If you have not yet done so, I recommend you to read through my blog post about DHCP Snooping, because using Dynamic ARP Inspection relies upon the DHCP Snooping Binding Table. The way this table operates, is explained in DHCP Snooping explained.
As with DHCP Snooping, a specific type of traffic (DHCP for DHCP Snooping and ARP for Dynamic ARP Inspection) is only allowed if the destination address you’re trying to reach, is listed in the DHCP Snooping table. An exception to this is your uplink, which you must explicity trust. This trust command differs in configuration between DHCP Snooping and Dynamic ARP Inspection, but the intention of the command is the same; to allow traffic which would otherwise be invalid.
What follows now is the basic connectivity configuration. This already includes the DHCP Snooping configuration, since this is a prerequisite for Dynamic ARP Inspection.
conf t 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
conf t vlan 100 ip dhcp snooping ip dhcp snooping 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 ip dhcp snooping trust
conf t vlan 200 ip dhcp snooping ip dhcp snooping 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 ip dhcp snooping trust ! interface GigabitEthernet0/2 description SERVER2 switchport access vlan 200 switchport mode access media-type rj45 negotiation auto
Now we’ll ensure that ‘PC1’, ‘Spoofed PC’ and ‘PC2’ receive an IP address from the DHCP server. Take note: the ‘Spoofed PC’ acts as a regular client, even though the name indicated differently. This is because we’re reusing the topology from the previous blog.
sudo ifconfig eth1 0.0.0.0 sudo dhclient eth1 cisco@server-1:~$ ifconfig eth1 | grep "inet addr" inet addr:192.168.1.2 Bcast:192.168.1.255 Mask:255.255.255.0
sudo ifconfig eth1 0.0.0.0 sudo dhclient eth1 cisco@server-3:~$ ifconfig eth1 | grep "inet addr" inet addr:192.168.1.3 Bcast:192.168.1.255 Mask:255.255.255.0
sudo ifconfig eth1 0.0.0.0 sudo dhclient eth1 cisco@server-2:~$ ifconfig eth1 | grep "inet addr" inet addr:192.168.2.2 Bcast:192.168.2.255 Mask:255.255.255.0
Now let’s first verify connectivity between ‘PC1’ <> ‘Spoofed PC’ and ‘PC1’ <> ‘PC2’.
cisco@server-1:~$ ping 192.168.1.3 PING 192.168.1.3 (192.168.1.3) 56(84) bytes of data. 64 bytes from 192.168.1.3: icmp_seq=1 ttl=64 time=0.895 ms 64 bytes from 192.168.1.3: icmp_seq=2 ttl=64 time=1.34 ms 64 bytes from 192.168.1.3: icmp_seq=3 ttl=64 time=1.18 ms ^C --- 192.168.1.3 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2001ms rtt min/avg/max/mdev = 0.895/1.141/1.341/0.187 ms cisco@server-1:~$ ping 192.168.2.2 PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data. 64 bytes from 192.168.2.2: icmp_seq=1 ttl=63 time=2.55 ms 64 bytes from 192.168.2.2: icmp_seq=2 ttl=63 time=2.43 ms 64 bytes from 192.168.2.2: icmp_seq=3 ttl=63 time=2.57 ms ^C --- 192.168.2.2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2001ms rtt min/avg/max/mdev = 2.435/2.520/2.572/0.073 ms
Since it is a ping, or more precise, an ICMP echo request and an ICMP echo reply, we know connectivity is working for all machines, so we only need to test this from PC1.
Now let’s configure the first part of Dynamic ARP Inspection and see what happens to this traffic. Based on what we’re going to test, only configuring Dynamic ARP Inspection on the switch ‘Left’ will suffice.
conf t ip arp inspection vlan 100
That’s it for enabling and configuring the use of Dynamic ARP Inspection for VLAN 100. As you might notice, in comparison to DHCP Snooping, you don’t need to enable it explicitly in global config with a separate command. You combine this with the VLAN statement.
To properly configure IP ARP Inspection, you will need to trust the uplink from the ‘Left’ switch towards the ‘Router’, or else any ARP’ing for addresses outside of the LAN will be denied, which will result in non-LAN traffic being stopped altogether. This is of course because the default gateway of the PC’s (the ‘Router’) will not be in the DHCP Snooping table and therefore be denied. This results in the PC’s not aquiring the ARP address of the ‘Router’ and in result won’t be able to reach traffic outside of the LAN.
To illustrate what happens if we don’t trust router facing interface, let’s see how our pings are holding up now:
cisco@server-1:~$ ping 192.168.2.2 PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data. From 192.168.1.2 icmp_seq=1 Destination Host Unreachable From 192.168.1.2 icmp_seq=2 Destination Host Unreachable From 192.168.1.2 icmp_seq=3 Destination Host Unreachable ^C --- 192.168.2.2 ping statistics --- 4 packets transmitted, 0 received, +3 errors, 100% packet loss, time 3014ms
The follow output shows the log from our ‘Left’ switch:
*Mar 7 18:22:21.717: %SW_DAI-4-DHCP_SNOOPING_DENY: 1 Invalid ARPs (Res) on Gi0/2, vlan 100.([fa16.3e2c.0bbd/192.168.1.1/fa16.3e4f.2f9f/192.168.1.3/18:22:21 UTC Wed Mar 7 2018]) *Mar 7 18:22:33.723: %SW_DAI-4-DHCP_SNOOPING_DENY: 1 Invalid ARPs (Res) on Gi0/2, vlan 100.([fa16.3e2c.0bbd/192.168.1.1/fa16.3e4f.2f9f/192.168.1.3/18:22:33 UTC Wed Mar 7 2018]) *Mar 7 18:22:34.723: %SW_DAI-4-DHCP_SNOOPING_DENY: 1 Invalid ARPs (Res) on Gi0/2, vlan 100.([fa16.3e2c.0bbd/192.168.1.1/fa16.3e4f.2f9f/192.168.1.3/18:22:34 UTC Wed Mar 7 2018]) *Mar 7 18:22:35.733: %SW_DAI-4-DHCP_SNOOPING_DENY: 1 Invalid ARPs (Res) on Gi0/2, vlan 100.([fa16.3e2c.0bbd/192.168.1.1/fa16.3e4f.2f9f/192.168.1.3/18:22:35 UTC Wed Mar 7 2018])
Notice that our ‘PC1’ will also not have an ARP entry for ‘PC2’:
cisco@server-1:~$ arp -n | grep 192.168.2.2 192.168.2.2 (incomplete) eth1
But since Dynamic ARP Inspection is only blocking ARP packets, we can simply restore our traffic flow by configuring a static ARP entry on ‘PC1’, as follows:
sudo arp -s 192.168.2.2 fa:16:3e:2c:0b:bd cisco@server-1:~$ arp -n | grep 192.168.2.2 192.168.2.2 ether fa:16:3e:2c:0b:bd CM eth1
And behold, we restored the traffic flow!
cisco@server-1:~$ ping 192.168.2.2 PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data. 64 bytes from 192.168.2.2: icmp_seq=1 ttl=63 time=2.57 ms 64 bytes from 192.168.2.2: icmp_seq=2 ttl=63 time=2.71 ms 64 bytes from 192.168.2.2: icmp_seq=3 ttl=63 time=2.30 ms 64 bytes from 192.168.2.2: icmp_seq=4 ttl=63 time=2.58 ms ^C --- 192.168.2.2 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3002ms rtt min/avg/max/mdev = 2.309/2.548/2.719/0.148 ms
In this case I’m using the MAC address of the router, since the router knows the way out of the LAN. In a normal functioning situation, the MAC address of the router would also be in the ARP table of ‘PC1’. So, as demonstrated, Dynamic ARP Inspection can easily be circumvented.
Static IP addresses with Dynamic ARP Inspection
Take note that it is not possible to use static IP addresses when you a basic Dynamic ARP Inspection configuration. This is ofcourse because you have not requested an IP address and therefore are not added to the DHCP Snooping Binding Table, which results in your ARP packets being blocked by Dynamic ARP Inspection.
Not being able to use static IP addresses might be a major drawback if you’re thinking about implementing this in your network.
To avoid this issue if you are using static IP addresses in your network, is to define access-lists and tell DAI to use these access-lists to ignore inspection for the content of the access-lists.
To demonstrate this, I’ve set an static IP address on ‘PC1’:
cisco@server-1:~$ sudo ifconfig eth1 192.168.1.10 netmask 255.255.255.0 cisco@server-1:~$ ifconfig eth1 | grep "inet addr" inet addr:192.168.1.10 Bcast:192.168.1.255 Mask:255.255.255.0
The pings towards 192.168.2.2 are not working anymore now, and the ‘Left’ switch will log the attempts. Let’s first create an access-list, defining what traffic needs to be ignored.
conf t arp access-list STATIC permit ip host 192.168.1.10 mac host fa16.3ea7.e993
This is not an ordinary access-list, but an ARP access-list. It works differently than a “normal” access-list by only being focussed on ARP traffic. We then have to tell DAI to use the ARP ACL with the following command:
ip arp inspection filter STATIC vlan 100
With the above rule, we have allowed a specific host with a combination of its IP and MAC address. The pings are once again working at this point.
You can also make the access-list a bit less restrictive in the following way:
conf t arp access-list STATIC permit ip 192.168.1.0 0.0.0.255 mac any
This will allow all IP addresses from the subnet 192.168.1.0/24, regardless of which MAC address they are using.
If you’re in a situation where you have some devices that can only operate with a static IP address, using an ARP ACL is the way forward.
IP Source Guard
Onwards with IP Source Guard! The reason IP Source Guard and Dynamic ARP Inspection are often used within the same sentence, is because they are both technologies that make use of the DHCP Snooping Binding Table. They are, however, very different from one another.
Whereas Dynamic ARP Inspection will filter ARP traffic, IP Source Guard will (as the name implies) filter traffic based on its source IP address. You will want to implement this if you want to counter source IP spoofing. This is when a malicious host will pretend to be a legitimate host by using the source IP address of the legitimate host.
IP Source Guard will block traffic where the source IP address does not match the MAC address in the DHCP Snooping Binding Table. It works on layer 2 of the OSI model and will dynamically create Port Access Control Lists (PACL’s), which are fancy words for saying: It creates ACL’s which are bound at a port level (interfaces) rather than at a protocol level (i.e. for routing packets). If IP Source Guard is active on a interface which has not yet received an IP address from DHCP, all traffic is dropped.
Let’s configure it! The most basic implementation, assuming you have already configured DHCP Snooping is as follows:
conf t interface GigabitEthernet0/1 ip verify source
That’s it! Now it’s active for this interface. It will check the DHCP Snooping binding table for an entry, and based on that allow or block traffic. The following output verifies the operation:
Left#sh run int gi0/1 Building configuration... Current configuration : 162 bytes ! interface GigabitEthernet0/1 switchport access vlan 100 switchport mode access media-type rj45 negotiation auto ip verify source end Left#sh ip dhcp snooping binding MacAddress IpAddress Lease(sec) Type VLAN Interface ------------------ --------------- ---------- ------------- ---- -------------------- FA:16:3E:A7:E9:93 192.168.1.2 141 dhcp-snooping 100 GigabitEthernet0/1 Left#sh ip verify source Interface Filter-type Filter-mode IP-address Mac-address Vlan --------- ----------- ----------- --------------- ----------------- ---- Gi0/1 ip active 192.168.1.2 100
We can see that it is active and running for 192.168.1.2 in VLAN 100. It got all that data from the DHCP Snooping Binding table.
I’ve configured the ‘Spoofed PC1’ with the same IP address as our legitimate host ‘PC1’. Before I spoofed the IP address on ‘Spoofed PC1’, connectivity from ‘PC1’ towards ‘PC2’ was working as it should. ARP entries on the router correlated to ‘PC1’ etcetera.
I configured the following on ‘Spoofed PC1’:
sudo ifconfig eth1 192.168.1.2 netmask 255.255.255.0 gateway 192.168.1.1
This will enable 192.168.1.2 on interface eth1. At that point, ‘PC1’ lost connection to ‘PC2’, even though the ARP entry on the router was still active. ‘Spoofed PC1’ basically took over the IP address.
Now watch what happens when we enable IP Source Guard on the interface facing ‘Spoofed PC1’:
Left#sh ip verify source Interface Filter-type Filter-mode IP-address Mac-address Vlan --------- ----------- ----------- --------------- ----------------- ---- Gi0/1 ip active 192.168.1.2 100 Gi1/0 ip active deny-all 100
Traffic coming from Gi1/0 is now blocked, because there is no correlation between interface and IP address from the information in the DHCP Snooping Binding Table.
If need be, you can statically assign IP addresses that will circumvent the IP Source Guard feature. Configure the following in global config:
Left(config)#ip source binding FA16.3EA7.E993 vlan 100 192.168.1.2 interface Gi0/1
With the command ‘show ip source binding’, you can see the effect this has:
Left#show ip source binding MacAddress IpAddress Lease(sec) Type VLAN Interface ------------------ --------------- ---------- ------------- ---- -------------------- FA:16:3E:A7:E9:93 192.168.1.2 infinite static 100 GigabitEthernet0/1
Traffic for this combination of IP and MAC will be allowed from the moment you set the static entry.
Thanks for reading, happy configuring!