LowEndBox - Cheap VPS, Hosting and Dedicated Server Deals

How to Setup An HE Tunnel to VPS (Ubuntu Host)

Tags: Date/Time: June 16, 2013 @ 2:27 pm, by Maarten Kossen


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 the latest LTS of Ubuntu (12.04), 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: I’m writing this tutorial for Ubuntu. Next week I will write the one for CentOS. Due to how different these two “types” of distributions work, I found it harder to combine this subject into one guide, as it covers multiple topics.

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/network/interfaces file and add the following to it:

# Xen bridge
auto xenbr0
iface xenbr0 inet static
bridge_ports eth0

What we’ve done here, is create a network bridge with as port eth0. This means that this virtual network interface 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 here and basically traffic will go over them as well (without getting into details).

We’ve also configured the IPv4 address of eth0 under xenbr0. This bridge will, from now on, act as your primary network interface. This means that the current eth0 configuration is not needed any more. Change the eth0 config to the following:

# The primary network interface
auto eth0
iface eth0 inet manual

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

sudo ifdown eth0 && sudo ifup eth0 && sudo ifup xenbr0

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:6e:ae:42
inet6 addr: fe80::216:3cff:fe6e:ae42/64 Scope:Link
RX packets:742142 errors:0 dropped:0 overruns:0 frame:0
TX packets:303359 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:141084239 (141.0 MB) TX bytes:66993159 (66.9 MB)

he-ipv6 Link encap:IPv6-in-IPv4
inet6 addr: 2001:db8:1f0a:3ec::2/64 Scope:Global
RX packets:65958 errors:0 dropped:0 overruns:0 frame:0
TX packets:38902 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:83514750 (83.5 MB) TX bytes:3924142 (3.9 MB)

xenbr0 Link encap:Ethernet HWaddr 00:16:3c:6e:ae:42
inet addr: Bcast: Mask:
inet6 addr: fe80::216:3cff:fe6e:ae42/64 Scope:Link
RX packets:390266 errors:0 dropped:0 overruns:0 frame:0
TX packets:210857 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:110188811 (110.1 MB) TX bytes:48526200 (48.5 MB)

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/network/interfaces:

up ip -6 route add 2001:db8:1f0a::/48 dev xenbr0
down ip -6 route del 2001:db8:1f0a::/48 dev xenbr0

These lines tell Ubuntu to route the entire 2001:db8:1f0a::/48 address range over device xenbr0, the one we’ve just set up, when the he-ipv6 interface comes up. It also removes the route again when the he-ipv6 interface goes down.

Your final he-ipv6 configuration should look like this:

# HE IPv6 tunnel
auto he-ipv6
iface he-ipv6 inet6 v4tunnel
address 2001:db8:1f0a:3ec::2
netmask 64
up ip -6 route add default dev he-ipv6
up ip -6 route add 2001:db8:1f0a::/48 dev xenbr0
down ip -6 route del 2001:db8:1f0a::/48 dev xenbr0
down ip -6 route del default dev he-ipv6

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:

sudo apt-get 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, restart it:

 sudo service radvd restart

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.

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:

sudo xm network-list ubuntu

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/network/interfaces:

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

So it looks like this:

# Xen bridge
auto xenbr0
iface xenbr0 inet static
bridge_ports eth0
up ip -6 r a 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:

sudo 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):

sudo ip -6 address add 2001:db8:1f0a:1::1/64 dev eth0
sudo 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:

auto eth0
iface eth0 inet6 static
address 2001:db8:1f0a:1::1
netmask 64
gateway 2001:db8:1f0a:ffff::1
up ip -6 route add 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!

Maarten Kossen was the administrator of LowEndBox from 2013 to 2015, and brought many ideas and improvements to the website during his leadership. Today he is member of our community and LowEndTalk.


  1. Robert:

    Do you have any email where i can contact you? I need this done for me how much you charge for this setup?


    June 18, 2013 @ 5:36 pm | Reply
  2. elgs:

    You didn’t mention radvd should be install on host or vm.

    September 22, 2015 @ 7:29 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 *