Neighbor Discovery (ND) is the protocol (RFC) 4861 sums up in one sentence: "IPv6 nodes on the same link use Neighbor Discovery to discover each other's presence, to determine each other's link-layer addresses, to find routers, and to maintain reachability information about the paths to active neighbors" (RFC 4861, Abstract). It replaces the Address Resolution Protocol (ARP) and the Router Discovery and Redirect mechanisms of the IPv4 Internet Control Message Protocol (), and also handles Neighbor Unreachability Detection (NUD) and Duplicate Address Detection () (sections 3 and 3.1), so every IPv6 host runs it before its first packet. After reading, you can decode its five ICMP version 6 () messages, derive a solicited-node group by hand, follow a resolution through the neighbour cache, recognise rogue advertisements and cache exhaustion with their defences, and watch it all with ip, ndisc6, tcpdump and Wireshark.

ICMPv6 carries the link

ICMP was never optional: RFC 792 makes it an integral part of IP that every IP module must implement (RFC 792, Introduction). ICMPv6, Next Header 58, carries more, in the Type, Code and Checksum header that ICMP, ping, and traceroute reads for IPv4, and "ICMPv6 is an integral part of IPv6, and the base protocol (all the messages and behavior required by this specification) MUST be fully implemented by every IPv6 node" (RFC 4443, sections 1 and 2). ND uses its informational types 133 to 137 (section 2.1). IPv4 filtering habits do not transfer (RFC 4890, Abstract): router and neighbour solicitations and advertisements, with the Multicast Listener Discovery (MLD) and SEcure Neighbor Discovery (SEND) messages, "must not be dropped if the node is to successfully participate in an IPv6 network" (section 4.4.1).

Five messages, five type numbers

RFC 4861 defines the five, all with code 0 (RFC 4861, sections 2.3 and 4):

TypeMessageSent by, toCarries
133Router Solicitation (RS)host, to all-routers ff02::2a request for an immediate advertisement
134Router Advertisement (RA)router (link-local), to the asker or all-nodes ff02::1M and O flags, Router Lifetime, timers; prefix, maximum transmission unit () and link-layer options
135Neighbor Solicitation (NS)any node; multicast to resolve, unicast to check reachabilityTarget Address, source link-layer address
136Neighbor Advertisement (NA)any node; unicast reply, or all-nodesR (router), S (solicited) and O (override) flags, Target Address, target link-layer address
137Redirectrouter, to hostTarget and Destination Addresses

Each leaves with Hop Limit 255 and is valid only if it arrives with 255 (RFC 4861, sections 4.1 to 4.5, 6.1, 7.1 and 8.1): "Because routers decrement the Hop Limit on all packets they forward, received packets containing a Hop Limit of 255 must have originated from a neighbor" (section 11.2). Options are Type, Length in 8-octet units (zero discards the packet) and data; type 3, Prefix Information, carries the L (on-link) and A (autonomous configuration) flags (sections 4.6 and 4.6.2). The RA's M and O flags point to the Dynamic Host Configuration Protocol for IPv6 () for addresses and for other configuration (section 4.2), as How IPv6 hosts get addresses explains. IPv6 also bans fragmented ND (RFC 6980, section 5).

Solicited-node multicast, worked by hand

IPv6 has no broadcast address; multicast takes its place (RFC 4291, section 2). Where broadcasts to every station (RFC 826, An Example), an NS goes to the target's solicited-node group, "formed by taking the low-order 24 bits of an address (unicast or anycast) and appending those bits to the prefix FF02:0:0:0:0:1:FF00::/104" (RFC 4291, section 2.7.1). Every node, routers included, joins the group of each unicast and anycast address it has configured, and addresses differing only above those 24 bits share one (section 2.7.1). Worked from a Media Access Control (MAC) address in the documentation range (RFC 9542, section 2.1.4), in the notation of the addressing article:

MAC address                        00-00-5e-00-53-01
insert ff-fe in the middle         00-00-5e-ff-fe-00-53-01
invert the universal/local bit     first octet 0x00 = 00000000 -> 00000010 = 0x02
interface identifier               0200:5eff:fe00:5301
link-local address                 fe80::200:5eff:fe00:5301
global address                     2001:db8::200:5eff:fe00:5301
low-order 24 bits (both)           00 53 01
ff02::1:ff00:0/104 + those bits    ff02:0000:0000:0000:0000:0001:ff00:5301
solicited-node group               ff02::1:ff00:5301
Ethernet destination               33-33 + ff-00-53-01 = 33:33:ff:00:53:01

