Stupid OpenWRT ipv6 tricks
So, if you’re like me you find yourself wondering why your broadband provider has a /32 IPv6 prefix assigned, and yet chooses not to use it, forcing one to either be IPv4-only (how 20’th century) or use an IPv6-over-IPv4 tunnel solution.
Fortunately there is a simple and free solution out there, courtesy of Hurricane Electric’s rather fabulous tunnelbroker service. Obtaining an IPv6 prefix and setting up the tunnel is covered, extensively, so I won’t go into it. It’s also rather easy to set the tunnel up on an OpenWRT based router, like mine. The default setup is rather nice, but there are some changes you can make to your router configuration that will make it even nicer.
Remove the “ULA Prefix”
OpenWRT creates, by default, a ULA prefix – a deprecated “site-local” prefix. While these are perfectly valid, I’ve found that non-globally routable IPv6 addresses tends to confuse the heck out of Android-based phones, resulting in certain operations taking forever while various network operations time out, and are then retried with globally routable addresses. They’re also pointless, as we don’t do IPv6 NAT (don’t even think it), so just remove it. Your phone will thank you.
A note about firewalls
It’s worth repeating: we don’t do IPv6 NAT. Assuming you’ve removed the ULA prefix, every non-link-local IPv6 address assigned will be globally routable, meaning, among other things, that you can’t just rely on NAT to be your firewall, you’ll actually have to use your router as a firewall as well.
This is also well documented, and left as an exercise for the reader. …one I rather suspect you’ve already completed, as, well, you’re using OpenWRT, aren’t you?
More than one network? Get a /48!
By default, HE will give you a /64 routed prefix: this is the pool of addresses your LAN-connected devices will draw from. If you ask – that is, hit the “assign /48” button on your tunnel’s configuration page – HE will also give you a /48. Why would you do this? Well, while you can subdivide your /64 up and route it however you want, most IPv6 tech presumes the smallest network it will ever encounter is a /64. If you choose to, say, make your wired and wireless networks distinct and route rather than bridge between the two the canonical approach is to use one /64 for the wired network, and a second, different /64 for your wireless. (The same logic applies if you wish to also delegate prefixes to hosts on your network – say a /64 to some box you have running a bunch of VM’s or docker containers on.)
But how to set this up easily? Remember that “ULA prefix” option, above? Just put the /48 prefix HE assigned you in there, and everything will Just Work. Delegating specific /64’s to interfaces can be done with “hints” in the interface configuration, and each internal interface will receive a /64 from your /48 automatically.
Yes, this means at least one of your internal networks will have two /64 prefixes addresses can be assigned/chosen from. Don’t sweat it: your device should pick up an address from each /64, and things will Just Work.
OpenWRT uses dnsmasq to provide DNS, and because of this we can do some neat
things. If you edit your
/etc/dnsmasq.conf appropriately, you can get:
Hostnames for the ips assigned to our interfaces, automatically
# hostnames for our interface ips! interface-name=wan.router,eth0 interface-name=wan.router,6in4-henet interface-name=lan.router,br-lan
$ host lan.router lan.router has address 192.168.1.1 lan.router has IPv6 address 2001:470:XXXX:1::1 lan.router has IPv6 address 2001:470:1f11:XXXX::1
That is, a deterministic hostname for every ip on a given subnet that dnsmasq doesn’t already know a hostname for.
synth-domain=ip.lan,192.168.1.0/24 synth-domain=ip.lan,2001:470:1f11:XXXX::/64 # Apparently /48 breaks dnsmasq more than a bit #synth-domain=ip.lan,2001:470:XXXX::/48 synth-domain=ip.lan,2001:470:XXXX:1::/64
$ host 2001:470:1f11:XXX::2 220.127.116.11.0.0.0.0.0.0.0.0.0.0.0.0.X.X.X.X.1.1.f.18.104.22.168.0.1.0.0.2.ip6.arpa domain name pointer 2001-470-1f11-XXXX--2.ip.lan.
Note this “synthetic hostname” will only be returned if dnsmasq lacks a better name, e.g.:
$ host 2001:470:1f11:XXX::1 22.214.171.124.0.0.0.0.0.0.0.0.0.0.0.0.X.X.X.X.1.1.f.126.96.36.199.0.1.0.0.2.ip6.arpa domain name pointer lan.router.
While OpenWRT does not use dnsmasq for router advertisements, we can still use it’s rather nifty “match info from DHCPv4 requests against the DID/MAC the device would use for SLAAC” functionality to enable it to return both A (IPv4) and AAAA (IPv6) records when asked for an internal hostname:
$ host mfc.lan mfc.lan has address 192.168.1.78 mfc.lan has IPv6 address 2001:470:... $ ping6 mfc.lan PING mfc.lan(mfc.lan) 56 data bytes 64 bytes from mfc.lan: icmp_seq=1 ttl=64 time=0.490 ms 64 bytes from mfc.lan: icmp_seq=2 ttl=64 time=46.5 ms ...
Enable with the somewhat cryptic:
# serve AAAA records based off DID/MAC and DHCPv4 requests dhcp-range=::,constructor:br-lan,ra-names
…or some permutation thereof, if you’ve altered the topology of your internal network.
Strip AAAA records for Netflix
Sigh. Yes, apparently we need to do this. Lame. Basically, Netflix thinks it doesn’t know where you are located, so will refuse to serve content to any address that HE has delegated to you via tunnelbroker (e.g. your /64, /48). Fortunately, this is a problem others have already elegantly resolved: OpenWRT workaround against Netflix blocking IPv6 requests from tunnel brokers.
Basically, the solution is to build and install a
bind package that supports
strip-aaaa option, then have dnsmasq delegate any lookups for
*.netflix.com to the bind server. Clean, simple, and easily extensible to any
other service that may choose to do the same thing in the future.
With this hack in place, without impacting any other domain your netflix.com lookups will go from this:
$ host netflix.com 188.8.131.52 Using domain server: Name: 184.108.40.206 Address: 220.127.116.11#53 Aliases: netflix.com has address 18.104.22.168 netflix.com has address 22.214.171.124 netflix.com has address 126.96.36.199 netflix.com has address 188.8.131.52 netflix.com has address 184.108.40.206 netflix.com has address 220.127.116.11 netflix.com has address 18.104.22.168 netflix.com has address 22.214.171.124 netflix.com has IPv6 address 2406:da00:ff00::34cf:6f90 netflix.com has IPv6 address 2406:da00:ff00::34ca:21dd netflix.com has IPv6 address 2406:da00:ff00::34c8:ef2b netflix.com has IPv6 address 2406:da00:ff00::36a4:da76 netflix.com has IPv6 address 2406:da00:ff00::34ce:44b0 netflix.com has IPv6 address 2406:da00:ff00::3655:55f6 netflix.com has IPv6 address 2406:da00:ff00::34cb:53f8 netflix.com has IPv6 address 2406:da00:ff00::34cd:591a
$ host netflix.com netflix.com has address 126.96.36.199 netflix.com has address 188.8.131.52 netflix.com has address 184.108.40.206 netflix.com has address 220.127.116.11 netflix.com has address 18.104.22.168 netflix.com has address 22.214.171.124 netflix.com has address 126.96.36.199 netflix.com has address 188.8.131.52
These are little things, yes (hence the “stupid … tricks” appellation), but every little bit helps when trying to figure out a problem.
…or, you know, appease Netflix :)