Following on from my first tutorial, we have a box set up which has basic IPv6 connectivity. There’s a firewall in place with a simple but sufficient configuration. And we can ping6 from this box to remote IPv6 destinations.
All of this has, so far, made use only of one network interface (in my case eth0) to set things up. However looking ahead to the next step I am aware that I will want devices inside my network (i.e. my workstations, etc.) to have IPv6 connectivity through this device I am setting up. In other words, this device must, as it does today for IPv4, act as a router.
With IPv4 this is, at a basic level (so forgetting about firewalling and so on) very easy: enable IPv4 forwarding and away you go.
For IPv6? A little more complicated…
My first step was to jump in to /etc/sysctl.conf and, just as I have IPv4 forwarding enabled here, do the same for IPv6. There’s even a (likely commented out) entry already there to help you. So I change it to show:
net.ipv6.conf.all.forwarding = 1
Reboot (or if you prefer manually involve the same change via sysctl or simply dropping the value in via /proc/sys/) and it takes effect.
Why has it all stopped working?
After doing this, the first thing I noticed was that suddenly I could no longer ping6 to my test destination. I find that the default route has disappeared from the route table (ip -6 route show)
It turns out that once the device is defined to be a router (i.e. that IPv6 forwarding is enabled) it stops acting on received Router Advertisements from the ISP, arriving on my WAN link eth0.
I was pretty miffed at first, but of course on reflection this is entirely sensible behaviour – I do not actually know who is sending me a given router advertisement. I have no knowledge of how the ISP has built its IPv6 infrastructure, and while I would hope that only the ISP can send an IPv6 Router Advertisement towards me, maybe not? What if someone else manages to do it too?
That’s why an IPv6 router, even in this context, as a home gateway, needs to treat a Router Advertisement with care!
What to do?
With IPv6 forwarding enabled it is possible to allow the RA to be accepted. In sysctl.conf set:
net.ipv6.conf.all.accept_ra = 1
However this then permits the interface(s) to autoconfig so far as addressing is concerned, but still does not pick up a default route. There is also a sysctl of net.ipv6.conf.all.accept_ra_defrtr which could be useful (if you trust your RA in the first place, that is) but anyway I could not make it work as I’d expect.
So really it comes down to making sure that, once IPv6 forwarding is enabled, that a default route is manually defined. Something along the lines of:
ip -6 route add default via fe80::207:cbff:aaaa:bbbb dev eth0
seems to do the trick
Of course the difficulty here is how you obtain the address of the required gateway. My ISP had not told me what it was. I obtained it by looking at what the default route had been prior to enabling IPv6 forwarding. Of course I could also have simply run tcpdump -i eth0 ip6 and waited for a to show up.To make this permanent, a suitable line can be added to /etc/network.interfaces, so mine now looks similar to:
iface eth0 inet6 static address 2a01:e35:8b25:aaaa::1 netmask 128 gateway fe80::207:cbff:aaaa:bbbb
[EDIT: 2 Aug 2011: “netmask 128” previously read “netmask 64” It *could* be 64, but more likely 128!!]
So with IPv6 forwarding enabled and a default route successfully restored, we can now proceed.