Skip to content

Firewall

firewalld is the managed front end on the RHEL family and is what a workstation or server running that distribution should be configured through. It groups interfaces into zones, and rules are expressed as services and ports permitted in a zone rather than as raw chains.

nftables is the kernel framework underneath. Red Hat deprecated iptables-nft and ipset in RHEL 9, including the iptables, ip6tables, arptables and ebtables compatibility commands, and recommends migrating to the nft command. Reach for nft directly when a rule set is complex enough that firewalld’s abstractions get in the way.

iptables is legacy. It still appears in older runbooks and in container tooling, and is worth being able to read, but new rules should not be written with it.

Terminal window
sudo firewall-cmd --state
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all # everything in the default zone

Permit a service or a port. Without --permanent the change is lost on reload, which is the safe way to test it; with --permanent it survives a reboot but does not take effect until --reload:

Terminal window
sudo firewall-cmd --zone=public --add-service=https
sudo firewall-cmd --zone=public --add-port=8080/tcp
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --reload

Masquerading — required for container and VM traffic to route out through the host:

Terminal window
sudo firewall-cmd --zone=public --add-masquerade --permanent
sudo firewall-cmd --reload

nftables organises rules into named tables and chains. Read the current rule set with:

Terminal window
sudo nft list ruleset

A minimal host policy. The order matters: the rules that keep you connected are added before the policy becomes drop.

Terminal window
sudo nft add table inet filter
sudo nft add chain inet filter input '{ type filter hook input priority 0; policy accept; }'
# Keep existing connections, including the SSH session you are typing into
sudo nft add rule inet filter input ct state established,related accept
sudo nft add rule inet filter input iif lo accept
sudo nft add rule inet filter input tcp dport 22 accept
sudo nft add rule inet filter input ip protocol icmp accept
# Only now switch the default to drop
sudo nft chain inet filter input '{ policy drop; }'

Rules added this way live only until reboot. Persist them by writing the rule set to /etc/nftables.conf (or a file included from it) and enabling nftables.service:

Terminal window
sudo nft list ruleset | sudo tee /etc/nftables.conf
sudo systemctl enable --now nftables

Traffic traverses chains — INPUT for packets addressed to the host, OUTPUT for packets it originates, FORWARD for packets it routes on behalf of something else. Each chain has a default policy applied to anything no rule matched.

Terminal window
sudo iptables -S # print the rules as the commands that would create them
sudo iptables -L -n -v # list them with packet and byte counters

The counters are the useful part when debugging: a rule with zero packets is not being reached, and a rising counter on a DROP rule tells you exactly what is being blocked.