IPv6 for a Linux generation

IPv6 is nothing new – it was finally standardised back in 1998 in RFC 2460, and virtually all operating systems have supported it now for at least 5 years, so most people are in a position to give it a try.

If you’re one of the lucky ones, your ISP might provide native IPv6 connectivity (like AAISP), but for most of us, the main way to get connected to the rest of the IPv6 Internet is to use something we’ve already got – IPv4. And we’re going to tunnel over it.

The first thing we need to do is choose a tunnel broker, which is a fancy name for someone who’ll provide us with an IPv4 endpoint we can tunnel IPv6 over. Wikipedia has a list, but the main, globally available ones are Hurricane Electric and SixXS. Either of these will do, and some people prefer HE over SixXS, but that’s a purely personal choice – in my experience, both work equally as well. For this example, though, we’ll go with HE – so head on over to http://tunnelbroker.net/ and create an account.

My first tunnel

Once you’ve created your account, log in and create a tunnel. For some reason, it always seems to pick their New York POP, so you might want to manually choose one geographically closer (in my case – and for our example – London, UK)

The IP address you use as your local end of the tunnel will need to be a public IP address. It’s possible to use a machine behind a NAT device if it’s in a DMZ-style setup where all the traffic destined for the public IP address gets forwarded by the NAT device to the machine behind it, but your mileage may vary.

Once created, view the tunnel details, which should look something like this:-

Our tunnel has been created! At the bottom of the page, you’ll notice a little drop-down that generates the commands needed to bring up the tunnel. For this example, we’re using iproute2, so the commands go something like this:-

ip tunnel add he-ipv6 mode sit remote 216.66.80.26 local 192.0.2.1 ttl 255 ip link set he-ipv6 up ip addr add 2001:470:1f08:810::2/64 dev he-ipv6 ip route add ::/0 dev he-ipv6

The first command creates an IPv6-in-IPv4 tunnel between us and HE, and the second command brings up that tunnel. The third command adds our IPv6 address to our end of the tunnel, and finally the fourth command sets the IPv6 default route to be down our newly-created tunnel.

And that’s it – we’re now connected to the global IPv6 internet. To test it, let’s try pinging something:-

mordor:~# ping6 -c 3 www.he.net PING www.he.net(he.net) 56 data bytes 64 bytes from he.net: icmp_seq=1 ttl=58 time=375 ms 64 bytes from he.net: icmp_seq=2 ttl=58 time=257 ms 64 bytes from he.net: icmp_seq=3 ttl=58 time=255 ms --- www.he.net ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2002ms rtt min/avg/max/mdev = 255.562/296.218/375.628/56.158 ms

If you see something like the above, then give yourself a pat on the back, because it’s working!

Next steps

HE by default assigns you a /64 network, which is the smallest size intended to be allocated. This gives you 18,446,744,073,709,551,616 IPs, and whichever way you look at it that’s a lot of addresses. With this in mind, you might be wondering why HE will give you a /48 (that’s 1,208,925,819,614,629,174,706,176 IPs!). The reason is that each network is intended to have a /64, and a /48 allows you to carve up that space into a total of 65,536 separate /64 networks. Now this obviously sounds like overkill to the average user, but autoconfiguration tools such as radvd won’t work with networks smaller than /64, again because of the intentions mentioned previously. This means that if you have more than one network at home (say, a wired network and a wireless network, currently with separate IPv4 networks for each), you can assign a /64 to each one.

With this is mind, let’s ask HE for a /48 by clicking on Allocate in the ‘Routed /48′ section. After a few seconds, you’ll see something like this:-

In our example, we’ve been allocated 2001:470:90d3::/48 , and now it’s time to plan our IP schema.

Laying it out

Taking my own home network as an example, I have three networks – one for general use (the ‘LAN‘), one for guest use over wireless (the ‘WLAN‘), and finally a DMZ (the… er, ‘DMZ‘). We could lay these out like this:-

LAN – 2001:470:90d3: 1 ::/64

DMZ – 2001:470:90d3: 2 ::/64

WLAN – 2001:470:90d3: 3 ::/64

