Skip to content

Firewall (firewalld)

firewalld is the default dynamic firewall management tool on CentOS / AlmaLinux / Rocky Linux. It provides zone-based firewall management and supports modifying rules at runtime without restarting the service.

Zones are the core concept of firewalld. Each zone defines a set of trust levels and corresponding firewall rules, and network interfaces are assigned to different zones.

Commonly used built-in zones:

ZoneDescription
publicDefault zone. Suitable for public network environments; only selected inbound connections are allowed
trustedAllows all inbound traffic
homeSuitable for home networks; trusts other devices on the network
workSuitable for work networks
internalSuitable for internal networks
dmzSuitable for servers in a DMZ; only specific inbound connections are allowed
externalSuitable for external networks with NAT masquerading enabled
blockRejects all inbound connections and returns an ICMP rejection message
dropDrops all inbound packets without returning any response
View firewalld running status
sudo systemctl status firewalld
Start and enable at boot
sudo systemctl enable --now firewalld
Check if firewalld is running
sudo firewall-cmd --state
View the default zone
sudo firewall-cmd --get-default-zone
View all active zones and their bound interfaces
sudo firewall-cmd --get-active-zones
View the complete rules for the current zone
sudo firewall-cmd --list-all
View rules for a specific zone
sudo firewall-cmd --zone=public --list-all
List all available zones
sudo firewall-cmd --get-zones
List all predefined services
sudo firewall-cmd --get-services
View the detailed definition of a service (e.g., http)
sudo firewall-cmd --info-service=http

firewalld rules come in two types:

  • Runtime rules: Take effect immediately but are lost after restarting firewalld or the system
  • Permanent rules: Written to configuration files and persist after a restart, but do not take effect immediately
Add a permanent rule and apply it immediately
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload

You can also add both runtime and permanent rules simultaneously (no reload needed):

Apply both runtime and permanent rules at once
sudo firewall-cmd --add-service=http
sudo firewall-cmd --permanent --add-service=http
Allow HTTP service (permanent)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
Allow both HTTP and HTTPS
sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --reload
Remove HTTP service allowance (permanent)
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload
List services allowed in the current zone
sudo firewall-cmd --list-services
Allow TCP port 8080
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
Allow a UDP port
sudo firewall-cmd --permanent --add-port=53/udp
sudo firewall-cmd --reload
Allow a port range
sudo firewall-cmd --permanent --add-port=3000-3100/tcp
sudo firewall-cmd --reload
Remove a port allowance
sudo firewall-cmd --permanent --remove-port=8080/tcp
sudo firewall-cmd --reload
List currently allowed ports
sudo firewall-cmd --list-ports
Change the default zone to internal
sudo firewall-cmd --set-default-zone=internal
Assign ens33 to the internal zone
sudo firewall-cmd --permanent --zone=internal --change-interface=ens33
sudo firewall-cmd --reload
Allow MySQL service in the internal zone
sudo firewall-cmd --permanent --zone=internal --add-service=mysql
sudo firewall-cmd --reload

Rich rules provide more granular firewall control, allowing you to flexibly set rules based on source addresses, destination addresses, ports, and other conditions.

The basic structure of a rich rule:

rule family="ipv4" source address="source_address" service name="service_name" accept/reject/drop

Allowing a Specific IP to Access a Service

Section titled “Allowing a Specific IP to Access a Service”
Allow only the 192.168.1.0/24 subnet to access SSH
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept'
sudo firewall-cmd --reload
Drop all connections from 10.0.0.100
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.100" drop'
sudo firewall-cmd --reload

Allowing a Specific IP to Access a Given Port

Section titled “Allowing a Specific IP to Access a Given Port”
Allow 172.16.0.0/16 to access TCP port 3306
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="172.16.0.0/16" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --reload
Log and drop connections from a specific IP
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.200" log prefix="BLOCKED: " level="warning" drop'
sudo firewall-cmd --reload
List all current rich rules
sudo firewall-cmd --list-rich-rules
Delete a specific rich rule
sudo firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="10.0.0.100" drop'
sudo firewall-cmd --reload
Typical web server configuration: allow HTTP, HTTPS, and SSH
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload

Database Server (restricting access sources)

Section titled “Database Server (restricting access sources)”
Allow only the application server subnet to access MySQL
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" service name="mysql" accept'
sudo firewall-cmd --reload
Node.js application running on port 3000
sudo firewall-cmd --permanent --add-port=3000/tcp
sudo firewall-cmd --reload
Forward external port 80 to internal port 8080
sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
sudo firewall-cmd --reload
Forward traffic to another host
sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=80:toaddr=192.168.1.50
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --reload
Enable IP masquerading
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --reload
View all rules across all zones
sudo firewall-cmd --list-all-zones

Viewing Underlying nftables/iptables Rules

Section titled “Viewing Underlying nftables/iptables Rules”
View the nftables rules generated by firewalld
sudo nft list ruleset

EL 8 and earlier versions use the iptables backend:

View iptables rules (EL 8)
sudo iptables -L -n -v
View firewalld-related logs
sudo journalctl -u firewalld --no-pager -n 30
Enable panic mode (block all traffic)
sudo firewall-cmd --panic-on
Disable panic mode
sudo firewall-cmd --panic-off
Check whether panic mode is active
sudo firewall-cmd --query-panic

Backing Up the Current Firewall Configuration

Section titled “Backing Up the Current Firewall Configuration”
Back up the firewalld configuration directory
sudo cp -r /etc/firewalld /etc/firewalld.backup.$(date +%Y%m%d)
Restore backed-up configuration
sudo cp -r /etc/firewalld.backup.20260324/* /etc/firewalld/
sudo firewall-cmd --reload