Firewalling IPv6

With my new ISP providing native IPv6 transit, enabling IPv6 in Debian is pretty trivial, just update /etc/networking/interfaces:

iface eth0 inet6 static
	pre-up modprobe ipv6
	address 2001:67c:1388::2
	netmask 64
	gateway 2001:67c:1388::1

if you have a Linux router, enable packet forwarding:

echo 1 > /proc/sys/net/ipv6/conf/all/forwarding

and add AAAA records to DNS:

danielpocock.com.        IN      AAAA    2001:67c:1388:1000::9

Yes, that really is enough to get up and running. Apache was already configured to listen on IPv6 and just needed a restart. However, it is not quite secure: the configuration above routes all traffic on all ports. If somebody has the time to port scan my 64 billion trillion possible IPv6 addresses (every IPv6 customer is allocated a /48 as standard), they might end up connecting to some service that should not be public.

ip6tables

The ip6tables tool for IPv6 does just about everything that iptables does for IPv4. It is tempting to just rewrite an existing firewall script, adding an extra rule for the IPv6 version of every host. For example, my web server is 195.8.117.9, so I copy the 9 off the end and assign the IPv6 address 2001:67c:1388:1000::9 to the same server and add the ip6tables firewall rule:

iptables --append FORWARD -p tcp -d 195.8.117.9 --dport http -j ACCEPT
ip6tables --append FORWARD -p tcp -d 2001:67c:1388:1000::9 --dport http -j ACCEPT

Notice that my IPv6 addressing simply involves re-using the same last byte as the IPv4 equivalent? This is a very easy way to start.

However, it is not quite so simple. IPv6 requires a couple of extra rules, in the simplest form:

# Allow traffic for link-local addresses:
ip6tables -A INPUT -s fe80::/10 -j ACCEPT
# Normally, link-local packets should NOT be forwarded and don't need an
# entry in the FORWARD rule.
# However, when bridging in Linux (e.g. in Xen or OpenWRT), the FORWARD rule is
# needed:
ip6tables -A FORWARD -s fe80::/10 -j ACCEPT

# Allow all ICMPv6 traffic (optional for IPv4, mandatory for IPv6):
ip6tables -A INPUT -p icmpv6 -j ACCEPT
ip6tables -A FORWARD -p icmpv6 -j ACCEPT

This works, but it turns out that it is less than ideal. Beyond that, the firewall can be significantly enhanced by rate-limiting the ICMPv6 packets and various other mechanisms as demonstrated with a practical netfilter example in Appendix B of RFC 4890

The question that arises, how to enable wide use of IPv6 without every sysadmin having to familiarise themselves with all these details of filtering ICMPv6 packets?

Debian firewall packages

My next step will be to look over the existing firewall packages in Debian to see which of them may answer that question. It would be really useful to hear feedback from anybody else who has already undertaken such an evaluation. If none of them are suitable, and if permitted by the licensing terms of RFC 4890, I may well wrap their sample code into a Debian package that can be used as a foundation for people building their own custom firewall scripts.