Configure Debian as an IPv6 Router

On February 3, 2011, the Internet Assigned Numbers Authority (IANA), which manages the allocation and assignment of IP addresses from the IPv4 address space, allocated the last remaining /8 blocks to the five regional Internet registries. While the Internet isn’t going to break because of this, it’s an important milestone on the road to worldwide IPv6 deployment.

(For background: IPv4 addresses are 32-bits, which equates to around four billion usable addresses. Many of those are not publicly routable, though, and addresses are allocated in blocks, so the world will “run out” well before there are four billion reachable servers + clients. IPv6 instead uses a 128-bit address space, or around 340 undecillion addresses. Put in more comprehendible terms: that’s enough to assign one address to every grain of sand on every beach on Earth and barely make a dent.)

I figured it might be fun to figure out how to make my LAN able to talk to the IPv6 Internet. I use a Debian Lenny server as my router and one of the advantages over using an appliance is that I can play with things like this.

My Internet provider, like most, doesn’t support native IPv6. Not to worry; there are several companies that offer free IPv6-over-IPv4 tunnels. The most popular are Hurricane Electric and SixXS. I chose HE, and it’s quite easy to set up.

First, sign up for a tunnel. For the following directions, you’ll need to know the names of your network interfaces, the tunnel server’s IPv4 address, the two IPv6 tunnel endpoints and your assigned address block. This is probably a /64. (Stop and think about that for a second: the prefix is 64 bits, meaning you get to use the other 128-64=64 bits, i.e. you’ve been assigned an address block of 264 addresses, or something 4 billion times bigger than the IPv4 Internet, and no one is worried about it. It’s mind boggling.)

Second, it’s time to edit some files. Add to your /etc/network/interfaces:

auto 6in4
iface 6in4 inet6 v4tunnel
        address YOUR-IPV6-ENDPOINT
        netmask 64 # or whatever your IPv6 block prefix is
        endpoint TUNNEL-SERVER-IPV4-ADDRESS
        gateway TUNNEL-SERVER-IPV6-ENDPOINT
        ttl 64
        up ip link set mtu 1280 dev $IFACE
        up route -6 add YOUR-IPV6-BLOCK/64 YOUR-EXTERNAL-INTERFACE

Install radvd, the route advertisement daemon, so clients on your LAN can autoconfigure their IPv6 address.

$ sudo aptitude install radvd

Edit /etc/radvd.conf to advertise your IPv6 block.

interface YOUR-INTERNAL-INTERFACE {
	AdvSendAdvert on;
	prefix YOUR-IPV6-BLOCK/64 {
	};
};

Enable IPv6 forwarding by editing /etc/sysctl.conf and uncommenting the line for net.ipv6.conf.all.forwarding. Then make the same change for the running kernel.

$ sudo sysctl -w net.ipv6.conf.all.forwarding=1

Start radvd.

$ sudo invoke-rc.d radvd start

Provided that IPv6 is enabled on your LAN clients, they should assign themselves an IPv6 address very quickly after radvd starts.

At this point, you’re done with the basics and you should be able to talk to the IPv6 Internet. Test it out and check if you can see the dancing turtle.

If you don’t score 10/10 on the IPv6 part of the test and you run your own caching nameserver, be sure that -4 is not in your /etc/default/bind9. Older Debian releases used this option and it forces BIND to only use IPv4, which means it can’t reach IPv6-only nameservers.

There is one last critical step, though the specifics are beyond the scope of this post. All addresses in your IPv6 block are publicly routable, unlike what you’ve probably done up to now with IPv4 and NAT. You must run a firewall on your router to ensure that your LAN workstations are not open to the Internet. If you are using a firewall package, make sure it creates rules for IPv6. If you are using your own custom script based on iptables, be aware that it doesn’t do anything for IPv6. You must add rules using ip6tables to cover IPv6 traffic. Use an IPv6 port scanner to verify your LAN is protected.