Surviving with IPv6 only

Trying to use an IPv6 only machine runs into a roadblock when you need to access a legacy IPv4 resource.

The best solution would be to convince services to move to an IPv6 first solution, incrementally adding reverse proxies for existing services and deploying new services to IPv6 only, with an IPv4 gateway only as needed.

Deploying new services to IPv6 only is much simpler than dual-stack, as you only need to worry about one set of configuration, firewalls, etc. Adding an IPv4 proxy on top, for legacy support, is then a simple, and contained, extension.

However, until that happens you still need a solution.

I found setting up DNS64 + NAT64 for my IPv6 only machines was pretty simple with my OpenWRT router.

Backstory

So, I was trying to install some form of local Kubernetes on my IPv6 only machine, but all the local cluster solutions hit an IPv6 wall trying to complete basic installation:

  • Kind: you can install via Go, as sigs.k8s.io is available via IPv6, but sudo kind create cluster fails as registry-1.docker.io does not support IPv6.
  • MicroK8s: snapcraft.io does not support IPv6.
  • k3s & k3d: download from Github, which does not support IPv6. There is a kind of work around for some pages (e.g. raw.githubusercontent.com) as the Content Distribution Network (CDN) being used, Fastly, now supports IPv6 and is just missing the needed DNS records. Adding your own HOSTS records for the working IPv6 address gives access to this content (see https://github.com/isaacs/github/issues/354). However other content, including the main github.com site, are not accessible via IPv6.
  • Minikube: I didn’t try installing as the documentation says minikube does not support IPv6 yet, although it is on the roadmap (just below multi-node clusters, which they added this year).

So, you still need access back to legacy IPv4 content, with a common solution DNS64 + NAT64.

NAT64

I am using a router running OpenWRT, so a bit of searching there is a NAT64 module for it, tayga, and has been for a long time. For a while it disappeared from OpenWRT but was added back in LEDE, and now that the two projects have merged back together it is easily added in more recent versions of OpenWRT, e.g. 19.07, following the instructions from https://github.com/cvmiller/nat64

Note that I did not change DHCP, or install Bind, or any other DNS-related things; I just installed the NAT64 package.

After installing the package (opkg install tayga-0.9.2-2.pkg), and adding it to the network configuration (/etc/config/network), I downloaded the start script and was able to SCP it across:

scp -P 2222 nat64_start.sh root@[fd12:3456:789a::1]:/root/nat64_start.sh

And test it:

chmod +x /root/nat64_start.sh
/root/nat64_start.sh -w pppoe-wan

I then added the start script to the Luci GUI System > Startup > Local Startup, so that I can easily check/change it. I had to include the PPPoE interface name in the startup:

/root/nat64_start.sh -w pppoe-wan

DNS64

Google provides a public DNS64, however I didn’t enable it on my OpenWRT box (I only set up the NAT64, and skipped the other sections). This means that most of the machines on my local network are still dual stack, i.e. still getting IPv4 DNS records.

Given that they are using NAT44 for everything anyway, I don’t think switching to NAT64 is going to make things much worse, although I have a lot of IoT devices that only support IPv4 (e.g. lights, robot vacuums, solar power system, air con, TV, etc), so I would need local dual stack for parts of my network anyway.

On my IPv6 box however I did just configure to use the Google DNS64 by modifying /etc/netplan and configuring the nameserver address 2001:4860:4860::6464

This means I can enable the machines I want to use DNS64, not a global setting, and slowly move them across.

Note that even if I did enable DNS64 for everything, it should all still work, as machines that understand IPv6 with get the fake IPv6 address and go via NAT64, while machines that don’t will continue to get the IPv4 address and go via NAT44. (But I’ll still need dual stack to access those machines locally).

Success

This now means that on my IPv6 only box, with Google DNS64 configured, when I lookup addresses I get the synthetic IPv6 equivalents:

$ nslookup raw.githubusercontent.com
…
Non-authoritative answer:
raw.githubusercontent.com canonical name = github.map.fastly.net.
Name: github.map.fastly.net
Address: 151.101.0.133
…
Name: github.map.fastly.net
Address: 64:ff9b::9765:85
…

Which are then happily used by apps (ping, curl, etc), intercepted by the NAT64 service, and work quite well:

$ ping raw.githubusercontent.com
PING raw.githubusercontent.com(64:ff9b::9765:c085 (64:ff9b::9765:c085)) 56 data bytes
64 bytes from 64:ff9b::9765:c085 (64:ff9b::9765:c085): icmp_seq=1 ttl=54 time=1.88 ms
64 bytes from 64:ff9b::9765:c085 (64:ff9b::9765:c085): icmp_seq=2 ttl=54 time=1.96 ms

Other machines on the network are still going to get the IPv4 address only (for now), but they still have to do NAT44 anyway.

So now my IPv6 only machine has a working DNS64 + NAT64 solution to access legacy IPv4 resources!

One thought on “Surviving with IPv6 only”

Mentions

Leave a Reply

Your email address will not be published. Required fields are marked *