Tunnels to the IPv6 Internet - 6in4

Unfortunately there are still internets with no native connectivity to the IPv6 Internet.
6in4 Internet Protocol 41 tunnels are a good way to connect to the IPv6 Internet.

You may set up a 6in4 Internet Protocol 41 tunnel with someone that has IPv6 connectivity and is willing to donate to you a bit more than your IPv6 traffic times 2 in Bandwidth or use a 6in4 provider.

I have been using 6in4 tunnels from HE ( tunnelbroker.net ) and SixXS ( sixxs.net ) for ~two years and according to my monitor, they have an excellent uptime --much better than some ADSL based connections to the IPv4 Internet.

HE offers tunnels to the IPv6 Internet with static endpoints only.
SixXS offers both tunnels with static endpoints and tunnels to clients using a Dynamic IPv4 address.
Both Providers provide the tunnels to the IPv6 Internet free of charge.

I recommend 6in4 tunnels from SixXS and HE to anyone --stuck in an IPv4 only Network-- looking for an easy way to make his services available through IPv6 or just connect to the IPv6 Internet.

Yes!, you could provide services to the IPv6 Internet using "your" IPv6 static space routed to you through a tunnel to your dynamic IPv4 address (Look for: SixXS 6in4 heartbeat IP 41 tunnels & SixXS AYIYA tunnels ).

However, these notes are for tunnels with static IPv4 endpoints.

If you use one of the providers above for your 6in4 tunnel open an account and then use ping to figure what tunnel Server - Point of Presence to choose. They have many PoP spread around the world and the Internet distance is not always analogous to the geographical distance.

IPv4 Firewall

Punch a hole on your IPv4 Firewall to allow IP 41 from the tunnel server.
# iptables -I INPUT -p ipv6 -s 203.0.113.114/32 -j ACCEPT
where 203.0.113.114 is the other side of your tunnel --your tunnel server.
# iptables -L -n |grep 41
ACCEPT     41   --   203.0.113.114       0.0.0.0/0


Tunnel Interface

A simple script that sets up the tunnel interface.
#!/bin/bash
#ipv6-tunnel.sh g0 2011-2013

HERE='198.51.100.100'
THERE='203.0.113.114'
MYIP6='2001:470:1f0a:35d::2/64'
TUIP6='2001:470:1f0a:35d::1/64'
TUNAME='he-ipv6-0'
MYOIP6="2001:470:1f0a:35d::3/64 2001:470:1f0a:35d::3/64 2001:470:1f0a:35d::da/64"

#$IP6_DEF_ROUTE='::/0'
IP6_DEF_ROUTE='2000::/3'
TTL=255 #sixxs suggests 64 
MTU=1280

ip tunnel add ${TUNAME} mode sit remote ${THERE} local ${HERE} ttl ${TTL}
ip link set ${TUNAME} up
ip link set mtu ${MTU} dev ${TUNAME}

ip addr add ${MYIP6} dev ${TUNAME}

if [ -n "${MYOIP6}" ] ; then
for IP6 in ${MYOIP6}; do
        ip addr add ${IP6} dev ${TUNAME}
done
fi

route -A inet6 add ${IP6_DEF_ROUTE} dev ${TUNAME}






where 198.51.100.100 is your ipv4 address , 203.0.113.114 is the tunnel server ipv4 address , 2001:470:1f0a:35d::2/64 is your tunnel ipv6 address, etc

You need to change at least HERE , THERE , MYIP6 , TUIP6 , and MYOIP6 in the ipv6-tunnel.sh script. If you want to set only one IPv6 address on the tunnel interface set MYOIP6 to "" or comment it out.

To get ipv6-tunnel.sh
# wget kod.ipduh.com/lib/ipv6-tunnel.sh


You may put the tunnel interface stanza in /etc/network/interfaces in Debian based Systems or the equivalent network interfaces configuration file in other Linux distributions. However, I like to put the ipv6-tunnel.sh in /etc/network/if-up.d which for IP 41 tunnels is effectively the same.