The identifier is in Modified 64-bit Extended Unique Identifier () format: 0xFF and 0xFE in the middle, universal/local bit inverted (RFC 4291, Appendix A). The link-local address is fe80::/64 plus that identifier (RFC 2464, section 5), and it shares those 24 bits, and so its group, with the global one. On the packet is "transmitted to the Ethernet multicast address whose first two octets are the value 3333 hexadecimal and whose last four octets are the last four octets of DST" (RFC 2464, section 7); 0x33 is binary 00110011, and the set bottom bit is the Group bit (RFC 9542, section 2.3.1). With 2^24 = 16,777,216 groups, few nodes besides the target are interrupted (RFC 4861, section 3.1). A switch without MLD snooping floods the frame regardless; a snooping one needs the MLD report DAD sends first (RFC 4862, section 5.4.2); see Multicast: what it costs to not flood.

Address resolution, packet by packet

Multicast is never resolved; for an on-link unicast neighbour with no entry (RFC 4861, sections 5.2 and 7.2):

  1. The sender creates an INCOMPLETE entry and queues the packet (RFC 4861, section 5.2).
  2. It multicasts an NS to the target's group, carrying its own link-layer address (section 7.2.2).
  3. The target, lacking an entry for the sender, should create a STALE one from it (section 7.2.3).
  4. The target replies with a unicast NA, S set, carrying its link-layer address (section 7.2.4).
  5. The sender records it, marks the entry REACHABLE and sends the queued packet (section 7.2.5).

One exchange gives both sides an entry (RFC 4861, section 3). After three unanswered solicitations a second apart, "The sender MUST return ICMP destination unreachable indications with code 3 (Address Unreachable) for each packet queued awaiting address resolution" (sections 7.2.2 and 10). In this illustrative capture, from documentation values, 2001:db8::1 (MAC 00:00:5e:00:53:02) resolves the address above; Ethernet type 86DD marks IPv6 in the Ethernet frame (RFC 2464, section 3):

Illustrative capture (documentation addresses)

1  Neighbor Solicitation
   Ethernet  dst 33:33:ff:00:53:01  src 00:00:5e:00:53:02  type 86dd
   IPv6      src 2001:db8::1  dst ff02::1:ff00:5301  next header 58  hop limit 255
   ICMPv6    type 135  code 0  target 2001:db8::200:5eff:fe00:5301
   option    type 1 (source link-layer address)  length 1  00:00:5e:00:53:02

2  Neighbor Advertisement
   Ethernet  dst 00:00:5e:00:53:02  src 00:00:5e:00:53:01  type 86dd
   IPv6      src 2001:db8::200:5eff:fe00:5301  dst 2001:db8::1  next header 58  hop limit 255
   ICMPv6    type 136  code 0  R=0 S=1 O=1  target 2001:db8::200:5eff:fe00:5301
   option    type 2 (target link-layer address)  length 1  00:00:5e:00:53:01

The NS carries the asker's MAC in option 1, one 8-octet unit; the NA returns unicast with S=1 (an answer), O=1 (override the cache), R=0 (not a router) and the target's MAC in option 2.

The Neighbor Cache and unreachability detection

Resolved addresses live in the Neighbor Cache, beside the Destination Cache of next hops, the Prefix List and the Default Router List behind a host's default gateway (RFC 4861, section 5.1). An entry has five states (section 7.3.2):

StateMeaningNext
INCOMPLETEresolvingREACHABLE on a solicited NA
REACHABLEconfirmed within ReachableTimeSTALE when it expires
STALEunconfirmed; idle until a packet is sentDELAY on the next packet
DELAYwaiting 5 seconds for an upper layerREACHABLE, or PROBE
PROBEunicast NS every RetransTimerREACHABLE, or deleted after three

