IP6to4 tunnel

This page applies to Linux distributions, Ubuntu 10.04 to be specific. It deals with 6to4 tunneling, not with 6in4, Teredo tunneling, or other schemes.

For a quick idea of how 6to4 and similar schemes work, check this pretty picture and imagine that you're in that pink "IPv6 island". (The corresponding article has a quite weird setup for reading the text.)

Use the following script to setup a 6to4 tunnel for IPv6 support, one of several options to get IPv6 when your ISP only provides you with IPv4 access. Read the comments in it on how to ensure that IPv6 addresses are preferred in programs using libc (libc6).

You should probably not use this unless you have a 6to4 relay nearby… :-) In my case my ISP provides for this. To see what's available to you (although you may not know who is operating it…), try:

$ ping
$ traceroute

You can also use mtr to do both at the same time.

Note 1: someone might just put up a 6to4 relay that does not answer pings etc. to itself, so the above command(s) may not give a definite indication. That said I'd prefer having one that does.

Note 2: that this goes both ways, since the host you are trying to reach may not have IPv6 capable apparatus nearby. Also, if you attempt to use a 6-to-4 tunnel for latency-critical applications like FPSers and such, you're on your own. :-)
(I doubt IPv6 usage is widespread among gaming servers, though, but who knows…)

Note: do not edit gai.conf (as described below) unless you want to enforce IPv6 usage wherever possible. The default of Ubuntu 10.04 seems to be to prioritize native IPv6 connections and IPv4 connections over a 6to4 tunnel. IPv6-only sites should work fine either way, try e.g. ipv6.google.com to see if your setup works.


# Based on: http://www.uibk.ac.at/linuxdoc/LDP/HOWTO/Linux+IPv6-HOWTO/configuring-ipv6to4-tunnels.html
# Uses the first available 6to4 relay (::
# Also adjust /etc/gai.conf if you want to enforce IPv6 preference (precedence).
# One way to do this (in Ubuntu 10.04) would be to disable (comment out) all the lines and
#   add this: (without the comment sign of course)
#   label 2000::/3       0
# Note that gai.conf should be read by glibc, so there's no need to reboot or so. However, depending on the situation
#   you may need to restart your application to get the changes to take effect.
# You can also test this by means of a C program (which, at least for its own purposes re-reads gai.conf implicitly), found on:
#   http://linux-hacks.blogspot.com/2008/04/default-address-selection-part-1.html
# Invoke it with a hostname that maps to both IPv4 and IPv6 to see their relative priority (addresses with higher priority are listed first).

IPV4_ADDRESS=`ifconfig $DEV | grep "inet addr" | sed 's/Bcast.*//' | sed 's/.*inet addr://'`
OUR_IPV6_GW=`printf "2002:%02x%02x:%02x%02x::1" $IPV4_ADDRESS_REFORMATTED`

TTL=30 # TODO what's a good setting here?

function start_tunnel
  /sbin/ip tunnel add tun6to4 mode sit ttl $TTL remote any local $IPV4_ADDRESS
  /sbin/ip link set dev tun6to4 up
  /sbin/ip -6 addr add $OUR_IPV6_GW/16 dev tun6to4
  /sbin/ip -6 route add 2000::/3 via :: dev tun6to4 metric 1

  # /sbin/ip -6 route add 2000::/3 via 2002:c058:6301::1 dev tun6to4 metric 1 # this may be needed instead of the previous line on some OSes

function stop_tunnel
  /sbin/ip -6 route flush dev tun6to4
  /sbin/ip link set dev tun6to4 down
  /sbin/ip tunnel del tun6to4

function show_invocation
  echo "Invocation: $0 [start|stop]"
  exit 0

if [ $# -ne 1 ]


case "$ARG" in
    echo "Starting."
    echo "Stopping."

(Download it!)


  • Again, the tunneling could possibly lead to performance problems. Also read any reservation(s) that may be listed in the comments in the script above.
  • This is tested in Ubuntu 10.04. Other distributions may handle this slightly differently.
  • If you want this to be loaded on boot, put the script in /root or some root-writable-only directory and add a call to it from /etc/rc.local . Alternatively you may want to use /etc/network/ifup.d , see the Ubuntu tips page.
  • Some applications, if written in that way, might fail to prioritize IPv6 even if gai.conf is setup properly. In this case you may need to try application-specific workarounds.
  • The "label 2000::/3 0" row is what I found to be working. Perhaps this is not the full story.
  • I have not tested if low-level operations such as DNS lookups etc. are done via IPv6 if available. I only have IPv4 DNS servers available, and I have not tested this.
  • This text describes how to setup a tunnel for one host. I've not yet tried to set up more hosts.

Troubleshooting tips

  • If you want to do something like /etc/init.d/networking restart , you may need to use the script to stop the tunnel first. You may want to use /etc/network/ifdown.d , see the Ubuntu tips page.
  • There's no way to re-read gai.conf (as far as I can tell) globally. You can only reload these settings on an application-by-application basis, e.g. restarting Firefox. Use the aforementioned C program to verify that gai.conf is satisfactory, then restart your application if necessary.

If there's no change indicated by the C program, try backing up gai.conf and placing only this line in it:

label 2000::/3 0

Assuming the C program was compiled to test.bin , we should get something like:

$ ./test.bin www.stacken.kth.se
family:10 socktype: 1 protocol:  6 addr:2001:6b0:1:ea:202:a5ff:fecd:13a6(28)
family: 2 socktype: 1 protocol:  6 addr:

when IPv6 is prioritized (since it's listed first).

You can also try:

lynx -dump http://whatismyv6.com/

to get an indication (not using Firefox or so as we'd have to restart it). This will display whichever address is used in fetching it (IPv4 or IPv6).

If you only want to see your IPv6 address, type:

ifconfig tun6to4

You should see an address starting with 2002: there.

Or, you can go to ipv6.whatismyv6.com .

Here's a somewhat long alias as well, which shows who the IPv4 and IPv6 worlds think you are:

alias myip="dig myip.opendns.com @resolver1.opendns.com +short ; lynx -dump http://ipv6.whatismyv6.com/ | grep '^ *[0-9a-f:]\+ *$' | awk '{print \$1}'"
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License