To bring up the tunnel interface you may run the ipv6-tunnel script
# /etc/network/if-up.d/ipv6-tunnel.sh
or restart networking
# /etc/init.d/networking restart
Running /etc/init.d/networking restart is deprecated because it may not enable again some interfaces ... (warning).
...
done.
You may get some warnings but you should be just fine ignoring them.

Once up you should see the tunnel infterface and your IPv6 addresse(s) with ifconfig
he-ipv6-0 Link encap:IPv6-in-IPv4  
          inet6 addr: 2001:470:1f0a:35d::2/64 Scope:Global
          inet6 addr: 2001:470:1f0a:35d::3/64 Scope:Global
          inet6 addr: 2001:470:1f0a:35d::da/64 Scope:Global
          inet6 addr: fe80::5e46:889b/128 Scope:Link
          UP POINTOPOINT RUNNING NOARP  MTU:1280  Metric:1
          RX packets:63 errors:0 dropped:0 overruns:0 frame:0
          TX packets:60 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:6408 (6.2 KiB)  TX bytes:6080 (5.9 KiB)



OK, ping the other side of the tunnel
# ping6 2001:470:1f0a:35d::1
PING 2001:470:1f0a:35d::1(2001:470:1f0a:35d::1) 56 data bytes
64 bytes from 2001:470:1f0a:35d::1: icmp_seq=1 ttl=64 time=175 ms
64 bytes from 2001:470:1f0a:35d::1: icmp_seq=2 ttl=64 time=227 ms
64 bytes from 2001:470:1f0a:35d::1: icmp_seq=5 ttl=64 time=114 ms
^C
ping an Internet ipv6 address
# ping6 ipduh.com
PING ipduh.com(2001:470:1f0a:2e2:da::) 56 data bytes
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=1 ttl=63 time=74.7 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=2 ttl=63 time=271 ms
^C


To view the IPv6 routing table
# route -6 -n


To put down the tunnel interface
# ip link set he-ipv6-0 down
where he-ipv6-0 is the name of the interface.

IPv6 Firewall

Put the following one liner in /etc/network/if-pre-up/ip6fwinit to start the ipv6 firewall at the right times.
# cat  /etc/network/if-pre-up.d/ip6fwinit
#!/bin/sh
/sbin/ip6tables-restore < /etc/rules.ip6tables



A simple IPv6 firewall script , ipv6fw.sh
#!/bin/bash
#ipv6fw.sh , g0 2013 , alog.ipduh.com
#stupid-simple bif.sh style ipv6 firewall 
#using stuff mostly stolen from: 
#http://www.sixxs.net/wiki/IPv6_Firewalling



##change these:
TUNIF='he-ipv6-0' 
BR='br0'
SSHD_HOST='2001:470:1f0a:35d::3'
NAMED_HOST='2001:470:1f0a:35d::3'
HTTPD_HOST='2001:470:1f0a:35d::da'
MAILD_HOST='2001:470:1f0a:35d::da'
MY48='2001:470:7134::/48'
##

IP6TABLES='/sbin/ip6tables'
IP6TABLES_SAVE='/sbin/ip6tables-save'
IP6TABLES_RULES='/etc/rules.ip6tables'

# First, delete all:
${IP6TABLES} -F
${IP6TABLES} -X

# Allow anything on the local link
${IP6TABLES} -A INPUT  -i lo -j ACCEPT
${IP6TABLES} -A OUTPUT -o lo -j ACCEPT

# Allow anything out on the internet
${IP6TABLES} -A OUTPUT -o ${TUNIF} -j ACCEPT
# Allow established, related packets back in
${IP6TABLES} -A INPUT  -i ${TUNIF} -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow the localnet access us:
${IP6TABLES} -A INPUT    -i ${BR} -j ACCEPT
${IP6TABLES} -A OUTPUT   -o ${BR} -j ACCEPT

# Filter all packets that have RH0 headers:
${IP6TABLES} -A INPUT -m rt --rt-type 0 -j DROP
${IP6TABLES} -A FORWARD -m rt --rt-type 0 -j DROP
${IP6TABLES} -A OUTPUT -m rt --rt-type 0 -j DROP

# Allow Link-Local addresses
${IP6TABLES} -A INPUT -s fe80::/10 -j ACCEPT
${IP6TABLES} -A OUTPUT -s fe80::/10 -j ACCEPT

