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.
Internet | | ERPoE <---> LAN radvd / \ dhcpd3 / \ / \ server clients pdns tayga
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.
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
setvariable()
return "getFakeAAAARecords", domain, "2001:db8:1000:64::"
end
Make sure you load it in recursor.conf
:
lua-dns-script=/etc/powerdns/scripts/dns64.lua
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
2001:db8:1000:64::4275:2fd6
Hooray, now move on.
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
ipv4-addr 10.64.0.1
prefix 2001:db8:1000:64::/96
dynamic-pool 10.64.0.0/24
data-dir /var/spool/tayga
Now starting tayga via systemctl start tayga
should set up an interface called nat64 and some routes:
$ ip route:
(...)
10.64.0.0/24 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 192.168.10.10 here is the LAN IPv4 address of the server on its interface eth0.
# iptables -t nat -A POSTROUTING -o eth0 --source 10.64.0.0/24 -j SNAT --to-source 192.168.10.10
# echo 1 > /proc/sys/net/ipv4/conf/all/forwarding
# echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
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
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.
An example netctl profile on Arch Linux could look like this:
Interface=wlp3s0
Connection=wireless
Security=wpa
ESSID=my-cool-v6-only-network
Key=hunter64
IP=no
IP6=dhcp-noaddr
DHCP6Client=dhclient # dhcpcd doesn't support dhcp-noaddr
TimeoutDAD=10
TimeoutDHCP=30
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.
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.