History and blahblah
Since several years I am dealing with IPv6. To be more exact, this is since about 2007 when we started to talk about the DNS-leak-problem of Tor. At the end of 2008 way came up with Onioncat at the 25C3. Although it did not solve the original problem it still is a cool VPN solution and — much more important withing this context — it natively supports IPv6 (and IPv4 is just an add-on).
Of course I knew about IPv6 before. A kind of knowledge that share most people: it is some kind of new version of IP but basically it behaves the same. But since I intended to write code which creates L3 IPv6 packets and L2 frames a had to delve into details.
However, this is not the story I’m going to tell you. Nevertheless, then I decided to get a connectivity to the IPv6 Internet. Unfortunately, there was and still is merely no ISP in Austria (except ACO Net) which provides IPv6 but luckily there is such a thing like IPv6 tunnel brokers.
In the following I describe a not so trivial IPv6 setup which means it is not just a tunnel and an Ethernet at its end. In this case I have various OSs, firewalls, NAT, remote locations, and VPNS.
Before I start I would like to explain the general network setup. Have a look at the network map. The cloud on the left top is the IPv4-based Internet. There is one central location connected through the OpenBSD firewall G and a remote location connected through the DSL router J. Behind both devices there are private RFC1918 networks and everything is setup correctly to allow hosts behind to access the Internet. On the central location there is a FreeBSD server (F) which terminates the tunnels and a Cisco router (I) which connects other networks. On the remote locaton there is the Linux server E.
The external IP address of G is 126.96.36.199,1 the IP address of the central server G is 192.168.10.10, and the IP address of the central router I is 192.168.10.5.
The first thing to do is register at a tunnel broker (in this case it is SIXXS) and request a tunnel. You have to supply the IP address your tunnel end point and the type of protocol you would like to run the tunnel. I chose protocol 41 which is 6-in-4 encapsulation. My tunnel end point IP address is 188.8.131.52. This is the official IP address as seen from the tunnel broker. Of course this is not very the tunnel really terminates. I run NAT on the firewall and the tunnel actually terminates on the server F.
You will get an email of the tunnel broker which contains the external tunnel IPv4 addresses (184.108.40.206 and 220.127.116.11) and the IPv6 address on the inner side of the tunnel (my side 2001:1234:5678:9abc::2/64, their side 2001:1234:5678:9abc::1/64). If you do not just want to supply IPv6 to a single network, you will have to register a subnet. I did so. In my case I reveived the subnet 2001:dead:beef::/48.
First add the following rules to the OpenBSD firewall G to let protocol 41 packets pass and redirect them.2
nat on $ext_if from 192.168.10.10 to any -> 18.104.22.168
rdr pass inet proto 41 to 22.214.171.124 -> 192.168.10.10
pass proto 41 to 192.168.10.10
Configure IPv6 Tunnel
Now configure the IPv6 tunnel on the central server. There is a good explanation in the Sixxs-FAQ. Additionally, I added the following two lines to my rc.conf because the local IPv6 address of the tunnel was not reachable because there was no entry in the routing table. I am not sure if this is a bug or it is by intenstion. However, I simply added the route.
ipv6_route_ltun="2001:1234:5678:9abc::2 -prefixlen 128 -interface lo0"
After this the tunnel is set up. Test it. You should be able to ping6 the local and the remote IPv6 address.
Configure VPN Tunnel
Let’s configure the OpenVPN tunnel between the remote and the local server. Actually, there is a quick HOWTO found on the OpenVPN page but I want to point out that it may not work with IPv6. According to the OpenVPN page, IPv6 is not supported before version 2.2-RC2. But this is no problem! OpenVPN always supported IPv6 if used in TAP mode. This is because TAP mode forwards all L2 frames, hence, everything above layer two is transported. The following shows may server and client OpenSVPN configurations:
# OpenVPN server configuration (on FreeBSD)
keepalive 10 60
# OpenVPN client configuration (on Linux)
keepalive 10 60
The keepalive is used to avoid that the states of neither the DSL router nor the firewall will timeout. As you can see, I do not configure IP addresses. I use the external script if.up to bring up the interface and configure it for IPv6. In the following you find the two scripts.
# server side if.up script
/sbin/ifconfig $dev up
/sbin/ifconfig $dev inet6 2001:dead:beef:f000::1/64
/sbin/route get -inet6 2001:dead:beef::/64 >/dev/null 2>&1
if test $? -ne 0 ; then
/sbin/route add -net -inet6 2001:dead:beef::/64 2001:dead:beef:f000::2
# client side if.up script
/sbin/ifconfig $dev up
/sbin/ifconfig $dev inet6 add 2001:dead:beef:f000::2/64
/bin/ip -6 route add ::/0 via 2001:dead:beef:f000::1
As you can see I add routes. In case of the server I route one /64 subnet down to the remote location and in case of the client I setup the default route ::/0 back to the server.
Run both OpenVPNs and it should immediately come up. If not, you might comment out the configuration line “daemon” and run it directly on the command line to see debugging output.
Provide IPv6 to the Remote Clients
Now we want to provide IPv6 to the clients on the LAN in the remote location. The IPv6 address of the Ethernet interface is configure statically in /etc/network/interfaces. Please note that the default gateway is setup dynamically in the if.up script by OpenVPN and not in the static network configuration. This is because the route cannot be set before the tunnel is up.
# /etc/network/interfaces [snippet]
iface eth0 inet6 static
The next thing that we need is radvd. This daemon announces IPv6 adresses to the local network. Clients will then auto-configure IPv6 address. Install it with `aptitude install radvd` (on Debian or Ubuntu).
Run radvd (`/etc/init.d/radvd start`) and all IPv6-enabled clients on this Ethernet network should immediately receive an IPv6 address.
Now let’s configure routing between the central server and the Cisco router I. First, on the central server we have to add an IPv6 address to the Ethernet were the router is connected to and we addna route to the Cisco for the network which will be behind the router. The network between the server and the router will be 2001:dead:beef:1::/64 and the networks on the other interface of the router will be chosen from the subnet 2001:dead:beef:100::/56. In rc.conf I add it like this:
ipv6_route_fhnet="2001:dead:beef:100:: -prefixlen 56 2001:dead:beef:1::1"
ipv6_ifconfig_em0="2001:dead:beef:1::2 prefixlen 64"
Please note that the variable ipv6_static_routes was already mentioned before! Now login to the Cisco router. First we have to enable IPv6 routing globally.
Now we set the IPv6 address on the Fastethernet 0/0 which is the link to the server. Further I disable router advertisements to avoid that other hosts on this network will receive an IPv6 address by the auto-configuration mechanism. Finally we set a default route back.
interface fast 0/0
ipv6 nd suppress-ra
ipv6 address 2001:dead:beef:1::1/64
ipv6 route ::/0 2001:dead:beef:1::2
Configuration of further Ethernets and routes is up to your personal needs and is not explained here.
I hope that there are hints for everybody. Please note that I did not deal with any security issues within this text. Of course you should take that into account for your setup!
Although it is not guaranteed, you should also note that the packets traveling through the tunnel will most probably not be captured by any data retention system as long as they are in the IPv6 tunnel. More specifically this means that if you are browsing IPv6-enabled sites and the servers reside outside your country no national ISP will “see” the traffic except the IPv4 tunnel packets. Of course, the traffic is neither invisible nor encrypted which means that if somebody in between sniffs your 6in4 tunnel packets, he can see everything very well!