# Allow multicast
${IP6TABLES} -A INPUT -d ff00::/8 -j ACCEPT
${IP6TABLES} -A OUTPUT -d ff00::/8 -j ACCEPT

# Allow ICMPv6 everywhere
${IP6TABLES} -I INPUT  -p icmpv6 -j ACCEPT
${IP6TABLES} -I OUTPUT -p icmpv6 -j ACCEPT
${IP6TABLES} -I FORWARD -p icmpv6 -j ACCEPT

# Allow forwarding
${IP6TABLES} -A FORWARD -m state --state NEW -i ${BR} -o ${TUNIF} -s ${MY48} -j ACCEPT
${IP6TABLES} -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# SSH in
${IP6TABLES} -A FORWARD -i ${TUNIF} -p tcp -d ${SSHD_HOST} --dport 22 -j ACCEPT

# HTTP in https , http
${IP6TABLES} -A FORWARD -i ${TUNIF} -p tcp -d ${HTTPD_HOST} --dport 80 -j ACCEPT
${IP6TABLES} -A FORWARD -i ${TUNIF} -p tcp -d ${HTTPD_HOST} --dport 443 -j ACCEPT

# NAMED in
${IP6TABLES} -A FORWARD -i ${TUNIF} -p tcp -d ${NAMED_HOST} --dport 53 -j ACCEPT
${IP6TABLES} -A FORWARD -i ${TUNIF} -p udp -d ${NAMED_HOST} --dport 53 -j ACCEPT

# MAIL smtp , imap over ssl
${IP6TABLES} -A FORWARD -i ${TUNIF} -p tcp -d ${MAILD_HOST} --dport 25 -j ACCEPT
${IP6TABLES} -A FORWARD -i ${TUNIF} -p tcp -d ${MAILD_HOST} --dport 993 -j ACCEPT

# Set the default policy
${IP6TABLES} -P INPUT   DROP
${IP6TABLES} -P FORWARD DROP
${IP6TABLES} -P OUTPUT  DROP

# save
${IP6TABLES_SAVE} > ${IP6TABLES_RULES}



You may use wget to get the ipv6fw.sh
# wget kod.ipduh.com/lib/ipv6fw.sh


Do the appropriate changes. The variable names in between ##change these and ## are self-explanatory. BR may be any LAN interface, not necessarily a bridge.

apply the ipv6fw.sh rules
# /etc/ipv6fw.sh


/etc/ipv6fw.sh applies the ip6tables rules and saves them at /etc/rules.ip6tables
/etc/network/if-pre-up.d/ip6fwinit applies the ip6tables rules in /etc/rules.ip6tables just before the network interfaces come up

ip6.arpa. aka `reverse IPv6` zones

You can delegate the `reverse` zones of the IPv6 space routed to your tunnel to your name servers.
If you got a tunnel from SixXS or HE you can do it through their web control panel.

Test the delegation and set the ip6.arpa. zone for 2001:470:1f0b:35d::/64
# cat db.d.5.3.0.b.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
$TTL 1h 
@ IN SOA nse.ipduh.com systems.ipduh.com. (
 2 ; serial
 1h ; slave refresh interval
 15m ; slave retry interval
 1w ; slave copy expire time
 1h ; NXDOMAIN cache time
 )

@ IN  NS nse.ipduh.com.
@ IN  NS nsd.ipduh.com.
@ IN  NS nsa.ipduh.com.

0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.5.3.0.b.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa.  IN PTR he-6in4-tunnel.bob.ipduh.com. 
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.5.3.0.b.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa.  IN PTR gw-bob.he.ipduh.com. 
2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.3.0.8.0.0.f.f.8.4.6.0.1.0.0.2.ip6.arpa.  IN PTR gw-he.bob.ipduh.com.
3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.3.0.8.0.0.f.f.8.4.6.0.1.0.0.2.ip6.arpa.  IN PTR 3.bob.ipduh.com.
a.d.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.3.0.8.0.0.f.f.8.4.6.0.1.0.0.2.ip6.arpa.  IN PTR da.bob.ipduh.com.



