LowEndBox - Cheap VPS, Hosting and Dedicated Server Deals

Routing IPv6 from a HE tunnel to VPS (CentOS host)


Last week I wrote a tutorial about routing IPv6 from a HE tunnel to VPS on Ubuntu. As promised, this week the CentOS version!

A couple of weeks ago I wrote a tutorial where I explained how to set up a Hurricane Electric IPv6 tunnel on your KVM VPS. While this is a nice solution, it still requires the customer to fix something that should have been done by the provider. So, I thought, let’s write a tutorial for providers how to fix this for the customer.

In this tutorial I will show you how to set up a bridged network interface and radvd to get the VPS on a host IPv6 connected. After that, you can route /64 blocks to individual VPS. By using the routed /48 you can get from HE, you can assign up to 65535 /64 blocks to your customers (the other one is used for SLAAC and routing). What’s better than to promise a customer 18,446,744,073,709,551,616 IPv6 addresses for _free_ and all the while being ready for the future of the internet?!

I’ve tested this tutorial on a Xen hosts with Xen PV guests. The Xen host was a KVM machine. The Xen host was running CentOS 6.5, 64-bit. I assume you’ve set up a HE IPv6 tunnel, according to my guide (you can request the free, routed /48 from the tunnel overview page at HE). You also need at least one VPS that uses the network bridge. For KVM and Xen, this is usually the case. For OpenVZ you should have set this up if you’re using veth networking.

Editorial note: the Ubuntu host version of this guide can be found here.

Bridged network interface and the /48

First thing to do, if you haven’t already, is create a network bridge for your VPS. In my case, I called it xenbr0 as it’s a bridge for Xen. Open up the /etc/sysconfig/network-scripts/ifcfg-xenbr0 file and add the following to it:


What we’ve done here, is create a network bridge with an IPv4 configuration. In order to get this to work, we need to add an interface to it.

Change the eth0 config in /etc/sysconfig/network-scripts/ifcfg-eth0 to the following:


What we’ve done here is remove all unnecessary information and add this interface to xenbr0. From now on, xenbr0 moves all traffic over the physical eth0 device (which is in this case virtualized as I am doing this on a KVM). If you have more physical network ports, you can add them to xenbr0 as well from their respective config files and basically traffic will go over them as well (without getting into details).

This will ensure eth0 configuration is left to the bridge interface. Now either reboot or restart the network:

/etc/init.d/network restart

If you now run ‘ifconfig’, it should be different from before and look like this (this includes the HE IPv6 tunnel, I’ve skipped other devices):

eth0 Link encap:Ethernet HWaddr 00:16:3C:9B:B5:B7
inet6 addr: fe80::216:3cff:fe9b:b5b7/64 Scope:Link
RX packets:874172 errors:0 dropped:173 overruns:0 frame:0
TX packets:61426 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:245980205 (234.5 MiB) TX bytes:5042623 (4.8 MiB)
Interrupt:10 Base address:0x4000

sit1 Link encap:IPv6-in-IPv4
inet6 addr: 2001:db8:1f0a:3ec::2/64 Scope:Global
inet6 addr: fe80::d453:3f2a/128 Scope:Link
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

xenbr0 Link encap:Ethernet HWaddr 00:16:3C:9B:B5:B7
inet addr: Bcast: Mask:
inet6 addr: fe80::216:3cff:fe9b:b5b7/64 Scope:Link
RX packets:13994 errors:0 dropped:0 overruns:0 frame:0
TX packets:313 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:723098 (706.1 KiB) TX bytes:61247 (59.8 KiB)

That’s all for the bridge for now. We’ll return to it later to add some routing configuration.

Next, we need to make the sure /48 you got from HE is routed properly on your host, so we can use one of the /64 blocks from it for radvd. The /48 is routed against your Client IPv6 Address, which ends with ::2. You also have a routed /64 available, which is routed the same way as the /48, but we do want to use the /48 here so you can assign /64-blocks to individual VPS.

We need to add the following lines to the he-ipv6 device in /etc/sysconfig/network-scripts/route6-sit1:

2001:db8:1f0a::/48 dev xenbr0

This line tell CentOS to route the entire 2001:db8:1f0a::/48 address range over device xenbr0, the one we’ve just set up, when the sit1 interface comes up. It also removes the route again when the sit1 interface goes down. Now bring down and bring up sit1 to activate this net configuration:

