IPv6-only network at home

01 Dec 2015

v6 only setup using EdgeOS, Debian, TAYGA and PowerDNS

This post describes how I got a IPv6-only network up and running in my home network. Some details are left out for clarity (VLANs for example), but all essential info should be here.


For sake of overview, a rough sketch of what the network looks like. Key here is the fact that my server is doing the DNS64+NAT64, and not my router/gateway (which is a Ubiquiti EdgeRouter PoE). So even if you don't have an EdgeRouter, or something similar (think Vyatta/VyOS, or a Linux box doing all your gateway things), you should be able to get a setup like mine in working order.

The LAN node is an abstraction of a Unifi UAP-Pro, connected to the ERPoE.

        ERPoE <---> LAN
      radvd         /  \
      dhcpd3       /    \
                  /      \
              server    clients

The remainder of this post is ordered according to 'if I do things in this order I hopefully break the least number of things'. Maybe.

PowerDNS with the power of LUA

First, get DNS64 up. As your clients will only be aware of v6 things, they will always request AAAA records. DNS64 will translate those AAAA into A requests if there is no AAAA available. The answer will be special v6 address within your specified range, which will be leading into the NAT64. Again, in this setup the DNS64 is running on the server, not on the gateway.

Credits to the PowerDNS guys for making things easy using lua. This is copied directly from their documentation:

function nodata ( remoteip, domain, qtype, records )
         if qtype ~= pdns.AAAA then return pdns.PASS, {} end  --  only AAAA records
         return "getFakeAAAARecords", domain, "2001:db8:1000:64::"

Make sure you load it in recursor.conf:


Now start PowerDNS via systemctl start pdns-recursor (you did upgrade to Jessie didn't you?) and test with a v4-only domain:

$ dig AAAA ipv4.whatismyv6.com +short @ip-of-your-server

Hooray, now move on.

NAT64 using TAYGA

Also on the server, install and configure TAYGA to do the NAT64 translation. An example /etc/tayga.conf that works in conjuction with the DNS64 configuration above, could look like this:

tun-device nat64
prefix 2001:db8:1000:64::/96
data-dir /var/spool/tayga

Now starting tayga via systemctl start tayga should set up an interface called nat64 and some routes:

$ ip route:
    (...) dev nat64  scope link 

$ ip -6 route:
    2001:db8:1000:64::/96 dev nat64  metric 1024 

Think about how far we are now, and notice we miss one crucial thing on the server for this specific topology. Requests to v4-domains will be translated into the 4-in-6 address in your defined 2001:db8:1000:64::/96 range, and the server will translate those into real v4 and use its dual-stack capabilities and send it out over v4 towards the gateway. If tayga was running on the gateway, you would MASQUERADE it there, but now we need to do that on the server. Otherwise, the return traffic will not end up at our server, where it should go into the nat64 interface, to be translated back into v6 again. Also, make sure that forwarding is enabled. You might opt for a less rigorous approach instead of conf/all, but this depends on your exact setup.

N.B.: the here is the LAN IPv4 address of the server on its interface eth0.

# iptables -t nat -A POSTROUTING -o eth0 --source  -j SNAT --to-source
# echo 1 >  /proc/sys/net/ipv4/conf/all/forwarding
# echo 1 >  /proc/sys/net/ipv6/conf/all/forwarding

Static routes in the EdgeRouter

Traffic from the clients heading towards the NAT64 needs to end up at the server running that NAT64, so the router needs some (static) routes to get the packets out via the right interface. In your EdgeRouter, add a static route for the NAT64-prefix, and set the next-hop to the IPv6 address of the server:

set protocols static route6 '2001:db8:1000:64::/64' next-hop '2001:db8:1000:1::10' distance 1

Finally, Stateless DHCPv6 + SLAAC

If everything is in place, you can provide your clients with a prefix (via Router Advertisements, so SLAAC), and information about the nameserver (via stateless DHCPv6). For EdgeOS, the following should do, although a bug(?) currently causes some unexpected behaviour:

set interfaces ethernet eth1 address '2001:db8:1000:1::1/64'
set interfaces ethernet eth1 ipv6 router-advert prefix '2001:db8:1000:1::/64' autonomous-flag true
set interfaces ethernet eth1 ipv6 router-advert managed-flag false
set interfaces ethernet eth1 ipv6 router-advert other-config-flag true
set interfaces ethernet eth1 ipv6 router-advert send-advert true

So, give the interface an IPv6 address, and enable Router Advertisements on it. Make sure it plays nicely with the stateless DHCPv6, so don't forget to set the right flags.

set service dhcpv6-server shared-network-name WLAN name-server '2001:db8:1000:1::10'
set service dhcpv6-server shared-network-name WLAN subnet '2001:db8:1000:1::1/128' domain-search local

Point to the server as being the name-server, as PowerDNS is running overthere. Furthermore, make sure the dhcpv6 process will be listening on the right interface by specifying the /128. The domain-search local is possibly misplaced in the resulting config file: please keep an eye on this thread for further info.

Now get connected

An example netctl profile on Arch Linux could look like this:



DHCP6Client=dhclient # dhcpcd doesn't support dhcp-noaddr

Maybe it takes a few tries and some tweaks for your specific setup, but once you think it's working, you could use the SixOrNot pugin for Firefox (or something similar) to check whether websites are being served over native v6, or your NAT64 range. Enjoy your v6-only network! Unfortunately, it's still a good idea to have a back-up dual-stack config at hand, as some applications use hard-coded IPv4 literals, and those will simply not work.

Some final notes

While switching between the dual-stack network and the v6-only one, I ended up in a situation where my laptop (running Arch Linux) did not generate a link-local v6 address upon interface up. The dhcp client needs a link-local address, so things broke. I've not been able to reproduce this behaviour yet.