With the previous articles we got our main network connected to the IPv6 Internet. But what about Laptops that are used off-site? Here I'll show how to use a VPN to tunnel IPv6 from any point in the IPv4 network into your main IPv6-enabled network.
OpenVPN is a fairly simple to configure secure VPN software that runs on all Unix-like systems, MacOS/X, and Windows. It is much more simple to configure than IP/Sec and as secure.
In the following paragraphs I'll concentrate on the things that are important to understand to get IPv6 running over OpenVPN, I'll skip the more interesting parts of OpenVPN internals - the OpenVPN Documentation does a better job at that than I ever could. That also means that I chose the security mode that is easier to configure (static keys) over the one that is more secure (X.509 PKI) - switching should be fairly easy once you understand what I did.
I also concentrate on Linux configuration here - other Unix-like systems and MacOS should behave similarly. Well, I can't really speak about Windows...
A note about the VPN connection - the current stable versions of OpenVPN (2.0.x) don't support transport over IPv6 yet, so OpenVPN cannot be used for IPv6-only mobility yet, but this will change in the post 2.0 line (according to the OpenVPN FAQ).
First we need to get OpenVPN installed. Most Linux distributions bring an OpenVPN package with them. Eg. for Debian based systems it is as simple as:
apt-get install openvpn
I'll assume that the OpenVPN package installs its configuration in /etc/openvpn/. If this is different for your platform, you have to adapt my paths accordingly.
Next we need to generate a key:
openvpn --genkey --secret /etc/openvpn/myhost.key
Copy this file to the second host, same path. Make sure it is only readable by root.
There are two device types supported by OpenVPN: tun and tap.
Tun devices receive raw IP packets and give them to a user space program. In the case of OpenVPN this program encrypts those packets and sends them on to the other end of the tunnel where they get decrypted and sent back to the tun device on that side. In other words a tun device behaves like a virtual Point-to-Point network connection. Usually OpenVPN uses IPv4 on those devices - IPv6 support is still experimental (as of mid 2009).
Tap devices use raw ethernet frames instead of IP packets. A tap device is like a virtual ethernet card - any packet sent to it goes through the tunnel and back up the ethernet stack on the other side. So an OpenVPN connection using tap is like a virtual ethernet bus with exactly two ethernet cards connected - one on each side of the tunnel. The downside of using tap is that for each packet 14 more bytes (the ethernet header) are used up, the upside is that we can use any protocol over it without having to think about OpenVPN support for it.
Therefore I will use tap in my examples below.
We have to spend some thoughts on network numbering now. I will assume that we have a /48 prefix for our network (eg. one provided by SixXS) - I will use 2001:db8:abba::/48 in my examples.
Each tunnel will use one /64 prefix for the virtual ethernet - I will use 2001:db8:abba:1000::/64 in the example below. In theory we could use a prefix with more than 64 bits, since the virtual ethernet is not automatically configured - but I don't recommend it: the configuration can cause severe headaches and a /48 has enough space for several thousand prefixes "wasted" on laptops. If your network is bigger than mine (more than one person and/or more than ten machines) you should document somewhere which prefixes are used for what.
I'll assume that OpenVPN is installed on the networks main gateway - otherwise the routing entries may need to be adjusted.
If we are using the OpenVPN tap device with IPv6 there is only very little configuration left (/etc/openvpn/myhost.conf):
dev tap secret myhost.key script-security 3 up /etc/openvpn/myhost.up
The actual work is done in the UP-script:
#!/bin/sh ifconfig $dev up ifconfig $dev add 2001:db8:abba:1000::1/64
The script must be executable. OpenVPN gives each script a number of variables that contain information about the virtual device - what we actually care about is the variable $dev that tells us the device name.
We first set the device up, so that it can accept further configuration. Then we give it its IPv6 address and netmask. This is already enough for the server side.
Now we only need to start it - in Debian based systems this happens automatically when /etc/init.d/openvpn start is called.
The client looks very similiar. Its /etc/openvpn/myhost.conf:
remote gateway.example.com float dev tap secret myhost.key script-security 3 up /etc/openvpn/myhost.up
The UP-script also looks very familiar:
#!/bin/sh ifconfig $dev up ifconfig $dev add 2001:db8:abba:1000::2/64 route -6 add 2000::/3 gw 2001:db8:abba:1000::1
Please note that the client gets a different IPv6 address - don't be shy, we've got plenty - this is necessary for the IPv6 stack to actually know the difference between the two tunnel end-points. In theory each end of the connection could get any number of IPv6 addresses - as long as each one is unique. The only address that can not be used is the one with all host bits set to 0 (2001:db8:abba:1000::0).
The new line with the route command tells the kernel where to direct any IPv6 traffic - I use 2000::/3 (the pool that all IP addresses come from for the next few decades) instead of the default route here in order to make sure we do not collide with any default route that the distributor might have set in his endless wisdom.
It is possible to put a full network behind an OpenVPN gateway (client). This is as simple as adding a route statement to the UP-script of the server. For example, if the client services the network 2001:db8:abba:2000::/64 the line would look like this:
route -6 add 2001:db8:abba:2000::/64 gw 2001:db8:abba:1000::2
The client would of course have to be configured as a router.
A few notes to firewall admins:
OpenVPN communicates on IPv4 UDP port 1194 (bound on both sides) per default. This can be changed if necessary - including the possibility to use TCP over HTTP-proxies. Please see the OpenVPN docu for details.
You need to add firewall rules in the IPv4 part of your firewall to let UDP port 1194 through. For the virtual device to function properly you need to add it to your IPv6 firewall just like any other ethernet device.
On modern Linux systems network devices can be renamed to make firewall configuration easier when dealing with dynamic devices. This renaming has to happen before the device goes up:
#!/bin/sh newdev=tap_myhost ip link set $dev name $newdev ifconfig $newdev up ifconfig $newdev add 2001:db8:abba:1000::2/64 route -6 add 2000::/3 gw 2001:db8:abba:1000::1