NAT64 and DNS64

After setting up IPv6 for nearly two months, I’m now interested in testing an IPv6 only LAN. In order to access the IPv4 Internet from an IPv6 only network, a method called NAT64 is used. It is an address only translation method which maps the IPv4 address space into a /96 block.

I reclaimed the 192.168.0.0/24 block on my eth1, making eth1 my test network and use the block for the NAT64. I also allocated the 2001:470:19:a87::/96 block for that. I didn’t use the well-known prefix as I may want IPv6 devices access IPv4 only devices on my other LAN (therefore, my NATted IPv4-only devices are now accessible from the IPv6 Internet, given firewall rules allow). Then, I installed tayga, a NAT64 server which runs in user space and set it up to use 192.168.0.0/24 and 2001:470:19:a87::/96, with 192.168.0.1 as the tunnel address.

Tayga works as follows:
1. It creates a tunnel device (normally called nat64) which connects an IPv4 and an IPv6 address to itself.
2. Routes on both IPv4 and IPv6 are created such that traffic to the NAT64 blocks is directed to the address of the tunnel.
3. It listen on the tunnel.
4. If an IPv6 packet is received, it will rewrite the source, which can be from anywhere on the Internet, and the destination, which is in the NAT64 block, to the corresponding IPv4 addresses, which will have the source address in the NAT64 block and the destination address somewhere on the Internet, then sent back to the host through the tunnel. If an IPv4 packet, it will do the opposite. As the entire IPv4 address space is mapped in the IPv6 NAT64 block, IPv6 packets always get forwarded to the IPv4 network. However, the reverse doesn’t stand. Therefore, an IPv4 packet only gets forwarded to IPv6 if a mapping exists, otherwise, the server responds with an ICMP host unreachable message. This mapping can be configured statically, or dynamically created when a packet is forwarded from IPv6 to IPv4, in a manner similar to regular NAT.
Note that Tayga does one-to-one mapping between IPv6 and IPv4. Therefore, if you only have a single IPv4 connection to the Internet, you should additionally configure regular NAT as well.

The following is an example:
The host 2001:db8::dead:face sends a packet to 2001:470:19:a87::192.0.2.14 (note that the last 32 bits of the IPv6 address are written in dotted decimal notation, which is the usual way to represent an IPv4 address mapped into IPv6). After a sequence of IPv6 routers, it reaches 2001:470:19:187::192.168.0.1 (which is the tunnel IPv4 address mapped into IPv6, aka the tunnel IPv6 address). Then, the packet passes through the tunnel and reaches the server. The server then rewrites the source address to, say, 192.168.0.138 (the mapping is created if needed) and the destination address to 192.0.2.14, and sends this packet back to the host. It then goes through a sequence of IPv4 routers, finally to the destination. The reply packet, which is from 192.0.2.14 to 192.168.0.138, goes through a sequence of IPv4 routers back to 192.168.0.1 again. The server sees the mapping and rewrites the address to make the packet appear from 2001:470:19:a87::192.0.2.14 to 2001:db8::dead:face, and sends it back to the destination through the IPv6 network.

Now, IPv6 only hosts can communicate with IPv4 only hosts through NAT64. However, to make the IPv6 only network useful, the DNS server must make up a fake AAAA record whenever an A record but not an AAAA record exists, by appending the NAT64 prefix to the A record. This is necessary because the host does not speak IPv4, hence cannot connect with only an A record. Reverse mapping for the NAT64 block should also be set up to translate the request into an IPv4 reverse (a CNAME referring to the in-addr.arpa domain is enough). This kind of DNS is called DNS64.

The version of bind9 in Debian wheezy is not high enough (DNS64 support is added in 9.8), so I compiled the version in sid from source and installed it. After some configuration, I plugged my laptop into the IPv6 only network and tried to access the Internet and it worked. Moreover, I found that in the netstat output on my router, most of the connections are in IPv6 (because of the DNS64)!