Recently, I discovered that our ISP (sonic.net) offers IPv6 tunnels. So they do not give a direct IPv6 connection, but a tunnel is good enough.
It works by offering each customer an IPv6 transport network and a /60 network, enough room for 2^(128-60) = 295147905179352825856 addresses! When logged in to their web interface, they give detailed instructions:
- the IPv4 address of the tunnel gateway
- the IPv6 addresses of the enpoints (customer and tunnel)
- the IPv6 network.
This is how it looks:
208.201.xxx.yyy = sonic-side v4 addy 209.204.xxx.yyy = customer-side v4 addy 2001:xxxx:0000:0001:0000:0000:0000:yyyy = Sonic-side transport IP 2001:xxxx:0000:0001:0000:0000:0000:yyyy = customer-side transport IP
To make use of that, a customer has to set up his own IPv4 to IPv6 gateway. I use Debian/unstable with a 2.6.17 kernel. It works with older 2.6 kernels, but at least 2.6.17 is recommended for proper ip6tables support with connection tracking. These are the relevant kernel options:
CONFIG_IPV6=m CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y # CONFIG_IPV6_ROUTE_INFO is not set CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_INET6_XFRM_TUNNEL=m CONFIG_INET6_TUNNEL=m CONFIG_IPV6_TUNNEL=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y
For iptables support with connection tracking, I have also enabled these:
CONFIG_NF_CONNTRACK_IPV6=m # CONFIG_IP6_NF_QUEUE is not set CONFIG_IP6_NF_IPTABLES=m CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_MATCH_OPTS=m CONFIG_IP6_NF_MATCH_FRAG=m CONFIG_IP6_NF_MATCH_HL=m CONFIG_IP6_NF_MATCH_OWNER=m CONFIG_IP6_NF_MATCH_IPV6HEADER=m CONFIG_IP6_NF_MATCH_AH=m CONFIG_IP6_NF_MATCH_EUI64=m CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_MANGLE=m CONFIG_IP6_NF_TARGET_HL=m CONFIG_IP6_NF_RAW=m
I had to build my own kernel, because the official Debian kernel package did not have all of the needed options enabled. I will not explain here how to compile a kernel – there are enough instructions elsewhere. After compiling the kernel and rebooting, the next step is loading the ipv6 module:
modprobe -v ipv6
To make this automatic on boot, append this to /etc/modules:
echo ipv6 >> /etc/modules
Now you need to configure the interfaces in /etc/network/interfaces. This will configure an IPv6 address for eth0. This entry needs to be right after the entry for the IPv4 address of eth0, otherwise it does not work. Also, so far it is not possible to configure more than one IPv6 address per interface, at least not without the manual method or using the ‘up’ and ‘down’ paramters.
iface eth0 inet6 static address 2001:xxxx:xxxx:xxxx::1 netmask 64
You need to use an address of you assigned network. I chose ::1 because it is easy to remember. Next you need to set up the tunnel interface:
iface sixbone inet6 v4tunnel address 2001:xxxx:xxxx:xxxx::xxxx netmask 127 endpoint 208.201.xxx.yyy local 192.168.2.3 ttl 255
The address here is local address of the transport network. The endpoint is the IPv4 address of the remote gateway (labeled ‘sonic-side v4 addy’ above). I also set the parameter local to the local network address – this is needed if this gateway is not the router itself, and the router uses NAT to forward tunneled IPv6 packets to this gateway – I will explain that later in another post.
After restarting the eth0 interface and starting the sixbone interface (ifdown eth0; ifup eth0; ifup sixbone), you should now be able to ping6 an IPv6 address. For example, try
# ping6 www.ipv6.uni-muenster.de PING www.ipv6.uni-muenster.de(2001:638:500:101:2e0:81ff:fe24:37c6) 56 data bytes 64 bytes from 2001:638:500:101:2e0:81ff:fe24:37c6: icmp_seq=1 ttl=47 time=215 ms 64 bytes from 2001:638:500:101:2e0:81ff:fe24:37c6: icmp_seq=2 ttl=47 time=209 ms
If it does not work, maybe your firewall blocks. Tunneled IPv6 packets have a special protocol type (41), this makes it easy to add a rule:
iptables -I INPUT -j ACCEPT --proto 41
To use this gateway in your home network as a router, you need to enable forwarding:
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
To make this automatic on boot, add a rule to /etc/sysctl.conf:
But careful! As soon as other hosts have an IPv6 address and have your new gateway configured as a router, they are wide open to the internet. So you need to setup a few firewall rules, for example:
-A INPUT -s ::/0 -d ::/0 -i sixbone -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT -A INPUT -s ::/0 -d ::/0 -i sixbone -p tcp -m tcp --dport 113 -m state --state NEW -j REJECT --reject-with icmp6-port-unreachable -A INPUT -s ::/0 -d ::/0 -i sixbone -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -s ::/0 -d ::/0 -i sixbone -j DROP -A FORWARD -s ::/0 -d ::/0 -i sixbone -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT -A FORWARD -s ::/0 -d ::/0 -i sixbone -p tcp -m tcp --dport 113 -m state --state NEW -j REJECT --reject-with icmp6-port-unreachable -A FORWARD -s ::/0 -d ::/0 -i sixbone -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -s ::/0 -d ::/0 -i sixbone -j DROP
Now you can configure other hosts in your network to use this gateway as your IPv6 router, for example:
iface eth0 inet6 static address 2001:xxxx:xxxx:xxxx::2 netmask 64 gateway 2001:xxxx:xxxx:xxxx::1
The nice thing is that NAT is no longer needed, because there are enough addresses available. Of course, this also means that every host is identifiable.
Next I will explain how to setup radvd, so you do not need to configure an IPv6 address for ever host in the network. That’s even easier than DHCP…