Tutorial: Setting up 6in4 IPv6 on an Ubuntu router

Despite lack of ISP support, I gave myself IPv6 network access by making my router switch IPv6 packets over an 6in4 tunnel. My tunnel provider is Hurricane Electric.

This tutorial is about setting up IPv6 tunnelling and routing, NDP router advertisement and tackling dynamic address. Not all part of this tutorial will fit your needs.

Part 1: Get Packets Through

Here is the information of my IPv6 tunnel:

  • IPv4 remote endpoint:
  • IPv6 remote endpoint: 2001:470:c:472::1/64
  • IPv4 local endpoint: (dynamic address)
  • IPv6 local endpoint: 2001:470:c:472::2/64
  • Routed prefix: 2001:470:d:472::/64, 2001:470:f10a::/48 (using the /48 block for internal network)

I am going to use my actual configuration information as demo files.

Step 1: Set up IPv6 Tunnel

Add the following (change according to your tunnel info though) to your /etc/network/interface file:

auto sit1
iface sit1 inet6 v4tunnel
 address 2001:470:c:472::2 # local endpoint v6
 netmask 64 # local endpoint net mask
 gateway 2001:470:c:472::1 # remote endpoint v6
 endpoint # remote endpoint v4
 ttl 255
 up ip -6 route add default dev sit1
 down ip -6 route del default dev sit1

This sets up the sit1 interface and configures it to be your IPv6 default route.

Step 2: Enable IPv6 switching

Uncomment (or add) the following line in /etc/sysctl.conf file:


This tells the kernel that forwarding IPv6 packets is okay (and disables address auto-configuration, which will be addressed later)

Step 3: Set up IPv6 LAN

Add a section to your /etc/network/interface file below the corresponding IPv4 configuration:

iface eth2 inet6 static # eth2: LAN interface
 address 2001:470:f10a::1 # routed address block
 netmask 64 # block is no smaller than /64

If you have a block bigger than /64 you can cut it up into multiple pieces and use them here, as long as it is no smaller than /64. I cut my /48 up so that I can have address space for future expansion, like NAT64.

Step 4: Make the tunnel follow you

We have dynamic IP, which is a beast against 6in4 which requires preconfigured endpoints. We need a script to mitigate that:


IPV4ADDR=$(ip addr show dev ppp0 | grep inet | sed "s/^ *//" | cut -f 2 -d " ") # ppp0 is your Internet interface with public address.
PASSKEY=$(printf ***password*** | md5sum | cut -f 1 -d " ")
USERID=***user-id*** # not your user name

wget --no-check-certificate -q -O /dev/null "https://ipv4.tunnelbroker.net/ipv4_end.php?ip=$IPV4ADDR&pass=$PASSKEY&user_id=$USERID&tid=$TUNNELID"

Replace your user ID, tunnel ID and password accordingly. The script can be called periodically by cron(8), upon boot in /etc/rc.local, or called with a DDNS update. I use latter with inadyn(8).

Now reboot your router so the changes takes effect. To test, after reboot, on your router, run:

ping6 2001:4860:4860::8888

which pings Google Public DNS servers (will come back later) over IPv6. This can be a connectivity test for IPv6.

Part 2: Get Known

Now we need to set other computers in our LAN up to use IPv6. We are not typing like a psycho on each and every computer but using something akin to DHCP to IPv4: NDP Router Advertisments. This requires this software package:

apt-get -y install radvd

Step 5: Advertise this IPv6 router

Write a file at /etc/radvd.conf like:

interface eth2
 AdvSendAdvert on;
 prefix 2001:470:f10a::/64
 AdvOnLink on;
 RDNSS 2001:4860:4860::8888 2001:4860:4860::8844 {};

Remember the content should match your /etc/network/interface file.

Now restart radvd service:

service radvd restart

After a few minutes your LAN devices should be able to pick up an IPv6 address and the aforementioned connection test should pass on your LAN devices too. For now, the IPv6 should be working and try visit https://ipv6.google.com/ on your device. From this point on, that is extra bells and whistles.

Part 3: Make a Mirror

More specifically, a mirror DNS server that queries Google servers over IPv6, with DNSSEC on. More importantly, if you need to accept IPv6-only devices you will need this (and the following part.) We will need this classic software package here:

apt-get -y install bind9

Step 6: Set up DNS mirroring

Add this to options section of /etc/bind/named.conf (on Ubuntu 14.04, this section is in a separate file /etc/bind/name.conf.options):

forwarders {

This asks BIND to forward requests to Google servers, preferring IPv6.

Then add your DNS server to both IPv4 DHCP DNS server list and IPv6 radvd RDNSS list, before all other servers. This forces all hosts prefer this server as it will relay requests over IPv6.

Restart BIND, DHCP server and radvd:

service bind9 restart
service isc-dhcp-server restart
service radvd restart

(It also make your days easier if a major IPv4 DNS pollution event occurs in certain countries.)

Part 4: Nobody is Left Down

That is, IPv6-only hosts. This will require NAT64/DNS64. Previously we set up BIND and it have DNS64 feature as well, and NAT64 can be configured with:

apt-get -y install tayga

Step 7: Set up NAT64

Configure tayga as its configuration file /etc/tayga.conf is pretty well documented. Note your choice of mirrored /96 prefix as it should match what is configured later in BIND. I used 2001:470:f10a:d64::/96 prefix, sliced from my /48.

Restart tayga:

service tayga restart

And it should work by now as you can ping:

ping6 2001:470:f10a:d64::808:808

This pings over IPv4, but using NAT64 address. If it works, proceed.

Step 8: Set up DNS64

BIND have DNS64 feature that can be turned on by adding the following to options section:

dns64 2001:470:f10a:d64::/96 {
 clients { any; };

Remember the prefix must match.

Restart BIND:

service bind9 restart

Now try resolve an IPv4-only address as IPv6:

dig www.baidu.com aaaa

All done! Happy surfing IPv6 Internet 🙂

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.