
Linux Networking Mastery Series Part 5: Firewalls and Packet Filtering
Welcome back to Linux Networking Mastery!
In previous parts we built a strong foundation:
- Part 1 – network stack basics and inspection tools
- Part 2 – interface and IP configuration (temporary + persistent via Netplan, nmcli, systemd-networkd)
- Part 3 – routing tables, static/policy routing, namespaces, simple router setup
- Part 4 – name resolution, systemd-resolved, per-link/global DNS, troubleshooting
Now we add a critical security layer: firewalls.
We'll focus on the modern nftables framework (the successor to iptables), look at higher-level front-ends (firewalld on RHEL/Fedora family and ufw on Ubuntu/Debian), write practical rules for common services, and understand stateful connection tracking.
By the end you'll be able to secure a server, allow only necessary traffic, and understand the transition away from legacy iptables.
From iptables to nftables – Why the Change?
iptables (and ip6tables, arptables, ebtables) served Linux for ~20 years but had serious limitations:
- Multiple separate tables/chains per protocol/family
- Difficult rule ordering and complex matching
- Performance issues with very large rulesets
- No atomic updates (rules applied one-by-one)
nftables (kernel 3.13+, userspace since ~2014) replaces all of them with:
- Single framework, unified syntax
- Tables → chains → rules
- Sets, maps, verdicts, concatenations, incremental updates
- Better performance and atomic rule-set replacement
- Native IPv4 + IPv6 + bridge + netdev support
Most distributions switched as default in 2019–2022:
- Fedora → nftables default since Fedora 32 (2020)
- Ubuntu → nftables backend default since 22.04 (2022), though ufw still uses iptables-nft compatibility layer by default
- Debian → nftables default since Debian 11 (bullseye, 2021) in many contexts
iptables-nft / ip6tables-nft provide a compatibility layer so old iptables commands still work (they translate to nft).
Working Directly with nftables
Basic Structure
table inet myfilter { # inet = IPv4 + IPv6
chain input {
type filter hook input priority 0; policy drop;
# rules here
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
Common hooks:
input→ packets to local processesforward→ packets being routed through the machineoutput→ packets originating from local processesprerouting/postrouting→ used in nat table
Quick Practical Example – Minimal Secure Server
Allow established/related, loopback, SSH, HTTP/HTTPS, drop everything else:
#!/usr/bin/env bash
# Reset to clean state
sudo nft flush ruleset
sudo nft -f - <<EOF
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept comment "Allow return traffic"
ct state invalid drop
iifname "lo" accept comment "Loopback"
tcp dport 22 ct state new accept comment "SSH"
tcp dport { 80, 443 } ct state new accept comment "Web"
# Optional: allow ping (careful in production)
icmp type echo-request limit rate 5/second accept
# Log dropped packets (optional, noisy)
# log prefix "DROPPED: " drop
}
chain forward {
type filter hook forward priority 0; policy drop;
# If this is not a router → keep drop
}
chain output {
type filter hook output priority 0; policy accept;
}
}
EOF
Apply: sudo chmod +x firewall.sh && sudo ./firewall.sh
List rules:
sudo nft list ruleset
Persistent nftables Rules
Debian/Ubuntu: save with
sudo nft list ruleset > /etc/nftables.conf
Enable:sudo systemctl enable nftablesFedora/RHEL:
/etc/sysconfig/nftables.confor use firewalld (recommended)
Higher-Level Front-Ends
firewalld (default on Fedora, RHEL, CentOS Stream, Rocky, AlmaLinux)
Zone-based firewall – very convenient for servers with changing roles.
Common zones: public, internal, trusted, drop, block, home, work, dmz, external
Quick examples:
# See active zone
sudo firewall-cmd --get-active-zones
# Allow SSH on public interface permanently
sudo firewall-cmd --permanent --zone=public --add-service=ssh
sudo firewall-cmd --reload
# Allow web server
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
# Rich rule example: allow SSH only from specific IP
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.42" service name="ssh" accept'
# Port forward 8080 → internal 80
sudo firewall-cmd --permanent --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=192.168.100.50
# Masquerade (NAT) for LAN clients
sudo firewall-cmd --permanent --zone=external --add-masquerade
List everything: sudo firewall-cmd --list-all-zones
ufw (Uncomplicated Firewall) – Ubuntu/Debian favorite
Very simple interface over iptables-nft (or pure nftables in newer versions).
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh # or 22/tcp
sudo ufw allow http
sudo ufw allow https
sudo ufw allow from 203.0.113.0/24 to any port 3306 proto tcp comment 'MySQL from office'
# Rate limiting
sudo ufw limit ssh
# See status with numbers
sudo ufw status numbered
# Delete rule by number
sudo ufw delete 3
# Enable (careful – make sure SSH is allowed first!)
sudo ufw enable
Connection Tracking and Stateful Filtering
Both nftables and firewalld/ufw use the conntrack (connection tracking) module.
Key states:
- NEW
- ESTABLISHED
- RELATED
- INVALID
Rule of thumb for servers:
- Allow ESTABLISHED,RELATED early
- Allow NEW only for services you want to expose
- Drop INVALID
Hands-On Exercises
nftables minimal firewall
- Flush current ruleset
- Apply the example script above (adjust ports)
- Test: can you still SSH? Can external hosts reach a web server? Try
curlfrom another machine.
firewalld zone switch (if on Fedora/RHEL family)
- Move interface to
dropzone → test connectivity - Move back to
public, add ssh/http services
- Move interface to
ufw rate-limit (Ubuntu/Debian)
- Enable ufw with SSH allowed
- Add rate limit on SSH
- Try many rapid SSH attempts from another host
Safety warning: Always allow SSH (or have console/rescue access) before enabling strict policies!
What's Next?
In Part 6 we will configure and harden common network services: SSH server (keys, no password, fail2ban basics), lightweight web servers (Nginx/Apache), file sharing (NFS and Samba), and a simple DHCP server.
Leave Linux Networking Mastery Series Part 5: Firewalls and Packet Filtering to:
Read more #computernetworks posts
Best Posts From Changzao Heka Fei
We have not curated any of x9ed1732b's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.
More Posts From Changzao Heka Fei
- Linux Networking Mastery Series Part 10: Container and Virtualization Networking
- Linux Networking Mastery Series Part 9: Wireless Networking on Linux
- Linux Networking Mastery Series Part 8: Advanced Networking Features
- The Future of Multi-Agent AI: From Cloud Orchestras to Decentralized Device Collaboration
- Linux Networking Mastery Series Part 7: Monitoring and Troubleshooting Tools
- Linux Networking Mastery Series Part 6: Network Services and Servers
- Linux Networking Mastery Series Part 5: Firewalls and Packet Filtering
- Linux Networking Mastery Series Part 4: DNS Configuration and Name Resolution
- Linux Networking Mastery Series Part 3: Routing, Gateways, and Advanced Addressing
- Linux Networking Mastery Series Part 2: Managing Network Interfaces and IP Configuration