IPv6 neighbor discovery on EdgeRouter is not usable in real scenarios

1 month ago 4

In 2025 it's surprising that IPv6 doesn't just work on a router, but my experience deploying EdgeRouter Infinity (ER-8-XG) in several network environments confirms it's still a work in progress.

ER-8-XG is based on Linux kernel 4.9.79-UBNT (using a modified Debian distribution). So the core routing/iptables works correctly. However, IPv6 is also about neighbor discovery (ND), and this is where the pain starts. IPv6 ND is like IPv4 ARP with additional link local IP details (interfaces in IPv6 have both link local IPs and logical IPs).

At the most basic level, one would expect a router configured with a single "bridge" net block to just work. In other words, if all the interfaces of the ER-8-XG are added to a bridge group with IPv6 RA enabled, all IPv6 devices connected to the interfaces should be able to discover snd communicate with each other. This is where EdgeRouter goes egregiously wrong. By transmitting ICMPv6 ND blindly between interfaces, it seems to mess up the neighbor discovery state. Only the router knows all of the link local IPs, so the link local IPs actually need to be "translated " to each interface. This is especially noticeable if any of the devices connected are L2 switches, which seem to use ND to optimize packet delivery.

It's such a basic configuration but absolutely fails. A more realistic scenario is to have a subset of the public IPs bridged to the interfaces, so that for example you have a bunch of hosts connected to the ER-8-XG with public IPs on their interfaces. The well-known supported solution on IPv4 is to use the config enable-proxy-arp to pass ARP messages between the upstream interface and the hosts. In IPv6, there is no solution. This is again a basic scenario where IPv6 is flat out broken on the ER-8-XG.

It turns out someone wrote the equivalent of proxy ARP for IPv6 over 10 years ago - https://github.com/DanielAdolfsson/ndppd. Various people have compiled it for EdgeRouters (https://github.com/sho7650/ndppd) and this is another fork to target the ER-8-XG (mips64) routers. It seems like not only should there be a "enable-proxy-nd" setting that basically runs the config in Example 1, but that is also how the IPv6 bridge should work by default. I don't believe it's correct to just blindly echo the ICMPv6 ND packets without translating the link local IPs.

This issue has been filed with Ubiquiti and is one of several existing requests to fix IPv6 ND on edge routers [1, 2].

Run make build_er8xg to build a version for ER-8-XG.

  1. https://community.ui.com/questions/IPv6-Neighbor-Discovery-is-Effectively-Broken/1ae0270d-8346-4974-881b-b16f9f2e7cfb
  2. https://community.ui.com/questions/Need-ND-proxy-again/62d4eac4-9a37-4ebe-b52f-1a844b2d8540

Example 1 - ndppd.conf template

The following template for /etc/ndppd.conf is created for each interface that has "enable-proxy-nd" enabled, for each IPv6 interface route.

proxy {INTERFACE} { rule {INTERFACE_ROUTE} { iface {VIA_INTERFACE} } }

ndppd, or NDP Proxy Daemon, is a daemon that proxies neighbor discovery messages. It listens for neighbor solicitations on a specified interface and responds with neighbor advertisements - as described in RFC 4861 (section 7.2).

Version 0.x has been discontinued, and is being replaced by 1.0-devel which you can find here.

index 00ca22b..3900339 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,12 @@ ifdef DEBUG CXXFLAGS ?= -g -DDEBUG else -CXXFLAGS ?= -O3 +CXXFLAGS = -O3 +LDFLAGS = -static endif -PREFIX ?= /usr/local -CXX ?= g++ +PREFIX = /ndppd/local +CXX = /usr/bin/mipsel-linux-gnu-g++ GZIP ?= /bin/gzip MANDIR ?= ${DESTDIR}${PREFIX}/share/man SBINDIR ?= ${DESTDIR}${PREFIX}/sbin
  1. git clone to your home computer
git clone https://github.com/sho7650/ndppd.git
  1. run your docker with ndppd directory
docker run -v $PWD/ndppd:/ndppd -it --rm sho7650/mipsel
  1. run make
  1. copy files to your edgerouter
scp ndppd [email protected]:/ndppd/local/sbin scp scripts/ndppd [email protected]:/config/scripts/post-config.d scp scripts/ndppd.initscript [email protected]:/ndppd/local/sbin

!!! check owner and execute flags of these files on your edgerouter

Read Entire Article