Mobile LAN-oriented filtering in iptables
One of the things that I really like about pf, the OpenBSD firewall, is how it lets you define dynamic packet filtering rules — rules that filter based on your network interfaces’ current addresses at the time of filtering. For instance, if I want to allow SSH connections to my laptop only from my local network:
pass in on xl0 inet proto tcp from (xl0:network) to any \
port ssh flags S/SFRA
(xl0:network) is not resolved to a specific address block at configuration load time; if you switch networks — say, if you go from home to work — the rule’s behavior will change accordingly.
Unless I have overlooked some recent change in Linux, this cannot be achieved in a direct fashion with iptables. You can insert a rule to reject non-LAN source addresses, but such a rule is static. When you change network addresses, the rule must be explicitly updated.
In lieu of rewriting all of netfilter to accommodate this use case (*cough*), I just wrote a shell script to help mitigate the pain of manually updating my laptop’s firewall rules — merely a shortcut to cut down on the amount of typing I do on any given day, but if you tend to move around as much as I do, all those keystrokes can add up :) So with this script you can, in one fell swoop, start and open up global access to an SSH server:
# ssh-serve any
Or only allow local access from the networks you’re connected to:
# ssh-serve lan
Or only local network access on a specific interface:
# ssh-serve lan eth0
Or only access from a given set of IP addresses and/or CIDR blocks:
# ssh-serve addr 192.168.0.104 10.18.0.0/16
Better yet, you can make the whole process automagical by hooking into your Linux distribution’s DHCP client. For instance, in Ubuntu Hardy Heron you can automate ssh-serve by creating a file /etc/dhcp3/dhclient-exit-hooks.d/ssh-serve:
# Allow SSH access from your local network only, and keep these filter
# rules up-to-date as you move from one network to another.
case $reason in
BOUND|REBIND|REBOOT)
ssh-serve lan
;;
esac
This script was written (and named) with Secure Shell in mind, but it could just as easily govern over any other service controlled by a standard SysV init script. See below the jump for the code…