IPv6 ND Inspection

IPv6 ND Inspection is one of the IPv6 first-hop security features. It creates a binding table that is based on NS (Neighbor Solicitation) and NA (Neighbor Advertisement) messages. The switch then uses this table to check any future NS/NA messages. When the IPv6-LLA combination does not match, it drops the message. This only applies to NS/NA messages, it doesn’t drop any actual data packets that have a spoofed IPv6 or MAC address.

Configuration

To demonstrate ND inspection, we’ll use the following topology:

Ipv6 Nd Inspection Lab Topology

H1 and H2 are two legitimate devices with IPv6 addresses. I will use R3 to spoof an IPv6 address, SW1 is where we configure ND inspection.

Enabling this is very simple if you want to get started. You can do it with a single command:

SW1(config)#interface range gi0/1 - 2
SW1(config-if-range)#ipv6 nd inspection

Let’s send a ping from R1 to R2 to generate some ND/NA messages:

R1#ping 2001:DB8:0:12::2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 2001:DB8:0:12::2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 0/0/4 ms

Now let’s take a look at SW1:

SW1#show ipv6 neighbors binding 
Binding Table has 4 entries, 4 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    4s  REACHABLE  301 s            
ND  FE80::217:5AFF:FEED:7AF0                0017.5AED.7AF0  Gi0/2        1  0005    4s  REACHABLE  305 s            
ND  2001:DB8:0:12::2                        0017.5AED.7AF0  Gi0/2        1  0005   15s  REACHABLE  288 s            
ND  2001:DB8:0:12::1                        001D.A18B.36D0  Gi0/1        1  0005   10s  REACHABLE  301 s

Above, we see four entries in the binding table. Two for R1 and two for R2. The binding table got populated by ND, you can see that the binding table can also be populated by other options like DHCP.

Let’s see what happens when we try to spoof an IPv6 address of R2 on R3. I’ll disable DAD (Duplicate Address Detection) first:

R3(config-if)#ipv6 nd dad attempts 0

Now we’ll copy the IPv6 link-local address of R2 to R3:

R3(config)#interface FastEthernet 0/0
R3(config-if)#ipv6 address FE80::217:5AFF:FEED:7AF0 link-local

Let’s do a ping from the spoofed link-local address of R3 to the link-local address of R1 to trigger some ND/NA messages:

R3#ping FE80::21D:A1FF:FE8B:36D0 source FE80::217:5AFF:FEED:7AF0 repeat 1

This is what we get on SW1:

SW1#
%SISF-4-PAK_DROP: Message dropped A=FE80::217:5AFF:FEED:7AF0 G=- V=123 I=Gi0/3 P=NDP::RA Reason=More trusted entry exists

The switch drops the ND from R3 since we already have an entry from R2 in our binding table. The binding table works with a “first come, first served” logic. Since we already have an entry from R2, we don’t accept the ND from R3 for the spoofed address.

Static Binding

If you want, you could make the spoofed address of R3 work. Let’s take another look at the binding table:

SW1#show ipv6 neighbors binding | begin Pref 
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

The binding table has different preference levels. The lowest preference level is a MAC and LLA match. The highest preference level is a static binding. Since the binding table is used for some other features, understanding it is important. Let me show you how to create a static binding for R3. Here’s the MAC address of R3:

R3#show interfaces FastEthernet 0/0 | include bia
  Hardware is MV96340 Ethernet, address is 0016.c7be.0ec8 (bia 0016.c7be.0ec8)

Let’s create a static binding:

SW1(config)#ipv6 neighbor binding vlan 1 FE80::217:5AFF:FEED:7AF0 interface GigabitEthernet 0/3 0016.c7be.0ec8

This shows up in our binding table:

SW1#show ipv6 neighbors binding 
Binding Table has 4 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    6mn STALE      87780 s          
S   FE80::217:5AFF:FEED:7AF0                0016.C7BE.0EC8  Gi0/3        1  0100    2s  REACHABLE  310 s            
ND  2001:DB8:0:12::2                        0017.5AED.7AF0  Gi0/2        1  0005   10mn STALE      88122 s          
ND  2001:DB8:0:12::1                        001D.A18B.36D0  Gi0/1        1  0005   10mn STALE      89190 s

Above, you can see the static binding. ND/NA messages from R3 are now accepted:

R3#ping FE80::21D:A1FF:FE8B:36D0 source FE80::217:5AFF:FEED:7AF0 repeat 1
Output Interface: FastEthernet0/0
Type escape sequence to abort.
Sending 1, 100-byte ICMP Echos to FE80::21D:A1FF:FE8B:36D0, timeout is 2 seconds:
Packet sent with a source address of FE80::217:5AFF:FEED:7AF0%FastEthernet0/0
!
Success rate is 100 percent (1/1), round-trip min/avg/max = 0/0/0 ms

Let’s get rid of R3 and clean up the policy before we continue:

R3(config)#interface FastEthernet 0/0
R3(config-if)#shutdown
SW1(config)#ipv6 neighbor binding vlan 1 FE80::217:5AFF:FEED:7AF0 interface GigabitEthernet 0/3 0016.c7be.0ec8

Policies

So far, we activated ND inspection with a single command and it worked out of the box. You can also customize it with policies. Let’s create a policy and look at the different options:

SW1(config)#ipv6 nd inspection policy MY_POLICY
SW1(config-nd-inspection)#?
IPv6 NDP inspection policy configuration mode:
  default        Set a command to its defaults
  device-role    Sets the role of the device attached to the port
  drop-unsecure  drop unsecure (3971) messages
  exit           Exit from NDP inspection policy configuration mode
  limit          Specifies a limit
  no             Negate a command or set its defaults
  sec-level      Specifies a minimum sec-level
  tracking       Override default tracking behavior
  trusted-port   setup trusted port
  validate       specific validation

There are quite some options, let’s walk through them. We’ll start with device-role:

We're Sorry, Full Content Access is for Members Only...

If you like to keep on reading, Become a Member Now! Here is why:

  • Learn any CCNA, CCNP and CCIE R&S Topic. Explained As Simple As Possible.
  • Try for Just $1. The Best Dollar You've Ever Spent on Your Cisco Career!
  • Full Access to our 651 Lessons. More Lessons Added Every Week!
  • Content created by Rene Molenaar (CCIE #41726)

567 Sign Ups in the last 30 days

satisfaction-guaranteed
100% Satisfaction Guaranteed!
You may cancel your monthly membership at any time.
No Questions Asked!

Forum Replies

  1. Seems to be a typo:
    “R1 and R2 are two legitimate devices with IPv6 addresses. I will use R3 to spoof an IPv6 address, SW1 is where we configure ND inspection.”

    In the network diagram you have H1 and H2 instead of R1 and R2

  2. Hello Elias

    Thanks for pointing that out. I’ll let Rene know…

    Laz

Ask a question or join the discussion by visiting our Community Forum