"Unlike ARP, Neighbor Discovery detects half-link failures (using Neighbor Unreachability Detection) and avoids sending traffic to neighbors with which two-way connectivity is absent" (RFC 4861, section 3.1). Only a solicited NA or upper-layer progress, such as a new TCP acknowledgment, confirms reachability, and only neighbours the node is sending to are probed (sections 7.3.1 and 7.3.3). ReachableTime is random between 0.5 and 1.5 times 30,000 milliseconds, so REACHABLE lasts 15 to 45 seconds, and a silent neighbour is deleted about 8 seconds after the next packet: 5 in DELAY, three probes a second apart (sections 6.3.2, 7.3.3 and 10). RFC 7048 finds this "operationally more brittle than the IPv4 Address Resolution Protocol (ARP)" and adds an UNREACHABLE state that keeps probing with exponential backoff (RFC 7048, sections 1 and 3).

Duplicate Address Detection

"Duplicate Address Detection MUST be performed on all unicast addresses prior to assigning them to an interface, regardless of whether they are obtained through stateless autoconfiguration, DHCPv6, or manual configuration" (RFC 4862, section 5.4), anycast being among the exceptions. The interface joins all-nodes and the tentative address's group, sends one NS for it from the unspecified address to that group, and waits a second (sections 5.1, 5.4 and 5.4.2). An owner answers with an NA to all-nodes (RFC 4861, section 7.2.4), and any answer makes the address a duplicate that must not be assigned (RFC 4862, sections 5.4.4 and 5.4.5); How IPv6 hosts get addresses places the check in autoconfiguration.

Routers: advertisements, timers and redirects

Routers advertise on request and, by default, at least every 600 seconds; a host sends up to three RSs at least four seconds apart (RFC 4861, sections 6.2.1 and 6.3.7). Since a host whose RSs were all lost could wait 30 minutes, RFC 7559 keeps it soliciting, with backoff up to 3600 seconds (RFC 7559, sections 1 and 2). A router sends a rate-limited Redirect when a better first hop, or the destination itself, is on the same link; hosts accept it only from their current first-hop router, never send one, and treat the new next hop as on-link (RFC 4861, sections 3.1 and 8.1 to 8.3).

How it fails or is attacked

ND trusts whoever is on the link: any neighbour can send RAs, and "The protocol does not allow hosts to verify whether the sender of a Neighbor Advertisement is the true owner of the IP address included in the message" (RFC 4861, section 11.1). Abuse diverts packets, for denial of service (DoS) or interception (section 11).

Rogue RAs are mostly accidents: Windows Internet Connection Sharing (ICS) turning a laptop into a 6to4 gateway, miscabling that bridges subnets, a mistake. In 2011 "reports of accidental rogue RAs are very commonplace", malicious ones rare (RFC 6104, sections 2.1 to 2.3). Either way hosts take the RA's source as default router (section 1), and NUD misses the black hole while the rogue answers probes with the R bit set (RFC 4861, section 11.1).

A spoofed NA pairing a victim's IP address with another link-layer address can "overwrite an existing entry in the sender's neighbor cache" (RFC 4861 errata, Errata ID 6983); this follows that verified erratum, as the published text names the destination cache. NUD clears the bad entry in 30 to 50 seconds unless the attacker keeps answering (RFC 3756, sections 4.1.1 and 4.1.2). Answering every DAD probe denies a host any address, and a Redirect forged with the first-hop router's link-local source is accepted (sections 4.1.3 and 4.2.4).

Cache exhaustion can come from off-link (RFC 3756, section 4.3.2): traffic to unused addresses makes the router, or a host, resolve each one, and a /64 holds 2^64 = 18,446,744,073,709,551,616 addresses against 4,096 in an IPv4 /20, so incomplete entries exhaust memory and displace in-use ones (RFC 6583, section 2). In testing, "four simultaneous nmap sessions from a low-end computer were sufficient to make a router's Neighbor Discovery process unusable" (RFC 6583, section 4); IPv6 subnetting and the /64 boundary explains the /64.

Defences, and what each one covers

With Hop Limit 255, only cache exhaustion can come from off-link. Router Advertisement Guard () filters in the switch, at its simplest passing RAs only from the router's port (RFC 6105, Abstract and section 3), and protects only traffic crossing such switches (section 5). Extension headers evaded some implementations, and fragmentation all of them in 2014, so RFC 7113 requires parsing the entire header chain, dropping first fragments that lack it and logging drops (RFC 7113, Abstract and sections 2 and 3). RFC 9099 still recommends RA-Guard as a first line of defence (RFC 9099, section 2.3.2.4).