The ip6.arpa zone for 2001:470:7134::/48
# cat db.4.3.1.7.0.7.4.0.1.0.0.2.ip6.arpa 
$TTL 1h 
@ IN SOA nse.ipduh.com systems.ipduh.com. (
 1 ; serial
 1h ; slave refresh interval
 15m ; slave retry interval
 1w ; slave copy expire time
 1h ; NXDOMAIN cache time
 )

@ IN  NS nse.ipduh.com.
@ IN  NS nsd.ipduh.com.
@ IN  NS nsa.ipduh.com.

0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.4.3.1.7.0.7.4.0.1.0.0.2.ip6.arpa.  IN PTR he-6in4-48.bob.ipduh.com. 
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.e.2.0.b.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa.  IN PTR gw.bob.ipduh.com. 
2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.e.2.0.b.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa.  IN PTR yet-another-ipv6-host.bob.ipduh.com.



Test DNS:
dns trace 2001:470:1f0b:35d::1
dns trace 2001:470:7134::2


Optimal MTU

The minimum MTU for IPv6 is 1280B and the maximum MTU for IP 41 tunnels is 1480B. If an upstream router or the tunnel server is using a smaller MTU than yours your IPv6 connectivity may be partially broken. You could figure out the best MTU across a path (path MTU Discovery) using ping6.

excerpt from the ping6 man page:
 -M hint
              Select Path MTU Discovery strategy.  hint may be either do (prohibit fragmentation, even local one), want (do  PMTU  discovery,  fragment  locally
              when packet size is large), or dont (do not set DF flag).

eg:
#ping6 -s 1432 -M do ipduh.com -c 1
PING ipduh.com(2001:470:1f0a:2e2:da::) 1432 data bytes
From cl-60.ath-01.gr.sixxs.net icmp_seq=1 Packet too big: mtu=1280

--- ipduh.com ping statistics ---
0 packets transmitted, 0 received, +1 errors
#ping6 -s 1432 -M want ipduh.com -c 1
PING ipduh.com(2001:470:1f0a:2e2:da::) 1432 data bytes
1468 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=1 ttl=53 time=73.9 ms

--- ipduh.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 73.991/73.991/73.991/0.000 ms


To set the MTU you could use ifconfig
#ifconfig ipv6-iface mtu 1480
or the route tools
ip link set ipv6-iface mtu 1480


However, the minimum MTU --1280B-- should work always.

Well, if you just want to make some services available to the IPv6 Internet from one host you are done with IPv6 and you can start setting up your daemons.

Routing to other Hosts

Add net.ipv6.conf.all.forwarding=1 in /etc/sysctl.conf and enable ipv6 forwarding right now
# echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
# sysctl -p
# echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
Comment out
${IP6TABLES} -P FORWARD DROP 
in /etc/ipv6fw.sh
Reset the IPv6 Firewall
# /etc/ipv6fw.sh


Set the LAN IPv6 Gateway in a /64 within the routed /48
HE routes 2001:470:7134::/48 to my tunnel.
I will use 2001:470:7134::/64 for my LAN and set the gateway to 2001:470:7134::1.

Set up the LAN Gateway
ip -6 addr add 2001:470:7134::1/64 dev br0:1
I am using a bridged interface, it could be any interface connected to the LAN.

On another host in the LAN
# ip -6 addr add 2001:470:7134::2/64 dev eth0:1
# ip -6 route add default via 2001:470:7134::1


Test:
# ping6 2001:470:7134::1 -c 1
PING 2001:470:7134::1(2001:470:7134::1) 56 data bytes
64 bytes from 2001:470:7134::1: icmp_seq=1 ttl=64 time=0.253 ms

--- 2001:470:7134::1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.253/0.253/0.253/0.000 ms
# ping6 ipduh.com -c 1
PING ipduh.com(2001:470:1f0a:2e2:da::) 56 data bytes
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=1 ttl=62 time=59.2 ms

--- ipduh.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 59.241/59.241/59.241/0.000 ms



You may use IPv6 router advertisements to give IPv6 addresses and routes to hosts in your LAN. The daemon doing that is called ravd. Router Advertisements is a great idea, however , I do not see any use on my setups.

