IPv6If you don’t know what IPv4 and IPv6 are, this post isn’t for you.

If you know, and are wondering how you might implement IPv6, this might be of interest. We handle http/https requests using a white box router running Debian. Until recently, we were IPv4 only, and the router used NAT to connect to an existing subnet with a local IPv4 address space (in the 10.x.x.x range). What makes it odd is that the subnet is also reachable through a different IPv4 address and NAT—it’s ancient history in a network that has been running since the 1990’s.

When our upstream became IPv6-ready, I found that simply allowing the entire subnet to acquire IPv6 addresses wasn’t practical. I’m not ready to give up the protection that NAT gives a lot of the devices on the subnet, many of them aren’t fully IPv6 ready, and it seems like a herculean task to test the whole mess and verify its security. But it turns out that there is a simple solution that allows us to tunnel http/https requests directly to the web server while leaving the rest of the network unchanged. It doesn’t increase our attack surface in the way that bypassing NAT for IPv6 requests would, and limits added exposure to our web server box only. It will let us incrementally add IPv6 to other services, but in a controlled fashion. In some ways it’s kicking the IPv6 can down the road. It’s a pragmatic solution, though, in a world where a single network engineer (me) cannot really dedicate days to re-configuring and vetting the entire network to support v6 all at once.

The answer is to use socat to tunnel requests on the router’s IPv6 address to the private IPv4 space:

/usr/bin/socat TCP6-LISTEN:443,fork TCP4:10.0.137.88:443
/usr/bin/socat TCP6-LISTEN:80,fork TCP4:10.0.137.88:80

I created a couple of systemd services (yuck!) to launch the socat jobs at boot time (they’re simple, but feel free to email me if you’d like the details).

Hint: debugging can be tricky if you cannot control whether requests come from the v4 or v6 space. I created an FQDN that has no A records, only AAAA records, for testing purposes (sixtest.sacdoc.org) which forces an IPv6 connection. I also made heavy use of a handy IPv6 web site reachability test.

Also be aware that using this technique will mess up your web server logs. Connections will appear to come from the router’s local IPv4 address. If that’s a concern, you can turn on logging in the router firewall, though you’ll have to correlate your router and web server logs if you want to know the IP address associated with a given request.