There are many ways to configure a firewall in Linux. Some people prefer ufw
, others go straight to iptables
or nftables
. But in between those layers of complexity, there’s a small, quiet tool that often goes unnoticed: Ferm, For Easy Rule Making.
The name says it all.
I like Ferm because it doesn’t try to be fancy or abstract. It simply translates human-readable logic into firewall rules that the system understands. It’s one configuration file, clean and transparent, no need to remember long chains of iptables commands that make your head spin.
Why Choose Ferm
On most of my Debian 12 servers, my security model is simple: block everything by default and open only specific ports from trusted sources. I want something that’s explicit, maintainable, and not dependent on background daemons. Ferm gives me exactly that.
With Ferm, writing firewall rules feels like writing a scrip, structured, readable, and explainable. There are no “zones” or “presets,” just clear logical rules that you define yourself.
Example: Allowing Access from Specific IPs
Let’s say we have a Debian 12 server with public IP 203.0.113.50
.
We want to allow SSH (port 22) only from the admin laptop 203.0.113.20
,
and allow HTTP/HTTPS (80 and 443) only from the office network 198.51.100.0/24
.
Everything else should be denied.
First, install Ferm:
0 1 2 3 4 |
sudo apt update sudo apt install -y ferm sudo systemctl enable ferm |
Then create /etc/ferm/ferm.conf
:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@def $trusted_http = ( 198.51.100.0/24 ); # office network @def $trusted_ssh = ( 203.0.113.20 ); # admin laptop table filter { chain INPUT { policy DROP; interface lo ACCEPT; mod state state (ESTABLISHED RELATED) ACCEPT; proto icmp ACCEPT; proto tcp dport 22 saddr ($trusted_ssh) ACCEPT; proto tcp dport (80 443) saddr ($trusted_http) ACCEPT; } chain FORWARD { policy DROP; } chain OUTPUT { policy ACCEPT; } } |
Save and apply:
0 1 2 3 |
sudo ferm -n /etc/ferm/ferm.conf # syntax check sudo systemctl restart ferm |
Within seconds, your firewall is active.
Any connection outside those IPs will be quietly dropped.
A Small Philosophy Behind the Configuration
Firewalls don’t need to be complicated. They’re like the fence around your house — strong enough to keep things safe, but with gates you choose to open. Ferm lets you design that fence in a language that makes sense to you.
What I like most about this approach is not just the security — it’s the intentionality. Every open port becomes a conscious choice, not a side effect of software defaults.
Testing and Verification
After applying the configuration, it’s always good to verify.
From your trusted admin laptop, check if SSH and web access still work:
0 1 2 3 4 |
ssh user@203.0.113.50 curl -I http://203.0.113.50 curl -I https://203.0.113.50 |
Then, from any untrusted machine, try to connect to those same ports. You should see no response — the packets are silently dropped.
If you want a more detailed check, use nmap
from another host:
0 1 2 |
nmap -Pn 203.0.113.50 |
Only ports 22, 80, and 443 should appear as open — and only if you’re scanning from the allowed IPs.
This simple test closes the loop: your firewall is active, predictable, and fully under your control.
Closing Thoughts
In a world of containers, proxies, and cloud layers everywhere, having one simple, dependable firewall at the system level still matters. Ferm isn’t popular, and maybe that’s its charm. It’s lightweight, stable, and honest about what it does.
Sometimes the best tools aren’t the most powerful ones, but the ones that stay true to their purpose.
Ferm is one of those.