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:
- Firewall and NAS functions are of vital importance for the security of a FreedomBox. These functions should therefore be implemented on the FreedomBox hardware and not be delegated to third party hardware. Most routers don’t come with source code or hardware specs and cannot be fully trusted.
- The FreedomBox cannot control the firewall or NAT of a particular router. There are just too many different brands and models. As a device for non technical users the FreedomBox cannot ask the user to manage the router firewall and NAT every time a new program is (de-)installed.
- Having a firewall on the FreedomBox gives us the possibility to log attacks and implement our own counter measures.
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:
192.168.1.3
This is the address of the br0 interface. (a.k.a. the internal address of my FreedomBox)
192.168.1.10
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: 192.168.1.10) to the host system (IP: 192.168.1.3). At the moment OpenVPN is the only service connected to the internet that is running directly on the host.
Objectives.
Installing a firewall/NAT should accomplish the following:
- Strengthen the isolation of the VM’s.
- Make it possible to have firewall settings for a single VM or a group of VM’s.
- Prevent VM’s to access services on the host system except for some necessary services.
- Create routes for traffic that cannot be routed by the internet module.
- Make it possible to run services on non standard ports.
- Forward traffic to other FreedomBox systems.
- Logging attacks.
Some small adjustments.
In order to integrate the firewall into my FreedomBox I had to make the following changes to my setup:
- Add a vendor class identifier to the DHCP request of a LXC module.
- Use the vendor class identifier to give LXC modules IP addresses from a separate DHCP range.
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:
change:
dhcp-range=192.168.1.10,192.168.1.250,12h
to:
dhcp-vendorclass=set:lxc,lxc.module
dhcp-range=net:lxc,192.168.1.10,192.168.1.50,12h
dhcp-range=192.168.1.100,192.168.1.150,12h
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:
- interfaces – specifies network interface <> zone relations.
- zones – defines zones and sub-zones
- hosts – specifies sub-zones
- policy – the default actions for inter-zone traffic
- rules – the exceptions to the policy
- tunnels – needed for VPN
- routestopped – specifies the state after Shorewall is stopped.
I have the following configuration:
interfaces
#ZONE INTERFACE BROADCAST OPTIONS
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)
zones
# IN OUT
#ZONE TYPE OPTIONS OPTIONS OPTIONS
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.
hosts
#ZONE HOST(S) OPTIONS
imod br0:192.168.1.10
vmnet br0:192.168.1.11-192.168.1.50 routeback
loc br0:192.168.1.100-192.168.1.150 routeback
This file has all the sub-zones
policy
#SOURCE DEST POLICY LOG LEVEL LIMIT:BURST
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
# The FOLLOWING POLICY MUST BE LAST
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.
rules
# DEST SOURCE ORIGINAL RATE USER/ MARK
#ACTION SOURCE DEST PROTO PORT PORT(S) DEST LIMIT GROUP
SECTION NEW
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:192.168.1.10:22 tcp 99999
# enable OpenVPN
DNAT:info net fw:192.168.1.3:1194 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
).
tunnels
#TYPE ZONE GATEWAY GATEWAY_ZONE
#openvpnserver:1194 net 0.0.0.0/0
routestopped
# DEST SOURCE
#INTERFACE HOST(S) OPTIONS PROTO PORTS PORTS
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.