T-Mobile IPv6 in the US

Swapped from AT&T to T-Mobile in order to take advantage of their 4G/LTE IPv6 network. Since I dogfood IPv6 every chance I get, and the cost to swap saved me a whopping $0.50, I moved forward with it. I find that if I set their EPC.TMOBILE.COM APN to IPv4/IPv6, I don’t really see much in the way of dual-stack actually working on the phone. So I set it from the default IPv4 to just IPv6, and that got it working with native IPv6 and using CLAT+NAT64/DNS64 for IPv4 sites. Screenshot from my Galaxy Nexus running 4.3:

Screenshot_2013-10-11-15-51-06

A quick NAT64/DNS64 setup

So you want to play around with an IPv6-only network! Great! One problem, lots of content is still on IPv4 🙁 A possible solution or workaround? Using NAT64 & DNS64 to let IPv6-only hosts communicate with IPv4 hosts. The gist of it is that you send your DNS lookup requests to a caching DNS recursor that forges (or rather creates) AAAA records for hosts that do not naturally have them configured. That DNS server creates the AAAA records using an IPv6 range will be configured on the NAT64 portion. That NAT64 machine is going to handle the translation of IPv6 to IPv4.

I’ll use ISC’s BIND9 for the DNS64 component, and Tayga for the NAT64. Because Tayga is designed for Linux, this will cover setting up a Linux based NAT64/DNS64 system. Start by installing the latest stable BIND9 daemon on your target machine. Next, pick a range of IPv6 addresses to generate the AAAAs from. We’ll go with our standard documentation prefix and specify 2001:DB8:1:FFFF::/96. Assuming you have proper routing control over your network, you’ll statically route the /64 you carved it from to the NAT64 machine. A very simple BIND9 named.conf.options can look like this:

options {
        directory "/var/cache/bind";
        auth-nxdomain no;
        listen-on-v6 { any; };
        allow-query { any; };
        dns64 2001:db8:1:ffff::/96 {
                clients { any; };
        };
};

You’ll want to lock down allow-query to whatever ranges/networks you plan on allowing DNS64 looksups with, as well as any specific IPv6 address you want it listening on. In the meantime, the above configuration will let any range query so you can test quickly. Start up the DNS daemon, and start making some queries against it for IPv4-only hostnames, they aren’t hard to find. Then try some queries for hosts you know have AAAA records. You’ll find that it doesn’t mangle them and will give you their proper AAAA record.

Next step is configuring Tayga. I’ve been installing both NAT64 and DNS64 components on the same machine, because I found that for a small network the load and traffic isn’t that much. So on the same machine, install Tayga from a package or source. Configure the tayga.conf file with:

tun-device nat64
ipv4-addr 192.168.0.1
prefix 2001:db8:1:ffff::/96
dynamic-pool 192.168.0.0/24

Next thing I did after reading the Tayga READMEs and FAQ on their site, was set up a quick shell script to fire off, eventually called from rc.local and called it start64.sh:

#!/bin/bash
tayga --mktun
ip link set nat64 up
ip addr add 192.168.0.1 dev nat64
ip addr add 2001:db8:1::1 dev nat64
ip route add 192.168.0.0/24 dev nat64
ip route add 2001:db8:1:ffff::/96 dev nat64
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o nat64 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i nat64 -o eth0 -j ACCEPT
tayga
/etc/init.d/bind start

So from an IPv6-only host, set your resolver to 2001:db8:1::1 (for this example), and try reaching an IPv4 only hostname with pings, traces, or connecting to the services run on it.

Now, to cover things that will need editing and additional configuration:

  • IPv6 address(es) that BIND9 listens on
  • IPv6 ranges that BIND9 will allow queries from
  • actual IPv6 range used for NAT64
  • adding ip6tables rules to restrict which IPv6 ranges are even allowed to use the NAT64 portion

Advanced tricks: BGP Anycast

So let us assume you want to try and blanket a network with these boxes for whatever reason, but perhaps the best of all: just to do it 🙂 Set aside a /48 to use for the NAT64/DNS64. Add on either BIRD or Quagga to the machine, and configure that to announce the /48 specific to an upstream router, ideally as part of your iBGP mesh and as a route-reflector client. Configure both BIND9 & Tayga to use a /96 out of that /48. Use the same config on all the machines that will act as anycast nodes. I’ve tested this between two locations by running a wget of an ISO from an IPv4-only hostname, and pulled the /48 announcement from the node I saw the traffic going over. The wget didn’t even hiccup, and instead reported “Read error at byte 504296054/4312793088 (Connection reset by peer). Retrying.” and then kept pulling down the file without issue. Perhaps more failover testing could be done, but I was happy with the results.

Caveat: IPv4 literals will not work since they aren’t hostnames with A records that can have AAAA records created.