I finally decided to play with ipset, given that it’s now included in the mainline Linux kernel and enabled in the default Ubuntu kernel. The use of tables/sets (like in OpenBSD’s pf) can make firewalls a lot shorter. Unfortunately Debian/Ubuntu don’t ship current versions of the userland packages. But manhandling the debian-packaging onto newer sources proved easy enough. The resulting amd64 package is available for the daring. A trivial ssh firewall using ipset looks like this:
for family in inet inet6; do
ipset -exist create ssh-allow-$family hash:net family $family
done
for net in $(grep -v ^# /etc/ipset/ssh_allow_inet); do
ipset -exist add ssh-allow-inet $net
done
for net in $(grep -v ^# /etc/ipset/ssh_allow_inet6); do
ipset -exist add ssh-allow-inet6 $net
done
iptables -A INPUT -p tcp -m set --match-set ssh-allow-inet src -m tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 22 -j DROP
ip6tables -A INPUT -p tcp -m set --match-set ssh-allow-inet6 src -m tcp --dport 22 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --dport 22 -j DROP
The contents of /etc/ipset/ssh_allow_inet look like this:
<sten@host:~> cat /etc/ipset/ssh_allow_inet
# me
127.0.0.1
# Work network
192.0.2.0/24
# home
198.51.100.0/24
# friend
203.0.113.1
And the created set looks like this:
<sten@host:~> sudo ipset -l ssh-allow-inet
Name: ssh-allow-inet
Type: hash:net
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 16944
References: 1
Members:
127.0.0.1
192.0.2.0/24
198.51.100.0/24
203.0.113.1