Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I would like to create host-only IPv6 networks on two hosts and then route between them. On each host, there will be a dummy interface, at ipv6_prefix::9. I would like to be able to ping that interface from the other host.

Is there a well-developed best practice for this? It seems reasonable that one could do it with 6in4 tunnels.

Below, I'll work through the setup I tried recently in EC2, using 6in4 to tunnel. The two hosts are and First, let's set up the dummy interfaces. We'll use these Bash functions:

function dummy {
  local name="$1" ipv6="$2"
  ip link add "$name" type dummy
  ip -6 addr add "$ipv6" dev "$name"
  ip link set "$name" up

function calc6to4 {
  printf '2002:%02x%02x:%02x%02x::\n' $(tr '.' ' ' <<<"$@")

function eth0ipv4 {
  ip addr list dev eth0 | egrep -o 'inet [^/]+' | head -n1 | cut -d' ' -f2

(You can just paste these straight in to your shell session.)

On the first host, we run:

:;  ipv4="$(eth0ipv4)"
:;  ipv6="$(calc6to4 "$ipv4")"
:;  echo "ipv4 = $ipv4" "ipv6 = $ipv6"
ipv4 = ipv6 = 2002:0aef:8f23::
:;  dummy dummy9 "$ipv6"9
:;  ip addr show dev dummy9
69: dummy9: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 
    link/ether e2:69:75:10:04:2c brd ff:ff:ff:ff:ff:ff
    inet6 2002:aef:8f23::9/128 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::e069:75ff:fe10:42c/64 scope link 
       valid_lft forever preferred_lft forever

Pinging seems to work okay:

:;  ping6 -q -c1 "$ipv6"9
PING 2002:0aef:8f23::9(2002:aef:8f23::9) 56 data bytes

--- 2002:0aef:8f23::9 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.040/0.040/0.040/0.000 ms

Now it's on to the second host:

:;  ipv4="$(eth0ipv4)"
:;  ipv6="$(calc6to4 "$ipv4")"
:;  echo "ipv4 = $ipv4" "ipv6 = $ipv6"
ipv4 = ipv6 = 2002:0aee:f971::
:;  dummy dummy9 "$ipv6"9

Ping check checks out:

:;  ping6 -q -c1 "$ipv6"9
PING 2002:0aee:f971::9(2002:aee:f971::9) 56 data bytes

--- 2002:0aee:f971::9 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.037/0.037/0.037/0.000 ms

Now it's time for the exciting bit: connecting the hosts with 6in4 tunnels. We use the following Bash function on both hosts:

function tunnel {
  local name="$1" self_ipv4="$2" ipv4="$3" ipv6="$4"
  ip tunnel add "$name" mode sit ttl 64 remote "$ipv4" local "$self_ipv4"
  ip -6 addr add "$ipv6"1 dev "$name"
  ip -6 route add "$ipv6"/64 dev "$name" metric 1
  ip link set "$name" up

On the first host:

################################### IPv4 and IPv6 from host 2 ##
:;  tunnel tun6in4 2002:0aee:f971::

On the second:

################################### IPv4 and IPv6 from host 1 ##
:;  tunnel tun6in4 2002:0aef:8f23::

When we try to find a route from the first host to 2002:aee:f971::9, bound to the dummy device on the second, we get a hit:

:;  ip -6 route get 2002:aee:f971::9
2002:aee:f971::9 from :: dev tun6in4  src 2002:aee:f971::1  metric 0 

But pings don't work:

:;  ping6 -q -c1 2002:aee:f971::9
PING 2002:aee:f971::9(2002:aee:f971::9) 56 data bytes

--- 2002:aee:f971::9 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

Maybe I need to add an address to eth0?

share|improve this question
Why do you use 6to4 addresses with a 6in4 tunnel? If you use 6to4 to connect to the IPv6 Internet, why the additional tunnel? A connection should work over 6to4 (as far as 6to4 works at all) using the IPv4 addresses of the corresponding routers. Official IPv6 prefixes would be preferable, but if you only need IPv6 on the two hosts, you try using Unique Local Addresses and the 6in4 tunnel. At least, I could imagine that there was a problem with 6to4 addresses being routed over the tunnel, but I didn't try it myself. – Dubu Apr 2 '14 at 8:22
Well, in this example I don't actually connect to the IPv6 internet (I don't think)...but I would like to have that option. So I was hoping to use addresses that would be globally routable if that change were made. (In "real life" I would derive the IPv6 addresses from an EC2 instance's external IPv4.) – solidsnack Apr 2 '14 at 17:32
It turns out that 6in4 tunneling -- protocol 41 -- is not well supported on Amazon's network. forums.aws.amazon.com/message.jspa?messageID=182611#182611 – solidsnack Apr 6 '14 at 1:50
up vote 1 down vote accepted

It turns out that the tunnel should have an IPv6 address on the source host, not the target host (the peer), for this simple ping test to work.

function tunnel {
  local name="$1" self_ipv4="$2" self_ipv6="$3" ipv4="$4" ipv6="$5"
  ip tunnel add "$name" mode sit ttl 64 remote "$ipv4" local "$self_ipv4"
  ip -6 addr add "$self_ipv6"1 dev "$name"
  ip -6 route add "$ipv6"/64 dev "$name" metric 1
  ip link set "$name" up

The tunnel setup commands would then be:

:;  tunnel tun6in4 2002:0aef:8f23:: 2002:0aee:f971::
:;  tunnel tun6in4 2002:0aee:f971:: 2002:0aef:8f23::
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.