Mastering Linux Firewalls: iptables, nftables, and firewalld
Securing a Linux server requires a solid understanding of how the kernel handles network traffic. For decades, iptables was the undisputed king of Linux firewalls. Today, the landscape has evolved with the introduction of nftables and high-level management tools like firewalld and ufw.
The Foundation: Netfilter
Before diving into the tools, it’s crucial to understand Netfilter. Netfilter is the actual packet filtering framework built deep inside the Linux kernel. It provides a set of hooks at different points in the network stack (like PREROUTING, FORWARD, INPUT, OUTPUT, and POSTROUTING).
Tools like iptables, nftables, and firewalld are just userspace utilities that talk to the Netfilter kernel framework to define rules.
The Legacy of iptables
iptables structures its rules into Tables (Filter, NAT, Mangle) and Chains (Input, Output, Forward).
To block all incoming traffic from a specific IP:
sudo iptables -A INPUT -s 192.168.1.50 -j DROP
To forward port 80 to port 8080:
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
The Problem with iptables
While powerful, iptables has architectural flaws. Every time you add a rule, the entire rule set must be re-evaluated and reloaded by the kernel. On servers with thousands of rules (like Kubernetes nodes), this causes massive performance bottlenecks.
The Modern Standard: nftables
Introduced to solve the performance issues of iptables, nftables provides a much cleaner syntax and drastically improved performance. It allows atomic updates (you can add a single rule without reloading the whole ruleset) and uses a more efficient data structure (sets and maps) for IP matching.
A modern nftables configuration file looks much more like code:
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Accept loopback traffic
iifname "lo" accept
# Accept established connections
ct state established,related accept
# Allow SSH and HTTP/HTTPS
tcp dport { 22, 80, 443 } accept
}
}
Most modern distributions (Debian 11+, RHEL 8+) use nftables as the default backend, even if you run an iptables command (via a compatibility wrapper).
Abstracting Complexity: firewalld
Managing raw iptables or nftables rules can be tedious. firewalld acts as a dynamic firewall manager sitting on top of nftables. It introduces the concept of Zones.
Instead of writing rules for interfaces, you assign an interface to a Zone (e.g., public, internal, dmz), and then assign rules/services to the Zone.
Essential firewalld Commands
Check which zone is active:
sudo firewall-cmd --get-active-zones
Allow HTTP traffic permanently in the public zone:
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --reload
Open a specific custom port:
sudo firewall-cmd --zone=public --add-port=3000/tcp --permanent
sudo firewall-cmd --reload
Create a rich rule to block a specific IP from accessing SSH:
sudo firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='203.0.113.5' service name='ssh' reject"
sudo firewall-cmd --reload
Conclusion
While iptables syntax is still heavily used and worth knowing, the actual execution has moved to nftables. For daily administration, abstracting the complexity away with firewalld (or ufw on Ubuntu) is the safest and most maintainable approach to securing your Linux servers.