Adding a firewall and NAT to my FreedomBox

Rob van der Hoeven
Thu Jun 09 2011

Something every FreedomBox should have is a firewall combined with NAT functionality. These functions are provided by every router, so why not let the router take care of these functions? There are several reasons against using the router for these functions:

Read this first.

This article is one in a series that describes the building of my FreedomBox. Not all information from the previous articles is repeated.

A short overview of my FreedomBox architecture.

In order to understand the configuration of the firewall you need to have a high level view of the architecture of my FreedomBox. In my architecture I use virtual machines (Linux Containers: LXC) that are all part of the same bridged network br0. All VM's use DHCP to get an IP address. There are two static IP addresses:

This is the address of the br0 interface. (a.k.a. the internal address of my FreedomBox)

This address belongs to a special VM: the internet module. The internet module is a so called bastion host A bastion host is a special hardened system that is placed in the DMZ of the router as a gateway to the internal systems (or programs).

In my architecture I try to run every service that is connected to the internet inside its own VM. Access from the internet to a service inside a VM always passes the internet module first.

Sometimes it is not possible to run a service inside a VM. In that case I use NAT to route incoming requests from the DMZ (IP: to the host system (IP: At the moment OpenVPN is the only service connected to the internet that is running directly on the host.


Installing a firewall/NAT should accomplish the following:

Some small adjustments.

In order to integrate the firewall into my FreedomBox I had to make the following changes to my setup:

For the vendor class identifier I changed my lxc-debian-box script. Click the link for the update. If you have already made some LXC modules you can bring them up to date by adding the following line to the /etc/dhcp/dhclient.conf file inside the container:

send vendor-class-identifier "lxc.module";

The vendor-class-identifier is used by dnsmasq. The file /etc/dnsmasq.conf should be edited as follows:





Restart dnsmasq and all the containers to activate the changes.

Installing Shorewall.

On my FreedomBox I use Shorewall for the firewall/NAT functions. It is a very mature and flexible program. Installing is simple:

apt-get install shorewall

Configuring Shorewall.

Shorewall is well documented so I only give a quick overview before presenting my Shorewall configuration.

Central in the Shorewall configuration is the concept of zones. A zone is one-to-one coupled to a network interface. If it is necessary to have multiple zones within the same network (this is the case with my FreedomBox) you can specify sub-zones. Only traffic between different (sub-)zones is examined by the firewall. Default actions for inter-zone traffic are specified by a policy. Exceptions to the policy are specified by rules.

All Shorewall configuration files are in the directory /etc/shorewall. After installing this directory only has one file (shorewall.conf) in it that does not have to be changed. The actual configuration is in the files:

I have the following configuration:



net     br0           detect        bridge,dhcp
vpn     tap0

On my system there are two network interfaces, br0 is placed in the net zone, this zone represents the internet. For OpenVPN I have a second zone (I will write about my OpenVPN configuration in a next article)


#                                 IN          OUT

fw          firewall
vpn         ipv4
net         ipv4
loc:net     ipv4
vmnet:net   ipv4
imod:vmnet  ipv4

The fw zone is a special firewall zone. Think of “fw” as the system on which Shorewall runs. The net zone is split in tho sub-zones: loc and vmnet. Loc stands for all the systems that are not VM's, those systems are in the vmnet zone. One special VM, the internet module, is placed inside its own imod sub-zone.


#ZONE     HOST(S)                           OPTIONS

imod      br0:
vmnet     br0:     routeback
loc       br0:   routeback

This file has all the sub-zones



net         all      DROP       info
imod        vmnet    ACCEPT
imod        all      REJECT     info
vmnet       net      ACCEPT
vmnet       all      REJECT     info
loc         all      ACCEPT
$FW         all      ACCEPT
vpn         all      ACCEPT


all         all      REJECT     info

The policies are examined from top to bottom and the first match cancels further processing of policies. You can see that no traffic from the net zone to any other zone is allowed by the default policy. The exceptions to the policies are in the rules configuration file.


#                                                           DEST     SOURCE     ORIGINAL     RATE     USER/     MARK
#ACTION        SOURCE      DEST                     PROTO   PORT     PORT(S)    DEST         LIMIT    GROUP


Ping(DROP)     net         all

# enable DHCP and DNS access for zones on the freedombox

ACCEPT         imod        $FW                      udp     67:68
DNS(ACCEPT)    imod        $FW
ACCEPT         vmnet       $FW                      udp     67:68
DNS(ACCEPT)    vmnet       $FW
ACCEPT         loc         $FW                      udp     67:68
DNS(ACCEPT)    loc         $FW

# enable HTTP and SSH access, use a non-standard port for SSH

ACCEPT:info    net         imod                     tcp     http
DNAT:info      net         imod:     tcp     99999

# enable OpenVPN

DNAT:info      net         fw:      udp     1194

The only traffic from the net zone to my FreedomBox is HTTP, SSH and OpenVPN traffic.

It's amazing how many people try a brute-force attack on your SSH port. Even if you clearly indicate that it is only possible to login with RSA. I got very annoyed by the constant flickering of my lan-light so for SSH i'm using a non-standard port (not port 99999 ;-)).


#TYPE                ZONE    GATEWAY      GATEWAY_ZONE
#openvpnserver:1194  net


#                                               DEST      SOURCE

br0            -          source

Running Shorewall

With the configuration in place Shorewall can be started. The Debian packagers have wisely prevented Shorewall to start by default. For this you have to edit /etc/default/shorewall and change the startup configuration option. Shorewall is a very flexible program. This flexibility comes at a price: it is very easy to make a mistake, and mistakes can lock you out. I think it is best to start Shorewall manually. If you make a mistake you can correct the error after restarting the system.