IPv6 Source Guard is one of the IPv6 FHS (First Hop Security) features. It filters inbound traffic on L2 switch ports that are not in the IPv6 binding table. The binding table stores the following information:
- IPv6 address
- MAC address
- Interface ID
Source Guard only looks at information found in the binding table, and it doesn’t fill the binding table. You need another feature like ND inspection or IPv6 snooping to do this. You can fill the binding table with information from:
When source guard denies traffic because it is not found in the binding table, it notifies the IPv6 address glean feature. This feature can query a DHCP server or uses IPv6 ND (Neighbor Discovery) to find the missing information, if possible.
In this lesson, we will take a look at Source Guard in action. This is the topology I use:
Let me explain this topology:
- H1 is a legitimate host and receives an IPv6 address through DHCP.
- H2 is an attacker that tries to perform a DoS attack on S1.
- R1 is our DHCP server.
- S1 is a server that is under attack by H2.
- SW1 is where we configure IPv6 Source Guard.
Want to take a look for yourself? Here you will find the startup configuration of each device.
hostname H1 ! interface FastEthernet0/0 ipv6 address dhcp ipv6 enable ! end
hostname R1 ! ipv6 unicast-routing ipv6 cef ipv6 dhcp pool MY_POOL address prefix 2001:DB8:0:12::/64 ! interface FastEthernet0/0 ipv6 address 2001:DB8:0:12::F/64 ipv6 dhcp server MY_POOL ! end
hostname S1 ! ipv6 unicast-routing ipv6 cef ! interface FastEthernet0/0 ipv6 address 2001:DB8:0:4::4/64 ! ipv6 route ::/0 2001:DB8:0:4::F ! end
Without Source Guard
Let’s get started. In our first scenario, I will show you how H2 can attack S1 when we don’t use Source Guard.
Let’s check if R1 has assigned an IPv6 address through DHCP to H1:
R1#show ipv6 dhcp binding Client: FE80::217:5AFF:FEED:7AF0 DUID: 0003000100175AED7AF0 Username : unassigned IA NA: IA ID 0x00030001, T1 43200, T2 69120 Address: 2001:DB8:0:12:FC57:49F8:6AA5:1448 preferred lifetime 86400, valid lifetime 172800 expires at Aug 08 2018 01:45 PM (172342 seconds)
H1#show ipv6 interface brief | include 2001 2001:DB8:0:12:FC57:49F8:6AA5:1448
We verify that H1 has an IPv6 address. Let’s make sure it can reach S1:
H1#ping 2001:DB8:0:4::4 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 2001:DB8:0:4::4, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 0/0/0 ms
Let’s take a look at S1:
S1#show ipv6 neighbors IPv6 Address Age Link-layer Addr State Interface FE80::21D:A1FF:FE8B:36D1 6 001d.a18b.36d1 STALE Fa0/0 2001:DB8:0:4::F 6 001d.a18b.36d1 STALE Fa0/0
S1 knows two neighbors with the same MAC address. Both addresses belong to R1.
Let’s see how we can attack S1 from H2. On H2, I enable IPv6 so that I get a link-local address and so that H2 knows how to get to other subnets through R1. I also configure a couple of fake IPv6 addresses that belong to the 2001:DB8:0:4::/64 subnet:
H2(config)#interface FastEthernet 0/0 H2(config-if)#ipv6 enable H2(config-if)#ipv6 address 2001:DB8:0:4::100/128 H2(config-if)#ipv6 address 2001:DB8:0:4::101/128 H2(config-if)#ipv6 address 2001:DB8:0:4::102/128 H2(config-if)#ipv6 address 2001:DB8:0:4::103/128
Let’s send a couple of pings from H2 to S1 from each fake IPv6 address:
H2#ping 2001:DB8:0:4::4 source 2001:DB8:0:4::100 timeout 0 repeat 1 H2#ping 2001:DB8:0:4::4 source 2001:DB8:0:4::101 timeout 0 repeat 1 H2#ping 2001:DB8:0:4::4 source 2001:DB8:0:4::102 timeout 0 repeat 1 H2#ping 2001:DB8:0:4::4 source 2001:DB8:0:4::103 timeout 0 repeat 1
You have to be quick but when you look at the IPv6 neighbors of S1, you see these entries:
S1#show ipv6 neighbors IPv6 Address Age Link-layer Addr State Interface FE80::21D:A1FF:FE8B:36D1 0 001d.a18b.36d1 REACH Fa0/0 2001:DB8:0:4::F 3 001d.a18b.36d1 STALE Fa0/0 2001:DB8:0:4::101 0 - INCMP Fa0/0 2001:DB8:0:4::100 0 - INCMP Fa0/0 2001:DB8:0:4::102 0 - INCMP Fa0/0 2001:DB8:0:4::103 0 - INCMP Fa0/0
S1 wants to know the MAC addresses of these IPv6 addresses but since nobody on the 2001:DB8:0:4::/64 subnet answers, it never gets a reply.
When S1 does not get a reply it deletes the entry in a few seconds. My four pings won’t do any harm but a script that generates random IPv6 addresses non-stop will.
With Source Guard
Let’s see if we can put a stop to this. Before I can play with Source Guard, I need to have a binding table with some entries. A quick way to do this is to enable IPv6 snooping.
IPv6 snooping tracks DHCP and ND packets so it’s a nice way to get entries in our binding table. Let’s create a snooping policy:
SW1(config)#ipv6 snooping policy SNOOPING SW1(config-ipv6-snooping)#security-level glean
I change the security level to glean because I only want to use snooping to get information into the binding table. If you don’t change the policy, IPv6 snooping will also activate RA guard.
Let’s activate the snooping policy on all interfaces:
SW1(config)#interface range GigabitEthernet 0/1 - 3 SW1(config-if-range)#ipv6 snooping attach-policy SNOOPING
Let’s clear the IPv6 address on H1 so that IPv6 snooping can see the DHCP packets:
H1#clear ipv6 dhcp client FastEthernet 0/0
SW1 now has some entries in the binding table:
SW1#show ipv6 neighbors binding Binding Table has 3 entries, 3 dynamic Codes: L - Local, S - Static, ND - Neighbor Discovery, DH - DHCP, PKT - Other Packet, API - API created Preflevel flags (prlvl): 0001:MAC and LLA match 0002:Orig trunk 0004:Orig access 0008:Orig trusted trunk 0010:Orig trusted access 0020:DHCP assigned 0040:Cga authenticated 0080:Cert authenticated 0100:Statically assigned IPv6 address Link-Layer addr Interface vlan prlvl age state Time left ND FE80::21D:A1FF:FE8B:36D0 001D.A18B.36D0 Gi0/1 1 0005 1s REACHABLE 311 s ND FE80::217:5AFF:FEED:7AF0 0017.5AED.7AF0 Gi0/2 1 0005 1s REACHABLE 304 s DH 2001:DB8:0:12:20A8:D970:FA26:4403 0017.5AED.7AF0 Gi0/2 1 0024 7s REACHABLE 298 s(164185 s)
We see two neighbor discovery entries and one DHCP entry. We now have everything we need to test Source Guard.