SEND adds cryptography: routers certified by a trust anchor each host must hold, Cryptographically Generated Addresses (CGA), a signature option, and Timestamp and Nonce options against replay (RFC 3971, section 4). On cache exhaustion, "SEND does not address this threat" (section 9.2.6); RFC 9099, a later operational document, reads it differently and counts Neighbor Discovery DoS attacks among what SEND protects against (RFC 9099, section 2.3.6). It is also rare: "CGA and SEND do not have support from widely deployed IPv6 devices; hence, their usefulness is limited and should not be relied upon" (section 2.3.6).

Against exhaustion, RFC 9099 suggests rate-limiting NSs, capping incomplete entries (for example at 256 per interface) and a /127 on point-to-point links (RFC 9099, section 2.3.1); sizing subnets to the addresses in use also works, but only for statically configured hosts, since prefixes longer than a /64 rule out stateless autoconfiguration (RFC 6583, section 6.2).

How to see it

ip -6 neigh show dev eth0
ip -6 neigh show nud stale
ip -6 neigh get 2001:db8::1 dev eth0
ip -6 maddress show dev eth0
sysctl net.ipv6.conf.eth0.accept_ra
ndisc6 -m 2001:db8::200:5eff:fe00:5301 eth0
rdisc6 eth0
tcpdump -i eth0 -n -e 'icmp6[icmp6type] == icmp6-neighborsolicit or icmp6[icmp6type] == icmp6-neighboradvert'

ip -6 neigh shows the five RFC states in lower case plus Linux's failed (probes exhausted), permanent, noarp and none (ip-neighbour(8)); ip -6 maddress lists the multicast addresses joined, where ff02::1 and each solicited-node group belong (ip-maddress(8)). The sysctls accept_ra, accept_redirects, dad_transmits (default 1) and router_solicitations (default 3) shape the host's side (kernel IP Sysctl; sysctl(8)). ndisc6 -m prints every answer, so a second answer points to a duplicate address or a spoofed NA (ndisc6(8)); rdisc6 lists routers and prefixes (rdisc6(8)), for spotting rogue routers (NDisc6). tcpdump -e prints the Ethernet header (tcpdump(1)), but its icmp6[...] accessor assumes no extension headers, so an ND message behind one escapes the filter (pcap-filter(7)). On Windows, Get-NetNeighbor -AddressFamily IPv6 reads the cache (Get-NetNeighbor). In Wireshark, icmpv6.type in {133..137} isolates ND and icmpv6.type == 134 the RAs, whose sources expose an unexpected router (Wireshark ICMPv6 reference; wireshark-filter(4)).

The IPv6 Toolkit classifies ff02::1:ff00:5301 as link-local-scope multicast and reads the MAC out of fe80::200:5eff:fe00:5301, but computes no solicited-node group and sends nothing. The OUI / MAC vendor lookup, named for the Organizationally Unique Identifier (), shows 33:33:ff:00:53:01 as multicast, and the Python playground runs the derivation (Python ipaddress):

import ipaddress
a = ipaddress.IPv6Address("2001:db8::200:5eff:fe00:5301")
g = ipaddress.IPv6Address(int(ipaddress.IPv6Address("ff02::1:ff00:0")) | (int(a) & 0xFFFFFF))
print(g.compressed)                                            # ff02::1:ff00:5301
print("33:33:" + ":".join(f"{b:02x}" for b in g.packed[12:]))  # 33:33:ff:00:53:01

What to remember

  • ND's five ICMPv6 messages, types 133 to 137, carry Hop Limit 255, so anything that crossed a router is rejected.
  • The solicited-node group is ff02::1:ff00:0/104 plus the low 24 bits, so 2001:db8::200:5eff:fe00:5301 resolves through ff02::1:ff00:5301 and 33:33:ff:00:53:01.
  • One multicast NS and one unicast NA give both sides an entry; three unanswered NSs mean Address Unreachable.
  • Entries pass through INCOMPLETE, REACHABLE (15 to 45 seconds by default), STALE, DELAY and PROBE.
  • DAD is one NS from the unspecified address, and any answer forbids the address.
  • Rogue RAs, mostly accidental, and spoofed NAs need a foothold on the link; cache exhaustion works from anywhere that reaches the /64.
  • RA-Guard built to RFC 7113, NS rate limits and right-sized subnets are the defences in use; SEND is rarely deployed.

Sources