Skip to content

🛡️ 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 ​

ZoneDefault BehaviorUse Case
dropDrop all inboundHighest security level
blockReject all inbound (returns ICMP reject)Similar to drop, but notifies the sender
publicDefault zone, only allows selected servicesPublic-facing servers
externalEnables masquerading (MASQUERADE)Routers/gateways
workAllows common office servicesOffice networks
homeTrusts most inboundHome networks
trustedAllows all inboundFully trusted networks

Basic Management ​

bash
# 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-zones

Service and Port Management ​

bash
# 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-service only applies to the current session (lost after reboot). Adding --permanent makes it persist. After adding --permanent, you need --reload to take effect.

Rich Rules ​

Rich Rules are firewalld's advanced syntax that enable more granular control.

bash
# 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 --reload

Direct Rules ​

bash
# 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 ​

bash
# 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