Configuring an IPv6 gateway with Debian

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:

net.ipv6.conf.default.forwarding=1

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…

Advertisements

2 Comments

Filed under debian, ipv6

2 responses to “Configuring an IPv6 gateway with Debian

  1. Pingback: Using radvd « Fermi Paradox

  2. Thanks for sharing the information, exactly what I was looking for and works perfectly on Ubuntu!