Linux

Tiny Firewall

About

This tiny firewall script is intended for use on small Linux-based routers, for example, with the OpenWRT distribution. It is intended for users who are already familiar with iptables and understand the commands generated by the script, but still prefer the simplified syntax over plain iptables commands.

The configuration concepts are partially stolen from Shorewall, but it only supports a very limited subset of Shorewall's functionality. Especially, IPv6 is not yet supported by the firewall script.

The script has been successfully tested on OpenWRT 8.09 and 10.03.

WARNING

A wrong configuration (or bugs in the firewall script) can make your router to become unaccessible over the network. In a worst case scenario this means that your hardware is just a piece of trash. USE ON YOUR OWN RISK!

Download

The tiny firewall script can be downloaded from here:

It is published under the terms of the GNU GPL v3 (see http://www.gnu.org/licenses/).

Installation

The following installation instructions apply for OpenWRT 8.09 and 10.03. If you use another distribution, you may have to adapt the installation procedure.

Untar the package, copy its contents to /etc/firewall on the router, and create some symlinks:

# ln -s ../firewall/etc_init.d_myfirewall.sh /etc/init.d/myfirewall
# ln -s ../init.d/myfirewall /etc/rc.d/S46myfirewall

You can disable the firewall script from OpenWRT with:

# /etc/init.d/firewall disable

If your router does not have the ASH shell (/bin/ash), you will have to adapt the first line of /etc/firewall/firewall.sh. The script should also work with /bin/bash and some other shells.

Configuration

The configuration is done by the files with .conf extension in /etc/firewall. Lines beginning with # are comments; empty lines will be skipped. Each file contains some comments with a minimalist description of the valid syntax. A more extensive description is given below.

The file /etc/firewall/variables.conf contains some shell variables used by the firewall script. The file will be sourced by the firewall script at its very beginning! In principle, it should be self-explanatory. Important variables that might require customization are:

DEBUG
If set to 1, the firewall script will just print what it would do. This is very useful for testing purposes. Always set to 1 when trying new configurations. (defaults to 0)
ADMIN_IP
This is the IP or network which will be granted access to the SSH and Telnet port of the router, if the firewall script exists with an error. (defaults to 192.168.1.3)

You can explicitly load kernel modules, although this is in general not required. Add a line with the name of the kernel module optionally followed by an arbitrary number of module parameters to /etc/firewall/modules.conf.

Kernel variables can be configured in /etc/firewall/kernel_vars.conf. Specify enable or disable followed by the kernel variable. Shell wildcards, for example *, are permitted. See the configuration file for examples. The default file shipped with the firewall package should be sufficient in most cases.

The user has to map interfaces to zones (one-to-one mapping!). This is done in /etc/firewall/interfaces.conf and has the only purpose of giving the interfaces some nice names.

The basic filtering behaviour of the script is as follows. The first rule that matches will stop further processing.

  1. all traffic on the loopback interface (lo) is accepted
  2. INVALID packets are dropped (according to nf_conntrack module)
  3. dangerous ICMP packets are dropped
  4. packets with invalid TCP flags are dropped (stolen from Shorewall)
  5. ESTABLISHED or RELATED packets are accepted (again according to nf_conntrack module)
  6. packets are filtered according to the rules in /etc/firewall/rules.conf
  7. packets are filtered according to the default policies in /etc/firewall/policies.conf
  8. packets are dropped

The filtering rules are defined in the file /etc/firewall/rules.conf. They consist of one line each with three mandatory entries followed by three optional entries. The first mandatory entry can be any of the default targets or one out of logdrop, reject, or logreject. Optional entries can be skipped or set to a minus -, if they shall not take any effect.

The filtering policies (something like default rules, if no other rule applied so far) are specified in the file /etc/firewall/policies.conf. A policy line consists of the same three mandatory entries as a rule, but does not have any optional entries.

The firewall script supports network address translations , which can be specified through entries in /etc/firewall/nat.conf. Masquerading is on by default for the 192.168.1.0/24 and 192.168.2.0/24 networks (corresponding to the LAN and WLAN on OpenWRT routers). Optional entries can again be skipped or set to a minus -, if they shall not take any effect.

The firewall script supports mangling of the MSS value of TCP SYN packets. To enable it for packets forwarded to a certain destination zone, put the name of the zone into the file /etc/firewall/tcpmss.conf.

Finally, at the very end of the script, the file /etc/firewall/raw_post.conf will be sourced. It is empty by default and allows to execute arbitrary user-defined shell code.

Starting

The script can be (re)started by running:

# /etc/init.d/myfirewall

It copies the directory /etc/firewall to /tmp (if it does not yet exist) and runs /tmp/firewall/firewall.sh. The /tmp directory is in a tmpfs filesystem, hence, the copying will not result in any writes to the flash memory of the router. The commands executed by firewall.sh and the exit status are written to the log file /tmp/firewall.log. Typically, the remote login session will get stuck when (re)starting the firewall script, so the log file is essential for checking the firewall status.

The procedure of creating a temporary copy on a tmpfs filesystem has a big advantage: The user can try out new configurations under /tmp/firewall first. Restarting /etc/init.d/myfirewall will cause a restart with the configuration under /tmp/firewall (as this directory exists now). If this fails and the router becomes unaccessible over the network, a reboot will result in the loss of any data under /tmp and the previously working configuration stored under /etc/firewall will be loaded again. If the new configuration works, the user can copy it to /etc/firewall.