Together with most of the internet, we tested IPv6 on World IPv6 day last week. I won’t go into details on what IPv6 is and why it’s important. Although IPv6 has been tested intensely in isolated networks, this is the first time it was tested on such a large scale. Technically, the participants would just add AAAA-records for their websites to DNS. This small change causes a huge effect. Since most browsers are configured to prefer IPv6 AAAA-records over IPv4 A-records, this causes all IPv6-connected users to suddenly connect over IPv6 instead of IPv4.
For the most part, this major changeover happened without as much of a hitch. In fact, if I hadn’t known it was World IPv6 day, I wouldn’t have noticed anything. But I’m not a normal web-user, so I did notice some issues.
Where it did went wrong
After some troubleshooting, they all boiled down to a single cause of oversight. They were not bugs or issues with IPv6 per se, just some “expected behavior” that we didn’t anticipate: IPv4-only VPNs.
Most servers in our datacenter are not publicly accessible; none of them are manageable over the public internet. In order to connect to them, you need a VPN connection. This serves multiple purposes: it secures all communication between client and server (so even plain-text http can be used securely to manage servers), it limits the number of users with access and most importantly (in the IPv4 world) it allows us to use RFC1918 addresses internally and still get the routing to work out. Technically it behaves an an extra (virtual) network card with a (virtual) cable connected straight to the datacenter. Additionally, some routes are configured automatically on the client to make sure traffic to the servers is sent over this “cable”.
We use two kinds of VPN-connections, but none of them was IPv6 enabled (i.e. could carry IPv6 data through the tunnel). Since by default client software prefers IPv6 connections, this caused the IPv6-internet connection to be preferred above the IPv4-VPN connection. Obviously, the firewall at the datacenter didn’t agree and refused access.
The solution was fairly obvious to state (enable IPv6 through the tunnels) but difficult to implement. In fact, I have not been able to get it to work well enough to install it on someone else’s computer.
IPsec in transport mode
However, I was not able to get this to work, even in manual keying mode (i.e. without ISAKMP). I couldn’t get setkey to accept the src-dst parameter in the SPD:
# setkey -c spdadd 2001:db8:0:1::1 2001:db8:1:1::3 any -P fwd ipsec esp/transport/2001:db8:1:0:2-2001:db8:1:1::3/require; ^D # setkey -DP 2001:db8:0:1::1[any] 2001:db8:1:1::3[any] any fwd prio def ipsec esp/transport//require created: Jun 14 12:13:53 2011 lastused: lifetime: 0(s) validtime: 0(s) spid=1641 seq=1 pid=10485 refcnt=1
This seems to be a Linux issue (Ubuntu 10.04 LTS with kernel 2.6.32-28-generic and ipsec-tools 0.7.1), since this does work on MacOSX (10.6.7).
IPsec tunnel mode
Since I’m not entirely sure that what I tried above (transport mode) is even supposed to work, I also tried tunnel mode. This worked, but is a pain to configure. I only tried manual keying, but using racoon to do username/password authentication will be even harder to explain to users…
The Mac built-in VPN client only supports “Cisco IPsec“. This uses the mode configuration stage to communicate the set of “networks” to tunnel (i.e. the SPD). However, according to racoon.conf man-page, I can only push IPv4 networks in the split_network directive.
OpenVPN with tun driver
According to the OpenVPN FAQ, IPv6 is only supported if the underlying TUN-driver supports it. The tuntaposx-page does not mention IPv6 at all and hasn’t been updated for almost 2 years, so this seems unlikely to work.
Also, OpenVPN does not provide configuration directives to push IPv6 routes over from server to client.
OpenVPN with tap driver
Even when using the TAP-driver and router advertisements, MacOSX does not seem to like enabling IPv6… Even after manually enabling it, MacOSX still doesn’t pick up its SLAAC address:
# ifconfig tap0 tap0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether 7e:95:80:00:90:0e inet 192.0.2.10 netmask 0xffffff00 broadcast 10.90.9.255 open (pid 3847) # ip6config start-v6 tap0 Starting IPv6 on tap0. # sleep 60 # Wait for Router advertisement to show up # ifconfig tap0 tap0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether 7e:95:80:00:90:0e inet 192.0.2.10 netmask 0xffffff00 broadcast 10.90.9.255 inet6 fe80::7c95:80ff:fe00:900e%tap0 prefixlen 64 tentative scopeid 0xa open (pid 3847)
And this still doesn’t allow me to push IPv6 routes to the clients upon connecting.
IPv6 is very stable and capable, but there are certain network-issues where there is still some work to do. If you happen to know a VPN-solution which supports IPv6 and works on Windows, linux and Mac, please let me know!
Edit: I worked out my own solution.