Guide from 2013. Commands and package versions have changed since then.
If you run a website or other services on a Raspberry Pi, you should know what traffic reaches it and have a firewall in place. Writing iptables rules by hand is hard if you've never done it. FERM makes it much easier: it's a wrapper with a far simpler rule syntax. This guide shows how to set up a working firewall for a web server and SSH on Raspbian.
1. Update the system
root@raspberrypi:~# apt-get update && apt-get -y upgrade2. Install FERM and conntrack
root@raspberrypi:~# apt-get install ferm conntrack
Enable ferm on bootup: Yes3. Move SSH to another port
Port 22 is one of the most attacked ports. In this example we move SSH to port 63222. Pick a number from the unregistered range 49152-65535.
root@raspberrypi:~# nano /etc/ssh/sshd_config# What ports, IPs and protocols we listen for
Port 63222 # default 22
...root@raspberrypi:~# service ssh restart
[ ok ] Restarting OpenBSD Secure Shell server: sshd.Don't close your current session after restarting SSH. Open a new one first and check that you can connect on the new port.
4. Configure the firewall
root@raspberrypi:~# nano /etc/ferm/ferm.conf# -*- shell-script -*-
#
# Example for ssh (63222), http, https and IPv6
#
table filter {
chain INPUT {
policy DROP;
# connection tracking
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
# allow local packet
interface lo ACCEPT;
# respond to ping
proto icmp ACCEPT;
# snmp - if you need for monitoring as CACTI, ICINGA, ...
proto udp dport snmp ACCEPT;
# allow tcp SSH, FTP, HTTP, HTTPS, ...
proto tcp dport (63222 http https) ACCEPT;
}
# outgoing connections are not limited
chain OUTPUT {
policy ACCEPT;
}
# only for a router
chain FORWARD {
policy DROP;
}
}
# IPv6 rules
domain ip6 table filter {
chain INPUT {
policy DROP;
# connection tracking
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
# allow local connections
interface lo ACCEPT;
# allow ICMP (for neighbor solicitation, like ARP for IPv4)
proto ipv6-icmp ACCEPT;
# allow tcp connections
proto tcp dport (http https) ACCEPT;
}
# outgoing connections are not limited
chain OUTPUT policy ACCEPT;
# only for a router
chain FORWARD policy DROP;
}root@raspberrypi:~# service ferm restart
[ ok ] Reloading Firewall configuration....5. Check the iptables rules and current connections
root@raspberrypi:~# iptables -nvL
Chain INPUT (policy DROP 43 packets, 5669 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 state INVALID
27 1772 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:161
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:63222
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 23 packets, 2164 bytes)
pkts bytes target prot opt in out source destinationCurrent connections:
root@raspberrypi:~# conntrack -L
tcp 6 299 ESTABLISHED src=192.168.252.119 dst=192.168.252.120 sport=51374 dport=63222 src=192.168.252.120 dst=192.168.252.119 sport=63222 dport=51374 [ASSURED] mark=0 use=1
tcp 6 431957 ESTABLISHED src=192.168.252.120 dst=192.168.252.119 sport=22 dport=50941 src=192.168.252.119 dst=192.168.252.120 sport=50941 dport=22 [ASSURED] mark=0 use=1
conntrack v1.2.1 (conntrack-tools): 2 flow entries have been shown.6. Done
This is a basic working firewall for a website on a Raspberry Pi with Raspbian. FERM can do much more: variables, more complex rule structures, port names from /etc/services or plain port numbers. You'll find plenty of other examples online.
Sources: FERM, Debian Wiki