ifdown sit1; ifup sit1

As a final step, enable IPv6 networking and IPv6 forwarding in /etc/sysconfig/network. Add these two lines to that file:


And restart the network to complete this:

/etc/init.d/network restart

Now let’s get started on getting your VPS initial IPv6 connection!


radvd is an IPv6 Router Advertisement Daemon. It responds to router solicitation queries that hosts send when trying to configure IPv6. radvd answers with a router advertisement message. Router solicitation and advertisement are part of the Neighbor Discovery Protocol that (amongst other things) facilitates Stateless Address Autoconfiguration (SLAAC). It makes sure the host has the “upper” 64 bits of the IPv6 address. The “lower” 64 bits are generated and based upon the MAC address of the host’s network interface for which the IPv6 address is requested.

We’re going to set up radvd to respond to solicitation queries and provide the upper 64 bits of the IPv6 address to the VPS. From that moment on, the VPS are IPv6 connected. The complete address that results from that process is then going to be used to route a /64 against.

Install radvd first:

yum install radvd

Open up /etc/radvd.conf (this file usually doesn’t exist yet) and past the following into it:

interface xenbr0
AdvSendAdvert on;
prefix 2001:db8:1f0a:ffff::/64
AdvOnLink on;
AdvAutonomous on;

I’ll go through this line-by-line.

interface xenbr0

This defines on which interface radvd is active. In this case it is our network bridge which we just added. The following configuration block (in between the curly braces) is applied to that interface.

AdvSendAdvert on;

This tells radvd to send router advertisement messages, either in response to a router solicitation query or periodically to announce its presence.

prefix 2001:db8:1f0a:ffff::/64

This is a very important line. This is a /64 we’ve taken from the /48 we got from HE. I’ve chosen to use ‘ffff’, the “highest” possible “number” in the range (from ‘0000’ to ‘ffff’). This /64 is used as an address prefix for your VPS (the upper 64 bits). You could choose another one here, of course. But since we’re going to be assigning /64-blocks, we might as well start with ‘1’ there (2001:db8:1f0a:1::/64, 2001:db8:1f0a:2::/64 and so on).

Next, there are the two last options:

AdvOnLink on;
AdvAutonomous on;

‘AdvOnLink’ makes sure you are responding to solicitation requests only on the interface you’ve just specified. ‘AvdAutonomous’ tells radvd that SLAAC should be allowed.

Now we’ve got radvd configured, start it:

/etc/init.d/radvd start

And make sure it starts with CentOS:

chkconfig radvd on

If you now reboot any of your VPS, they should be handed an IPv6 address! That address should work out of the box on an Ubuntu VPS, with CentOS it depends on which version/template you’re using.

Routing /64-blocks

The final part is actually routing /64 address blocks to your VPS. For this process, you need to know the IPv6 address of the virtual machine you’re going to route the /64 to. This is the address the VPS got from radvd. For the address to be active, the VPS will have to be rebooted (or it’s networking interface restarted).

Now, the next step is a bit dependent upon your situation. I’ve done this on a Xen host, so I had to do the following to obtain the SLAAC-obtained IPv6 address of my Xen domU. For other virtualization types, it may be different. I listed my domU’s network information with:

xm network-list centos

This will output something like this:

Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path
0 0 00:16:3e:72:39:de 0 4 10 768 /769 /local/domain/0/backend/vif/8/0

The MAC address is what I’m looking for. I’m going to use the MAC address to calculate the lower 64 bits, so I can create the full address and use that for routing. I’ve used this calculator: http://silmor.de/ipaddrcalc.html#ip6. I put in the 48 bit MAC and converted that to a Host ID:

MAC: 00:16:3e:72:39:de
Host ID: ::216:3eff:fe72:39de

If I combine that Host ID with the prefix from radvd, I get the following IPv6 address:


Which is the IPv6 address of the virtual machine you’re going to route the /64 to. Try pinging the address to see if it works:

