IPv6 Stateful Firewall with netfilter/ip6tables
2011/11/13 Leave a comment
IPv6 is coming!
Ok, that was just a provocation. If you have some interest in networking technologies you’ll know for sure that stable IPv6 implementation are around for many years now but very few providers give the user IPv6 connectivity. You can follow the IPv6 deployment status around the world on this Wikipedia page.
Anyway, for those of you who are lucky enough to have a real IPv6 connection, it’s time to add the “6” to some network utility, and that includes ip6tables!
This script is a stateful firewall for an IPv6 standalone and router installation, which provides the same level of security given by an IPv4 NAT router.
This script assumes that there are two wired networks: LAN is the internal one, like a local Ethernet network, and WAN is the external, like a tunnel broker.
The internal network, as well as any WiFi networks, are considered trusted, while WAN is filtered.
Assuming you are running an IPv6 router, you want the IPv6 routing activated on the stack. You can do that with the command:
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
These are the rules that filters packets directed to the host. If this is the external node of your network, you’ll probably want to keep only the essential services open.
So, first set the default input policy to drop:
ip6tables -P INPUT DROP
then, ACCEPT all the packets from trusted networks:
ip6tables -A INPUT -i lo -j ACCEPT ip6tables -A INPUT -i $LAN -j ACCEPT ip6tables -A INPUT -i $WLAN -j ACCEPT
also ACCEPT any packet on the external network for trusted services (SSH and ICMPv6), remember that IPv6 uses ICMPv6 for MAC address resolution:
ip6tables -A INPUT -i $WAN -p tcp --dport ssh -j ACCEPT ip6tables -A INPUT -i $WAN -p icmpv6 -j ACCEPT
lastly, to implement the stateful firewall, ACCEPT every known connection:
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Keep in mind that you can check IPv6 input policy using the link-local IPv6 addresses with the “%interface” suffix. As an example, to ping a link-local address of the host fe80::221:f3ff:fe83:1500 on the “wlan0” interface, use the command:
If your host is routing IPv6 packets between interfaces, the external network have complete direct visibility of internal hosts. The NAT-like security, where all internal hosts are inaccessible from the outside, except for some trusted service, is implemented as following:
first, DROP as default FORWARD policy:
ip6tables -P FORWARD DROP
then, ACCEPT all the packets originated by the internal hosts (this will mark the conntrack entry for that connection as ESTABLISHED):
ip6tables -A FORWARD -i $LAN -o $WAN -j ACCEPT
now, accept all the trusted services (just ICMPv6):
ip6tables -A FORWARD -i $WAN -o $LAN -p icmpv6 -j ACCEPT
finally, accept packets of known connections:
ip6tables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
That’s it! You can find the complete script, named rc.firewall6, on GitHub!