Back in v6

After quite a long time we are now back in the v6 world thanks to Hurricane Electric.
We lost our IPv6 connectivity when migrating our VPS from OpenVZ to KVM. There is no IPv6 on the newer OVH VPS 2016 although we had one on the older version. I don’t know why it is and when asked via a ticket they assured me that it would be available soon. This was months ago, still no IPv6, and I am not alone. This is becoming long and really awkward for OVH, supposed to be the 3rd hosting provider in the world.

Setting up the tunnel with HE was painless. You just configure a simple 6in4 (gif on BSD / sit on Linux) tunnel from your IPv4 to the endpoint they provide to you and your are done!

In the meantime we also configured the IPv6 prefix that we received from our ISP. I used ndppd, an NDP proxy daemon, so that our ISP modem believes that the IPv6 hosts are located on the same link and not one or more hop away (as they really are indeed, there is an intermediate router between our LAN and the modem). So we don’t need SixXS anymore which is great!

Source based routing

My two home servers are down for the moment. This also means that our two IPv6 SixXS tunnels are down which costs us 100 ISK per week. Argh! I need to get these up and running as soon as possible. Fortunately we have another VPS on Linux that can save us. So we just have to enable the two tunnels there and make sure that we can ping to/from both interfaces.

Setting up the two tunnels is easy. Use one configuration file per tunnel. Ensure that you change the parameters “tunnel_id” to the tunnel associated to this configuration file, one “pidfile” and “ipv6_interface” for each tunnel and “defaultroute” to false because we already have a default IPv6 route. Now you can start/stop each tunnel with:

aiccu start /etc/aiccu/tunnel0.conf
aiccu start /etc/aiccu/tunnel1.conf

aiccu stop  /etc/aiccu/tunnel0.conf
aiccu stop  /etc/aiccu/tunnel1.conf

Don’t forget to hack /etc/init.d/aiccu to start/stop both tunnel on each reboot. OK! So now ifconfig list the two interfaces, up and running sixxs0 and sixxs1. This is great but wait… Nobody outside can ping these interfaces. The tunnel must ping to be considered active by SixXS so we better get this running.

For now we have these three interfaces and IPs (not the actual names/IPs):

  1. net0 (2001::1) default
  2. sixxs0 (2a02::1)
  3. sixxs1 (2a02::2)

By default, all our IPv6 traffic goes through net0. However and unsurprisingly our ISP filters the traffic at the output of net0. So we cannot use this interface to answer the echo-requests. Actually, what we want is that traffic originating 2a02::1 goes through sixxs0 and from 2a02::2 goes through sixxs1. That is, one default route based on the source address.

Linux has long had support for multiple routing tables (CONFIG_IP_MULTIPLE_TABLES). Basically what we will do here:

  • Create two routing tables for each tunnel interface (sixxs0, sixxs1).
  • Each table will have a default route through its interface.
  • Lookup into one of the two tables according to the source IP.

You can find some relevant documentation in Linux Advanced Routing & Traffic Control, Chapter 4.

We first list the actual rules:

# ip rule list
0:  from all lookup local
32766:  from all lookup main
32767:  from all lookup default

We can see that we have three routing tables. One for the local addresses, the normal routing table (what you get with ip -6 route) and the fallback default table.
Let’s first check the local routing table (we are just curious):

# ip -6 route list table local
local ::1 via :: dev lo  proto none  metric 0  mtu 16436 advmss 16376 hoplimit 0
local 2a02::1 via :: dev lo  proto none  metric 0  mtu 16436 advmss 16376 hoplimit 0
local 2001::1 via :: dev lo  proto none  metric 0  mtu 16436 rtt 6ms rttvar 7ms cwnd 10 advmss 16376 hoplimit 0
local 2a02::2 via :: dev lo  proto none  metric 0  mtu 16436 advmss 16376 hoplimit 0
local fe80::1 via :: dev lo  proto none  metric 0  mtu 16436 advmss 16376 hoplimit 0
local fe80::2 via :: dev lo  proto none  metric 0  mtu 16436 advmss 16376 hoplimit 0
ff00::/8 dev net0  metric 256  mtu 1500 advmss 1440 hoplimit 0
ff00::/8 dev sixxs1  metric 256  mtu 1280 advmss 1220 hoplimit 0
ff00::/8 dev sixxs0  metric 256  mtu 1280 advmss 1220 hoplimit 0

So now you know what’s going on when you ping one of your local interfaces. But back to our point. We name our two new routing tables in /etc/iproute2/rt_tables:

# SixXS tables
200 sixxs0
201 sixxs1

Now we add the default route in each of these two tables:

ip -6 route add default dev sixxs0 table sixxs0
ip -6 route add default dev sixxs1 table sixxs1

And finally we use two rules to map the source address to the correct routing table:

# ip -6 rule add from 2a02::1 table sixxs0
# ip -6 rule add from 2a02::2 table sixxs1
# ip -6 rule list
0:  from all lookup local
16383:  from 2a02::1 lookup sixxs0
16383:  from 2a02::2 lookup sixxs1
32766:  from all lookup main
32767:  from all lookup default

It should be OK but let’s check that. We can ping from the sixxs interfaces:

ping6 -c1 -I 2a02::1
ping6 -c1 -I 2a02::2

We also check that we can ping our interfaces from another host:

ping6 -c1 2a02::1
ping6 -c1 2a02::2

Everything works, that’s great! Finally we just hack /etc/init.d/aiccu to configure the routing tables on each reboot. Note that you need to sleep a bit when you issue the aiccu start because the daemon needs a bit of time to enable the tunnels. Also note that you must be careful when you test your script (quoting the SixXS FAQ):

“If a client connects more than 4 times in 60 seconds (1 minute) the client will not be allowed to connect again for the next 5 minutes. In case this threshold is exceeded more than once in 24 hours a client will be automatically blocked for a week.”

As you can guess, I have been blocked. Oops!

Raspberry Pi Ethernet speed

I’ve been a long time user of IPv6 tunnels from SixXS to provide an access to the IPv6 Internet behind my ISP. These tunnels also allow me to use static IP addresses for my home servers along with static AAAA records and this is cool !

Currently I use several Debian GNU/Linux based soft-routers with two (100 and 1000) Ethernet ports. These are often running on old recycled laptops which consumes around 40 Watts of power at peak level. Next to that the ARM Raspberry Pi platform consumes around 3 Watts of power (though I still have to measure it by myself). So I thought about replacing all my home-routers with those.

However the Raspberry Pi model B uses a SMSC LAN951x chip which includes the USB 2.0 Hub and an 10/100 Ethernet controller on top of it (which is known as smsc95xx in the Linux kernel). My  main concern was that it would not be fast enough to support the IPv6 tunnel at its peak bandwidth of 60Mbps (that is 30Mbps downstream/upstream).

I already use one RPi as an experimental home-router here. Our Internet bandwidth is a bit slow (12Mbps) so the USB-Ethernet  shouldn’t be a problem. I’ve conducted quick tests with IPerf and as you can see the results are pretty good as long as it doesn’t involve I/O on the RPi.

Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
[ 4] local port 5001 connected with port 37373
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.1 sec 114 MBytes 94.4 Mbits/sec
[ 5] local port 5001 connected with port 37376
[ 5] 0.0-10.1 sec 114 MBytes 94.5 Mbits/sec
[ 4] local port 5001 connected with port 37377
[ 4] 0.0-10.1 sec 114 MBytes 94.6 Mbits/sec
[ 5] local port 5001 connected with port 37378
[ 5] 0.0-10.1 sec 114 MBytes 94.5 Mbits/sec