mpkossen@xen01:~$ ping6 2001:db8:1f0a:ffff:216:3eff:fe72:39de
PING 2001:db8:1f0a:ffff:216:3eff:fe72:39de(2001:db8:1f0a:ffff:216:3eff:fe72:39de) 56 data bytes
64 bytes from 2001:db8:1f0a:ffff:216:3eff:fe72:39de: icmp_seq=1 ttl=64 time=0.509 ms
64 bytes from 2001:db8:1f0a:ffff:216:3eff:fe72:39de: icmp_seq=2 ttl=64 time=0.314 ms
64 bytes from 2001:db8:1f0a:ffff:216:3eff:fe72:39de: icmp_seq=3 ttl=64 time=0.374 ms
64 bytes from 2001:db8:1f0a:ffff:216:3eff:fe72:39de: icmp_seq=4 ttl=64 time=0.388 ms
— 2001:db8:1f0a:ffff:216:3eff:fe72:39de ping statistics —
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.314/0.396/0.509/0.072 ms

Of course, when the MAC address changes, the SLAAC-obtained IP address changes. So make sure the VPS always has the same MAC address. We could have entered the VPS, of course, but I assumed you couldn’t and still wanted to get the SLAAC-obtained IPv6 address.

Now, with that address, we can route a /64 to the virtual machine. On your host, add the following line to the xenbr0 block in /etc/sysconfig/network-scripts/route6-xenbr0:

2001:db8:1f0a:1::1/64 via 2001:db8:1f0a:ffff:216:3eff:fe72:39de dev xenbr0

What we’ve done here, is route the 2001:db8:1f0a:1::/64 via the SLAAC-obtained address 2001:db8:1f0a:ffff:216:3eff:fe72:39de on device xenbr0. You should also add the route manually once, so you don’t need to restart your network interface to get it up:

ip -6 r a 2001:db8:1f0a:1::1/64 via 2001:db8:1f0a:ffff:216:3eff:fe72:39de dev xenbr0

From this moment on, all traffic to the 2001:db8:1f0a:1::/64 will be sent to your VPS. Your VPS still needs to handle traffic, though. On the guest, an IPv6 from the /64 needs to be configured and routed.

So let’s do that. Inside the VPS, run the following two commands (or put them in a wiki for your customers):

ip -6 address add 2001:db8:1f0a:1::1/64 dev eth0
ip -6 route add default via 2001:db8:1f0a:ffff::1 src 2001:db8:1f0a:ffff:216:3eff:fe72:39de

The first line adds and IP address to eth0, in this case the first address from the routed /64. The second line adds a default route for IPv6 traffic. It routes it via the gateway address of radvd and uses the SLAAC-obtained address to get there.

You should configure the address and add the last line to the network configuration of your VPS, to ensure the address and route are still there after a reboot. Add the following lines to/etc/sysconfig/network-scripts/ifcfg-eth0:


Finally, edit/etc/sysconfig/network-scripts/route6-eth0 to add the route:

default via 2001:db8:1f0a:ffff::1 src 2001:db8:1f0a:ffff:216:3eff:fe72:39de

And you’re done! Congratulations, it was a long run!

Final notes

While the above is a great solution for customers to get IPv6 connectivity (even if it is without the /64), it does require both work and knowledge from the provider. SolusVM is probably not going to help you with this, because of the way they’ve implemented IPv6. This is thus something the provider should do manually (could be automated a bit by scripting some parts of it). However, it is, in my humble opinion, important to have IPv6 and it would really add value to your customers.

Besides, it’s really cool if you get this setup working! It becomes easier to take a large KVM, load an OpenVZ or Xen kernel on it and create a large number of IPv6-only machines!



  1. Amazing script..I love it…someone would not complain about the IPv6 now…

    June 23, 2013 @ 8:21 am | Reply
  2. It’s great that it’s very detailed and step by step. Easy for anyone to pick up.

    June 23, 2013 @ 2:09 pm | Reply
  3. Prashant:


    I need configure ipv6 dhcp server with 112 perfix..When i configured ipv6 Dhcp server on centos.@ my client box it showing xxxx:xxxx:xx:xxxx:3000:50/64.even i have diff’nt subent in ipv6 for ex:xxxx:xxx:xxx:x:4000:50..

    July 15, 2013 @ 5:26 am | Reply

Leave a Reply

Some notes on commenting on LowEndBox:

  • Do not use LowEndBox for support issues. Go to your hosting provider and issue a ticket there. Coming here saying "my VPS is down, what do I do?!" will only have your comments removed.
  • Akismet is used for spam detection. Some comments may be held temporarily for manual approval.
  • Use <pre>...</pre> to quote the output from your terminal/console, or consider using a pastebin service.

Your email address will not be published. Required fields are marked *