Freerunner simple firewall

This is a simple firewall for the Neo Freerunner.  It requires only the ‘iptables’ package, and assumes that the only inbound traffic you want is either replies to outbound connections you initiated, SSH, pings, or (optionally) any/all traffic over USB networking, ie usb0.  A more ‘proper’ and flexible approach is covered in the article “Freerunner advanced firewall“.  (although the firewall itself is essentially identical) While the firewall rules are essentially the same in both, the ‘advanced’ firewall requires the programs iptables-save and iptables-restore as well.  With those binaries installed, it supports saving/restoring firewall rules on demand, meaning you can change the active firewall rules on the fly and save those changes to be automatically restored on reboot.  Since the ‘iptables-utills’ package gives us little additional functionality apart from load/save active rulesets, I decided to pursue both approaches, the dynamic and the semi-static ruleset, since for many people the simpler approach will serve their security needs effectively while requiring less to be installed.

Iptables v1.3.8-r4 is the latest iptables package in the Angstrom feed, and they also have the package iptables-utils which provides iptables-save and iptables-restore.  I’ve also built the latest iptables version, v1.4.2-rc1, as a single binary that functions as all three commands in one.  My package is (at the time or this writing) hosted at http://newkirk.us/om/iptables_1.4.2-rc1_armv4t.ipk, and I’ve also packaged up ip6tables (linux netfilter firewall control for IPv6 networking – included in the v1.3.8-r4 package from Angstrom) at http://newkirk.us/om/ip6tables_1.4.2-rc1_armv4t.ipk.  Note that my ipk actually installs everything described in the ‘Freerunner advanced firewall’ article, NOT just the iptables binary required to use the script below.

The firewall script below will work with either iptables package – v1.3.8-r4 from Angstrom or v1.4.2-rc1 from my page, and in fact should work with any moderately recent iptables version.  (if you can find another version, that is)  It uses only the ‘iptables’ command.

Now, on to the firewall.  Paste the following script as /etc/init.d/iptables, then invoke “update-rc.d iptables defaults 42″ (my favorite way to paste something like this is to copy the text, go to a console and type ‘cat – >/etc/init.d/iptables’ and enter, then paste and hit ctrl-c):

#!/bin/sh
#
# iptables	This shell script starts and stops an iptables firewall.
#
# chkconfig: 345 90 42
# description: Starts and controls an iptables firewall
# processname: iptables

ipt="/usr/sbin/iptables"
inp="/usr/sbin/iptables -A INPUT"

[ ! -x $ipt ] && exit 0
if test ! -f $ipt
then
    echo "iptables does not appear to be installed, no firewall possible."
    exit 1
fi

start() {
    echo -n "Starting iptables firewall: "
    $ipt -P INPUT DROP
    $ipt -P FORWARD DROP
    $ipt -F
#    $ipt -t nat -F
#    $ipt -A FORWARD -i usb+ -j ACCEPT
#    $ipt -t nat -A POSTROUTING -o ! lo -j MASQUERADE
#    echo "1" >/proc/sys/net/ipv4/ip_forward
    $ipt -P OUTPUT ACCEPT
    $inp -i lo -j ACCEPT
#    $inp -i usb+ -j ACCEPT
#    $inp -i usb+ -s 192.168.0.0/24 -j ACCEPT
    $inp -m state --state ESTABLISHED,RELATED -j ACCEPT
    $inp -p icmp -j ACCEPT
#    $inp -p tcp --dport 22 -m state --state NEW -j LOG --log-level 7 --log-prefix "SSHin: "
    $inp -p tcp --dport 22 -j ACCEPT
    echo -n "Firewall configured, "
#    echo -n " usb network allowed in, "
    echo "pings and SSH allowed in."
}

stop() {
    echo -n "Stopping iptables firewall (wide-open): "
    $ipt -P INPUT ACCEPT
    $ipt -P FORWARD ACCEPT
    $ipt -F
 #   $ipt -t nat -F
    echo "Firewall removed, no filtering in place."
}

lock() {
    echo -n "Firewall locking down: "
    $ipt -P INPUT DROP
    $ipt -P FORWARD DROP
    $ipt -P OUTPUT ACCEPT
    $ipt -F
    $ipn -m state --state ESTABLISHED,RELATED -j ACCEPT
    echo " nothing NEW allowed in."
}
# See how we were called.
case "$1" in
  start)
	start
	;;
  stop)
	stop
	;;
  lock)
	lock
	;;
  restart|reload)
	stop
	start
	;;
  *)
	echo "Usage: $0 {start|stop|lock|restart}"
	exit 1
esac

exit 0