The problem I had so far with ravd breaks down to that:
Almost everything is IPv6 ready and it will get an IPv6 address but most sites still do not have Native IPv6 Connectivity and connect to the IPv6 Internet through a tunnel making almost everything with an AAAA record slower.
Therefore, I prefer giving static IPv6 addresses and routes to the hosts that need it.

Here is a low on effort attempt to quantify the IPv6 through-tunnel-content:through-tunnel-client latency penalties. Quantifying the router stress and bandwidth penalties of tunnels to the IPv6 is simple arithmetic.

Compare latency: an IP 41 IPv6 SixXS tunnel to a PoP in grnet
from an IPv4 Endpoint in 6799
IPv4:
$ ping -c6 ipduh.com -n
PING ipduh.com (85.25.242.245) 56(84) bytes of data.
64 bytes from 85.25.242.245: icmp_seq=1 ttl=49 time=50.1 ms
64 bytes from 85.25.242.245: icmp_seq=2 ttl=49 time=51.0 ms
64 bytes from 85.25.242.245: icmp_seq=3 ttl=49 time=51.4 ms
64 bytes from 85.25.242.245: icmp_seq=4 ttl=49 time=51.1 ms
64 bytes from 85.25.242.245: icmp_seq=5 ttl=49 time=50.3 ms
64 bytes from 85.25.242.245: icmp_seq=6 ttl=49 time=50.8 ms

--- ipduh.com ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5005ms
rtt min/avg/max/mdev = 50.188/50.830/51.497/0.503 ms
Tunnel-Tunnel IPv6:
$ ping6 -c6 ipduh.com -n
PING ipduh.com(2001:470:1f0a:2e2:da::) 56 data bytes
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=1 ttl=53 time=57.8 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=2 ttl=53 time=67.5 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=3 ttl=53 time=60.6 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=4 ttl=53 time=57.3 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=5 ttl=53 time=56.5 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=6 ttl=53 time=60.1 ms

--- ipduh.com ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5008ms
rtt min/avg/max/mdev = 56.581/60.013/67.582/3.684 ms



Compare latency: an IP 41 IPv6 HE tunnel to a tunnel server in the he transit network
from an IPv4 Endpoint in 6799
IPv4:
$ ping -c6 ipduh.com -n
PING ipduh.com (85.25.242.245) 56(84) bytes of data.
64 bytes from 85.25.242.245: icmp_req=1 ttl=50 time=48.6 ms
64 bytes from 85.25.242.245: icmp_req=2 ttl=50 time=48.4 ms
64 bytes from 85.25.242.245: icmp_req=3 ttl=50 time=48.8 ms
64 bytes from 85.25.242.245: icmp_req=4 ttl=50 time=48.0 ms
64 bytes from 85.25.242.245: icmp_req=5 ttl=50 time=48.4 ms
64 bytes from 85.25.242.245: icmp_req=6 ttl=50 time=47.9 ms

--- ipduh.com ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5008ms
rtt min/avg/max/mdev = 47.904/48.382/48.811/0.428 ms

Tunnel-Tunnel IPv6:
# ping6 -c6 ipduh.com -n
PING ipduh.com(2001:470:1f0a:2e2:da::) 56 data bytes
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=1 ttl=63 time=59.5 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=2 ttl=63 time=59.7 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=3 ttl=63 time=59.6 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=4 ttl=63 time=59.4 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=5 ttl=63 time=60.0 ms
64 bytes from 2001:470:1f0a:2e2:da::: icmp_seq=6 ttl=63 time=59.3 ms

--- ipduh.com ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5008ms
rtt min/avg/max/mdev = 59.373/59.653/60.077/0.339 ms


To disable IPv6.
# ip -6 addr del 2001:470:7134::2/64 dev eth0


The systems used:
# cat /etc/issue /etc/debian_version ; uname -r
Debian GNU/Linux 6.0 \n \l

6.0.7
2.6.32-5-amd64


Usefull Links:
Linux IPv6 HowTo
Debian IPv6
SixXS IPv6 Firewalling




Tunnels to the IPv6 Internet - 6in4