I recently upgraded to gigabit Internet at home but unfortunately my old faithful router running OpenWRT just couldn’t keep up with the faster speeds. I needed something with hardware offloading and didn’t want to use the ISP provided solution, so since I like Ubiquiti I decided on an ER-Lite-3.
After getting everything setup how I wanted things were working well, fast too, both on IPv4 and IPv6. Well almost everything. When I went to setup external SSH access for the router I hit a snag - I couldn’t ping it from outside my LAN.
In the IPv4 world this would be totally normal. It’s very common for firewalls to block the ICMP packets ping needs to do its thing. IPv6 is different though because ICMPv6 is a critical part of how it deals with things like avoiding packet fragmentation. This means my firewall is configured to let pings through so that couldn’t be the cause of my issues 🤔.
Next thing I do is check the connectivity to other devices on my LAN and they’re all pingable over IPv6 as I’d expect. This got me thinking about outgoing pings instead of incoming - do they work? The answer is yes… for every device but the router 🤦♂️. So next I try to curl ipv6.google.com and this fails too.
The issue it turns out is bigger than I originally thought because the router has no IPv6 connectivity at all. This is a problem for me since the router is my caching DNS resolver and I want it to be using IPv6 wherever possible but it can’t do that if it can never use IPv6 😢. The router gets its address from somewhere but it doesn’t seem to be globally routable like he rest of the LAN.
So as far as I understand things, I think this address is coming from my ISP but I’m not sure so I have to go do some googling around and read some RFCs. Turns out the address does come from my ISP through DHCPv6. This is one of the ways clients can get configured in IPv6 and my router is a client to the upstream ISP router.
The way this works is my router makes a request for two things: an address for itself and a prefix. The prefix is basically a big chunk of addresses which my router can allocate to its own networks, my LAN in this case. This is how IPv6 avoids needing to use NAT unlike IPv4. You get so many addresses that every device can have it’s own globally unique one 😯!
So now I’m like 90% sure the address is coming from my ISP but just to be sure I use tcpdump and wireshark to see what’s actually being sent over the wire. Sure enough, I see the non-working address is being assigned along with the working prefix. So at this point I fire off an email to tech support with the issue I’ve found and in the meantime I try to work around the problem on my end.
It turns out a fix for the issue is really simple: just tell my router not to ask the upstream one for an address, just a prefix. Now it doesn’t end up with any address on it’s WAN interface so will end up using the address from it’s LAN interface, which it allocates from within the prefix. In IPv4 land this wouldn’t work due to NAT but in IPv6 land that address is globally routable and now everything ends up working swimmingly 😁.