🛡️ firewalld (CentOS/RHEL Firewall)
What is firewalld?
firewalld introduces the concept of "Zones" — imagine your server has different "faces" depending on the setting: at home (trusted zone) everything is allowed, at a coffee shop (public zone) only essential ports are open, at the office (work zone) work-related services are available.
Zones
| Zone | Default Behavior | Use Case |
|---|---|---|
| drop | Drop all inbound | Highest security level |
| block | Reject all inbound (returns ICMP reject) | Similar to drop, but notifies the sender |
| public | Default zone, only allows selected services | Public-facing servers |
| external | Enables masquerading (MASQUERADE) | Routers/gateways |
| work | Allows common office services | Office networks |
| home | Trusts most inbound | Home networks |
| trusted | Allows all inbound | Fully trusted networks |
Basic Management
# Start and enable on boot
sudo systemctl start firewalld
sudo systemctl enable firewalld
# Check status
sudo firewall-cmd --state
running
# View default zone
sudo firewall-cmd --get-default-zone
public
# View all zones
sudo firewall-cmd --get-zones
block dmz drop external home internal public trusted work
# View current zone rules
sudo firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: dhcpv6-client ssh
ports:
protocols:
masquerade: no
forward-ports:
rich rules:
# View rules for all zones
sudo firewall-cmd --list-all-zonesService and Port Management
# View available services list
sudo firewall-cmd --get-services
RH-Satellite-6 amanda-client amanda-k5-client bacula
bacula-client bitcoin bitcoin-rpc ... ssh dhcpv6-client
http https mysql postgresql redis ...
# Add service (runtime, not persistent)
sudo firewall-cmd --add-service=http
sudo firewall-cmd --add-service=https
# Add port
sudo firewall-cmd --add-port=8080/tcp
sudo firewall-cmd --add-port=3000-4000/tcp # Port range
# Add permanently (persists after reboot)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=8080/tcp
# Reload to apply permanent rules
sudo firewall-cmd --reload
# Remove service/port
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --permanent --remove-port=8080/tcp
# View currently active rules (runtime)
sudo firewall-cmd --list-services
dhcpv6-client http https ssh
sudo firewall-cmd --list-ports
8080/tcp⚠️ Warning: ⚠️ Runtime vs Permanent:
--add-serviceonly applies to the current session (lost after reboot). Adding--permanentmakes it persist. After adding--permanent, you need--reloadto take effect.
Rich Rules
Rich Rules are firewalld's advanced syntax that enable more granular control.
# Allow only a specific IP to access SSH
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="192.168.1.100"
port protocol="tcp" port="22"
accept'
# Rate limiting (max 10 new SSH connections per minute)
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
port protocol="tcp" port="22"
accept
limit value="10/m"'
# Deny a specific IP
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="10.0.0.50"
drop'
# Allow a specific subnet to access MySQL
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="192.168.1.0/24"
port protocol="tcp" port="3306"
accept'
# View all rich rules
sudo firewall-cmd --list-rich-rules
# Delete a rich rule
sudo firewall-cmd --permanent --remove-rich-rule='
rule family="ipv4"
source address="10.0.0.50"
drop'
sudo firewall-cmd --reloadDirect Rules
# Directly insert iptables rules (firewalld's backdoor)
sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 \
-p tcp --dport 9090 -j ACCEPT
# View direct rules
sudo firewall-cmd --direct --get-all-rules
# Make permanent
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 \
-p tcp --dport 9090 -j ACCEPT
sudo firewall-cmd --reload📝 Note: 📝 When to use Direct Rules? When firewalld's rich rules can't meet your needs (e.g., complex iptables rules), you can use direct rules to operate the underlying iptables directly.
Zone Binding
# Bind a network interface to a zone
sudo firewall-cmd --permanent --zone=public --change-interface=eth0
# Bind an IP to a zone
sudo firewall-cmd --permanent --zone=trusted --add-source=192.168.1.100
# View which zone each interface is in
sudo firewall-cmd --get-active-zones
public
interfaces: eth0 eth1