NOTE: This script presumes that the iptables binary lives in /usr/sbin, the default install location used by both the Angstrom and my own iptables ipks – if you’ve overridden the install location you will need to edit the ‘ipt=’ and ‘inp=’ lines near the top to match the path to your iptables binary.

On next reboot, it will automatically set up the firewall – you can manually start it now with “/etc/init.d/iptables start”.  At any time you can call the script with ‘start’, ‘stop’, ‘restart’ or ‘lock’.  Be sure you understand the difference between ‘stop’ and ‘lock’: ‘stop’ removes all firewalling completely, allows any/all traffic, while ‘lock’ locks down the firewall, permitting ONLY outbound traffic, replies to that, and device lo.  Be aware that ‘lock’ WILL prevent you from SSH’ing into the Freerunner, but a current active SSH session will be permitted to continue, since it is state ‘ESTABLISHED’.

You can see several lines commented out, including three referring to USB networking. With them commented out, SSH, pings, and replies to connections initiated by the Freerunner are allowed in via USB networking, as with other networking devices. If the first usb+ rule is uncommented, ANY traffic inbound via USB networking is allowed, while the second restricts it to only traffic from the expected 192.168.0.0/24 subnet on that interface. (change that IPnet in the script if your USBnet is configured differently) One of those two will be needed if you are utilizing a remote X11 login (port 6000 is open on the default Freerunner, as well as 111 and 22) or other applications/services that the host computer connects to over USBnet, if the connection is initiated on the desktop instead of the Freerunner.

Additional rules commented out: There are a few FORWARD and ‘-t nat’ rules, plus the /proc/sys/net/ipv4/ip_forward activation that tells the kernel to allow packets to route in one interface and out another.  Enabling them means FORWARD is locked down except for traffic coming in via USB networking (and ‘ESTABLISHED/RELATED’ states again) – which is allowed through and NATted with the ‘MASQUERADE’ target, permitting the Freerunner to function as a Wifi, GPRS, PPP-over-GSM, or Bluetooth PAN gateway device for the desktop system. (just jack into USB, fire up GPRS or whatever, point desktop system at Freerunner as its gateway)    Also commented out is a LOG rule that will log each new SSH connection attempt. These are all commented out by default to avoid the overhead of loading kernel modules to support the LOG and MASQUERADE targets and the nat table.

Be aware that using ‘MASQUERADE’ involves more resources than using ‘SNAT’ (Source NAT) – SNAT specifies a static IP that is used for outbound packets, while MASQUERADE always uses the first active IP on the interface being used.  SNAT is more efficient, but accommodating dynamic IPs is awkward at best – if you switch to a different WiFi AP on possibly a different LAN, your IP is subject to change which effectively breaks SNAT.  And you need a separate SNAT rule for each interface.  MASQUERADE will periodically check the IP(s) of the interface over which a connection occurs, which means a small amount of time and processing is used to look up that information, but it’s much more efficient insofar as ruleset maintenance – one unchanging rule instead of 3-4 that require intermittent updating when IPs change.  In this instance, I unhesitatingly choose MASQUERADE and let the kernel deal with adapting to changing IPs.  (oh, and it’s a bad idea to NAT traffic on device lo – hence the ‘-o ! lo’ which applies the rule only if the packet in question is NOT going out on lo)

Apart from the optional rules mentioned above, the rules are simple: If it’s on interface lo let it in. (this is potentially all sorts of local communications within the system – if you don’t allow it freely, unexpected things can break, like local dnscache lookups) If it’s a ping, let it in. If it’s SSH, allow it in. If it’s connection state is ESTABLISHED (like replies to packets that left the Freerunner, or SSH packets after the first – which is state NEW) or RELATED (like FTP data is related to FTP control, though different ports) it is allowed in. Everything else is discarded.  Outbound traffic is unrestricted.

Note on logging:  The optional ‘-j LOG’ rule presented here will log all NEW state SSH connection attempts.  This is done via syslog, which on current default OM distributions does NOT log anything to a file.  You’ll need to enable logging to a file in order to actually record these log entries for later examination.

That’s it.  A simple but effective firewall ruleset, and a simple but effective script that automatically sets it up on reboots.  The article “Freerunner advanced firewall” will cover a more flexible approach to firewall management, but utilizes the same rules as its basis.

j

3 thoughts on “Freerunner simple firewall

  1. Pingback: חופש הדיבור » ארכיון » ועל אף עירא ..

  2. Mark Lamers (1 comments)

    in lineno  25 you use “inp” which should be “ipt”
    thanx for the script nice work

  3. j (1 comments) Post author

    Thanks for the heads-up on line 25, I fixed it. I changed to the macros after I’d commented that section out.

    j

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>