Nice and simple, and easy to remember. Assuming all three networks are connected to the same gateway machine, we can give the gateway the first IP in the range – 2001:470:90d3:1::1 , 2001:470:90d3:2::1 and 2001:470:90d3:3::1 .

Routing things further

Before we start, we need to enable IP forwarding for IPv6:-

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

You’ll probably want to add this somewhere so it gets activated on bootup – under Debian this would be in /etc/sysctl.conf (which already has the entry, albeit commented out).

One way to provide connectivity to machines on the individual networks is to manually give each machine an IPv6 address, and to route it through our gateway:-

ip addr add 2001:470:90d3:1::2/64 dev eth0 ip route add ::/0 via 2001:470:90d3:1::1 dev eth0

Again, all being well, you should now be able to route to the wider IPv6 Internet from our newly-configured IPv6 node. More importantly, this also means that the wider IPv6 Internet can route back to you – which brings us to…

Security, not obscurity

Don’t be fooled into thinking that because of the immense range of possible IPv6 addresses that securing your new IPv6 setup isn’t required – IPv6 is no exception when it comes to the Internet Bad Guys, so implementing firewall rules is of the utmost importance.

The problem with IPv4 and NAT is that it’s allowed people to become somewhat complacent about security, because machines behind a NAT device are naturally unreachable from the global Internet. IPv6 does not have NAT, which means you don’t have this (rather lazy) safety net, so we have to do it properly.

Luckily, if you’re familiar with iptables, you’ll be glad to know that there’s an IPv6 equivalent – and it’s called (predicatably) ip6tables. The syntax is identical, and in fact the only noticeable difference is that you’re using IPv6 addresses and networks instead of IPv4 ones.

A quick example would go something like this:-

# Clear our INPUT, OUTPUT and FORWARD chains ip6tables -F INPUT ip6tables -F OUTPUT ip6tables -F FORWARD # Allow packets related to existing connections ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT ip6tables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT # Allow link-local (for neighbour discovery) ip6tables -A INPUT -s fe80::/10 -j ACCEPT # Allow SSH inbound to our gateway from our LAN ip6tables -A INPUT -i lan -s 2001:470:90d3:1::/64 -p tcp -m tcp --dport 22 -j ACCEPT # Allow all outbound from our networks ip6tables -A FORWARD -i lan -s 2001:470:90d3:1::/64 -j ACCEPT ip6tables -A FORWARD -i dmz -s 2001:470:90d3:2::/64 -j ACCEPT ip6tables -A FORWARD -i wlan -s 2001:470:90d3:3::/64 -j ACCEPT # Allow all outbound from our gateway ip6tables -A OUTPUT -j ACCEPT # Allow SSH and HTTPS inbound to our DMZ ip6tables -A FORWARD -i he-ipv6 -d 2001:470:90d3:2::/64 -p tcp -m multiport --dports 22,443 -j ACCEPT # Set the default policy to drop ip6tables -P INPUT DROP ip6tables -P FORWARD DROP ip6tables -P OUTPUT DROP

So there you have it – IPv6 firewalling needn’t be difficult. If you want to make something more complex, you might want to take a look at my previous post about iptables and the ‘mark’ target, which also applies to ip6tables.

IPv6 – automatically

Just like DHCP for IPv4, there are autoconfiguration mechanisms for IPv6 – radvd and DHCPv6. Radvd is the older of the two, but both can be used for the same purpose. Configuration of radvd is relatively straightforward, and if we wanted to provide autoconfiguration on our example LAN, we can do something like this:-

interface lan { AdvSendAdvert on; MinRtrAdvInterval 3; MaxRtrAdvInterval 10; AdvDefaultPreference low; AdvHomeAgentFlag off; prefix 2001:470:90d3:2::/64 { AdvOnLink on; AdvAutonomous on; AdvRouterAddr off; }; };

Where next?

This only covers the start – there’s more involved in bringing an IPv6 network up to scratch, like setting up forward and reverse DNS, and configuring various daemons to talk over IPv6 as well as IPv4. If you’re interested, you might find some of the following links useful reading:-

Thanks to these commenters for pointing out errors in the original post where I’d mixed up two separate networks!