firewalld is the default firewall manager on AlmaLinux, Rocky Linux, RHEL, CentOS Stream and Fedora. You control it with firewall-cmd. It organises rules into zones and services, and changes apply without dropping existing connections.
Status
sudo systemctl status firewalld
sudo firewall-cmd --state
sudo firewall-cmd --list-all
--list-all shows the default zone’s interfaces, allowed services and ports, and rich rules.
Runtime vs permanent
The most important concept:
- Commands without
--permanentchange the running configuration — effective immediately, lost on reload or reboot. - Commands with
--permanentchange the saved configuration — effective after--reload.
Typical pattern:
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Or test at runtime first, then save what’s running:
sudo firewall-cmd --add-port=8080/tcp
# test…
sudo firewall-cmd --runtime-to-permanent
Zones
A zone is a trust level with its own rules. Each network interface (or source address range) belongs to one zone.
firewall-cmd --get-zones
firewall-cmd --get-default-zone # usually "public"
firewall-cmd --get-active-zones
sudo firewall-cmd --zone=public --list-all
Common zones: public (default, untrusted networks), internal, trusted (everything allowed), drop (drop everything incoming), block.
Bind a private interface to a more trusting zone:
sudo firewall-cmd --permanent --zone=internal --change-interface=eth1
Or assign a source range to a zone — e.g. let your VPN subnet reach everything:
sudo firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
Services and ports
firewall-cmd --get-services # predefined services
sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --permanent --remove-service=cockpit
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --add-port=27015-27030/udp
sudo firewall-cmd --reload
Services are XML definitions in /usr/lib/firewalld/services/. Create your own in /etc/firewalld/services/ for apps with several ports.
Changed the SSH port? Either add the new port, or edit a copy of the ssh service. Don’t remove ssh until the new port works. (SELinux also needs semanage port -a -t ssh_port_t -p tcp NEWPORT.)
Rich rules: IP-based restrictions
Allow MySQL only from the app server:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.6" port port="3306" protocol="tcp" accept'
Allow SSH only from your office network, and stop allowing it from everywhere:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.0/24" service name="ssh" accept'
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
Block an address:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.0.2.66" drop'
Rate limit:
sudo firewall-cmd --permanent --add-rich-rule='rule service name="ssh" accept limit value="10/m"'
List them: sudo firewall-cmd --list-rich-rules.
IP sets for large lists
sudo firewall-cmd --permanent --new-ipset=blocklist --type=hash:net
sudo firewall-cmd --permanent --ipset=blocklist --add-entry=203.0.113.0/24
sudo firewall-cmd --permanent --zone=drop --add-source=ipset:blocklist
sudo firewall-cmd --reload
Thousands of entries in an IP set are far more efficient than thousands of rich rules.
Port forwarding and masquerading
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --permanent --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=10.0.0.20
sudo firewall-cmd --reload
Masquerading is also what a VPN gateway needs to route client traffic to the internet.
Panic mode
sudo firewall-cmd --panic-on # drop ALL traffic — including your SSH session
sudo firewall-cmd --panic-off
Only useful from the console during an active incident.
Logging denied packets
sudo firewall-cmd --set-log-denied=unicast
journalctl -k | grep -i "REJECT\|DROP"
firewalld and Docker
Docker creates its own docker zone and rules. Published container ports remain reachable regardless of your public zone settings — bind internal services to 127.0.0.1. See Docker networking.
Quick reference
| Task | Command |
|---|---|
| Show config | firewall-cmd --list-all |
| Allow service | --permanent --add-service=https |
| Allow port | --permanent --add-port=8080/tcp |
| Allow port from IP | --permanent --add-rich-rule='rule family="ipv4" source address="IP" port port="N" protocol="tcp" accept' |
| Apply permanent rules | --reload |
| Save runtime rules | --runtime-to-permanent |
| Trust a subnet | --permanent --zone=trusted --add-source=CIDR |
On Ubuntu and Debian, the equivalent tool is UFW. For the full concepts underneath, see nftables.