firewalld Linux: Complete Dynamic Firewall Management Guide

firewalld is a powerful, dynamic firewall management tool for Linux systems that provides a flexible and user-friendly interface for managing network security. Unlike traditional static firewalls, firewalld allows you to make real-time changes without disrupting existing connections, making it an essential tool for modern system administrators.

Table of Contents

What is firewalld?

firewalld is a frontend controller for iptables that implements network security zones and supports both IPv4 and IPv6 protocols. It was developed by Red Hat and is the default firewall solution for RHEL, CentOS, Fedora, and many other Linux distributions. The key advantage of firewalld is its ability to manage firewall rules dynamically without requiring a complete restart of the firewall service.

Key Features of firewalld

  • Dynamic rule management: Add, remove, or modify rules without service interruption
  • Zone-based configuration: Organize network interfaces into security zones
  • Rich rule support: Create complex firewall rules with advanced conditions
  • Service-based management: Predefined service configurations for common applications
  • Direct rule support: Direct iptables rule manipulation when needed
  • D-Bus integration: API access for other applications and services

Installing firewalld

Most modern Linux distributions come with firewalld pre-installed. However, if you need to install it manually, use the following commands:

Red Hat/CentOS/Fedora:

sudo dnf install firewalld
# or for older versions
sudo yum install firewalld

Ubuntu/Debian:

sudo apt update
sudo apt install firewalld

Starting and Enabling firewalld

sudo systemctl start firewalld
sudo systemctl enable firewalld
sudo systemctl status firewalld

Expected output:

● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2025-08-26 15:30:12 IST; 2min 15s ago
     Docs: man:firewalld(1)
 Main PID: 1234 (firewalld)
    Tasks: 2 (limit: 4915)
   Memory: 25.6M
   CGroup: /system.slice/firewalld.service
           └─1234 /usr/bin/python3 -Es /usr/sbin/firewalld --nofork --nopid

Understanding firewalld Zones

Zones are the cornerstone of firewalld’s security model. Each zone represents a different level of trust for network connections and defines which services and ports are accessible.

Default Zones Explained

Zone Trust Level Description
drop Lowest All incoming packets are dropped without notification
block Very Low Incoming connections are rejected with icmp-host-prohibited message
public Low For use in public areas with untrusted networks
external Low For external networks with masquerading enabled
dmz Medium For computers in DMZ with limited access to internal network
work Medium For work environments with mostly trusted computers
home High For home networks where you trust most computers
internal High For internal networks with trusted systems
trusted Highest All network connections are accepted

Managing Zones

Viewing Available Zones

sudo firewall-cmd --get-zones

Output:

block dmz drop external home internal public trusted work

Checking Active Zones

sudo firewall-cmd --get-active-zones

Output:

public
  interfaces: eth0 wlan0

Getting Default Zone

sudo firewall-cmd --get-default-zone

Output:

public

Setting Default Zone

sudo firewall-cmd --set-default-zone=home

Basic firewalld Commands

Checking Firewall Status

sudo firewall-cmd --state

Output:

running

Listing All Configurations

sudo firewall-cmd --list-all

Output:

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 8080/tcp
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:

Listing Configuration for Specific Zone

sudo firewall-cmd --zone=home --list-all

Managing Services

firewalld uses predefined service configurations that group related ports and protocols. This approach simplifies firewall management by allowing you to enable entire services rather than individual ports.

Viewing Available Services

sudo firewall-cmd --get-services

Output (truncated):

RH-Satellite-6 amanda-client amanda-k5-client amqp amqps apcupsd audit bacula bacula-client bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine cockpit condor-collector ctdb dhcp dhcpv6 dhcpv6-client dns docker-registry docker-swarm dropbox-lansync elasticsearch freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp galera high-availability http https imap imaps ipp ipp-client ipsec irc ircs iscsi-target jenkins kadmin kerberos kibana klogin kpasswd kprop kshell ldap ldaps libvirt libvirt-tls managesieve matrix mdns minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql murmur mysql nfs nfs3 nmea-0183 nrpe ntp nut openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster quassel radius redis rpc-bind rsh rsyncd rtsp salt-master samba samba-client sane sip sips slp smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh steam-streaming svdrp svn syncthing syncthing-gui telnet tftp tftp-client tinc tor-socks transmission-client upnp-client vdsm vnc-server wbem-http wbem-https wsman wsmans xdmcp xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server

Adding Services

# Add HTTP service temporarily
sudo firewall-cmd --add-service=http

# Add HTTP service permanently
sudo firewall-cmd --add-service=http --permanent

# Add multiple services at once
sudo firewall-cmd --add-service={http,https,ssh} --permanent

Removing Services

# Remove HTTP service temporarily
sudo firewall-cmd --remove-service=http

# Remove HTTP service permanently
sudo firewall-cmd --remove-service=http --permanent

Checking if Service is Enabled

sudo firewall-cmd --query-service=ssh

Output:

yes

Port Management

While services provide convenient groupings, you may need to open specific ports for custom applications or services not covered by predefined service definitions.

Adding Ports

# Add single port
sudo firewall-cmd --add-port=8080/tcp --permanent

# Add port range
sudo firewall-cmd --add-port=5000-5010/tcp --permanent

# Add UDP port
sudo firewall-cmd --add-port=53/udp --permanent

Removing Ports

sudo firewall-cmd --remove-port=8080/tcp --permanent

Listing Open Ports

sudo firewall-cmd --list-ports

Output:

8080/tcp 5000-5010/tcp

Querying Port Status

sudo firewall-cmd --query-port=8080/tcp

Output:

yes

Rich Rules: Advanced Firewall Configuration

Rich rules provide granular control over firewall behavior, allowing you to create complex rules with specific conditions, actions, and logging capabilities.

Rich Rule Syntax

rule [family="ipv4|ipv6"] [source address="address[/mask]" [invert="True"]] [destination address="address[/mask]" [invert="True"]] [service name="service name"] [port port="port value" protocol="tcp|udp"] [protocol value="protocol value"] [icmp-block name="icmptype name"] [masquerade] [forward-port port="port value" protocol="tcp|udp" to-port="port value" to-addr="address"] [log [prefix="prefix text"] [level="emerg|alert|crit|error|warning|notice|info|debug"]] [audit] [accept|reject [type="reject type"]|drop]

Rich Rule Examples

Allow SSH from Specific IP

sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept' --permanent

Block Specific IP Address

sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.50" drop' --permanent

Allow HTTP with Logging

sudo firewall-cmd --add-rich-rule='rule service name="http" log prefix="HTTP-ACCESS: " level="info" accept' --permanent

Rate Limiting SSH Connections

sudo firewall-cmd --add-rich-rule='rule service name="ssh" accept limit value="3/m"' --permanent

Port Forwarding

sudo firewall-cmd --add-rich-rule='rule family="ipv4" forward-port port="80" protocol="tcp" to-port="8080"' --permanent

Managing Rich Rules

Listing Rich Rules

sudo firewall-cmd --list-rich-rules

Removing Rich Rules

sudo firewall-cmd --remove-rich-rule='rule family="ipv4" source address="192.168.1.50" drop' --permanent

Network Address Translation (NAT) and Masquerading

firewalld supports NAT functionality, allowing you to share internet connections and implement routing between different network segments.

Enabling Masquerading

# Enable masquerading temporarily
sudo firewall-cmd --add-masquerade

# Enable masquerading permanently
sudo firewall-cmd --add-masquerade --permanent

# Check masquerading status
sudo firewall-cmd --query-masquerade

Port Forwarding

# Forward external port 80 to internal port 8080
sudo firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080 --permanent

# Forward to different host
sudo firewall-cmd --add-forward-port=port=80:proto=tcp:toaddr=192.168.1.100:toport=80 --permanent

Source and Destination Management

Control traffic based on source and destination addresses to implement network segmentation and access control.

Adding Sources to Zones

# Add IP address to trusted zone
sudo firewall-cmd --zone=trusted --add-source=192.168.1.0/24 --permanent

# Add specific IP to public zone
sudo firewall-cmd --zone=public --add-source=203.0.113.10 --permanent

Listing Sources

sudo firewall-cmd --zone=trusted --list-sources

Output:

192.168.1.0/24

Removing Sources

sudo firewall-cmd --zone=trusted --remove-source=192.168.1.0/24 --permanent

ICMP Management

Control ICMP (Internet Control Message Protocol) traffic for network diagnostics and security.

Viewing Available ICMP Types

sudo firewall-cmd --get-icmptypes

Output:

address-unreachable bad-header beyond-scope communication-prohibited destination-unreachable echo-reply echo-request failed-policy fragmentation-needed host-precedence-violation host-prohibited host-redirect host-unknown host-unreachable ip-header-bad neighbour-advertisement neighbour-solicitation network-prohibited network-redirect network-unknown network-unreachable no-route packet-too-big parameter-problem port-unreachable precedence-cutoff protocol-unreachable redirect reject-route router-advertisement router-solicitation source-quench source-route-failed time-exceeded timestamp-reply timestamp-request tos-host-redirect tos-host-unreachable tos-network-redirect tos-network-unreachable ttl-zero-during-reassembly ttl-zero-during-transit unknown-header-type unknown-option

Blocking ICMP Types

# Block ping requests
sudo firewall-cmd --add-icmp-block=echo-request --permanent

# Block destination unreachable messages
sudo firewall-cmd --add-icmp-block=destination-unreachable --permanent

Listing ICMP Blocks

sudo firewall-cmd --list-icmp-blocks

Runtime vs Permanent Configuration

firewalld maintains two separate configurations: runtime (temporary) and permanent. Understanding this distinction is crucial for effective firewall management.

Configuration Types

  • Runtime Configuration: Active rules that apply immediately but are lost on reboot
  • Permanent Configuration: Rules saved to disk that persist across reboots

Working with Configurations

Applying Permanent Rules to Runtime

sudo firewall-cmd --reload

Making Runtime Rules Permanent

sudo firewall-cmd --runtime-to-permanent

Checking Permanent Configuration

sudo firewall-cmd --list-all --permanent

Creating Custom Services

For applications with unique port requirements, you can create custom service definitions.

Creating a Custom Service

# Create service definition file
sudo firewall-cmd --new-service=myapp --permanent

# Add description
sudo firewall-cmd --service=myapp --set-description="My Custom Application" --permanent

# Add short description
sudo firewall-cmd --service=myapp --set-short="MyApp" --permanent

# Add ports
sudo firewall-cmd --service=myapp --add-port=8080/tcp --permanent
sudo firewall-cmd --service=myapp --add-port=8443/tcp --permanent

# Reload to apply changes
sudo firewall-cmd --reload

Using Custom Service

sudo firewall-cmd --add-service=myapp --permanent

Editing Service Files Manually

Service files are stored in /usr/lib/firewalld/services/ (system) and /etc/firewalld/services/ (custom).

# Example custom service file: /etc/firewalld/services/myapp.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>MyApp</short>
  <description>My Custom Application Service</description>
  <port protocol="tcp" port="8080"/>
  <port protocol="tcp" port="8443"/>
</service>

Logging and Monitoring

Effective logging is essential for security monitoring and troubleshooting firewall issues.

Enabling Logging

# Enable logging for denied packets
sudo firewall-cmd --set-log-denied=all --permanent

# Other options: off, all, unicast, broadcast, multicast
sudo firewall-cmd --reload

Viewing Firewall Logs

# View recent firewall logs
sudo journalctl -u firewalld -f

# View kernel messages (iptables logs)
sudo dmesg | grep -i firewall

# Check system logs
sudo tail -f /var/log/messages | grep kernel

Rich Rule Logging Example

sudo firewall-cmd --add-rich-rule='rule service name="ssh" log prefix="SSH-ATTEMPT: " level="warning" accept' --permanent

Troubleshooting Common Issues

Diagnosing Connectivity Problems

Testing Port Connectivity

# Test from client machine
telnet your-server-ip 80
nc -zv your-server-ip 80

# Test locally on server
ss -tlnp | grep :80
netstat -tlnp | grep :80

Checking Active Rules

# View actual iptables rules
sudo iptables -L -n
sudo iptables -t nat -L -n

# Check firewalld rules
sudo firewall-cmd --direct --get-all-rules

Common Configuration Mistakes

  • Forgetting –permanent flag: Rules lost after reboot
  • Not reloading configuration: Permanent rules not applied
  • Wrong zone assignment: Interface in different zone than expected
  • Service vs port confusion: Opening individual ports when service exists

Backup and Restore

Backing Up Configuration

# Backup entire firewalld configuration
sudo tar -czf firewalld-backup-$(date +%Y%m%d).tar.gz /etc/firewalld/

# Backup specific zone
sudo cp /etc/firewalld/zones/public.xml /backup/public.xml.backup

Restoring Configuration

# Restore from backup
sudo tar -xzf firewalld-backup-20250826.tar.gz -C /

# Reload configuration
sudo firewall-cmd --reload

Advanced Configuration Techniques

Direct Rules

For complex scenarios not covered by firewalld’s high-level interface, you can use direct rules to interact with iptables directly.

# Add direct rule
sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 9999 -j ACCEPT --permanent

# List direct rules
sudo firewall-cmd --direct --get-all-rules

# Remove direct rule
sudo firewall-cmd --direct --remove-rule ipv4 filter INPUT 0 -p tcp --dport 9999 -j ACCEPT --permanent

Interface Assignment

# Assign interface to specific zone
sudo firewall-cmd --zone=dmz --change-interface=eth1 --permanent

# Remove interface from zone
sudo firewall-cmd --zone=dmz --remove-interface=eth1 --permanent

# List interfaces in zone
sudo firewall-cmd --zone=dmz --list-interfaces

Panic Mode

# Enable panic mode (blocks all network traffic)
sudo firewall-cmd --panic-on

# Disable panic mode
sudo firewall-cmd --panic-off

# Check panic mode status
sudo firewall-cmd --query-panic

Best Practices for firewalld Management

Security Best Practices

  • Principle of least privilege: Only open necessary ports and services
  • Use appropriate zones: Match zone trust levels to network environments
  • Regular audits: Periodically review and clean up firewall rules
  • Source-based restrictions: Limit access to trusted IP ranges when possible
  • Enable logging: Monitor access attempts and blocked traffic

Management Best Practices

  • Document changes: Maintain records of firewall modifications
  • Test thoroughly: Verify rules work as expected before making permanent
  • Use version control: Track configuration changes over time
  • Automate deployments: Use configuration management tools
  • Regular backups: Maintain current configuration backups

Performance Considerations

  • Rule ordering: Place frequently matched rules earlier in the chain
  • Avoid overlapping rules: Remove redundant or conflicting rules
  • Monitor resource usage: Check CPU and memory impact of complex rules
  • Use services over individual ports: Leverage predefined service groups

Integration with Configuration Management

Ansible Example

---
- name: Configure firewalld
  hosts: webservers
  become: yes
  tasks:
    - name: Start and enable firewalld
      systemd:
        name: firewalld
        state: started
        enabled: yes
    
    - name: Allow HTTP service
      firewalld:
        service: http
        permanent: yes
        state: enabled
        immediate: yes
    
    - name: Allow HTTPS service
      firewalld:
        service: https
        permanent: yes
        state: enabled
        immediate: yes
    
    - name: Open custom port
      firewalld:
        port: 8080/tcp
        permanent: yes
        state: enabled
        immediate: yes

Conclusion

firewalld provides a robust, flexible framework for managing Linux firewall configurations. Its zone-based approach, dynamic rule management, and rich feature set make it an excellent choice for both simple and complex network security scenarios. By mastering the concepts and commands covered in this guide, you’ll be well-equipped to implement effective firewall policies that protect your systems while maintaining the flexibility needed for modern applications.

Remember to always test firewall changes in a controlled environment before applying them to production systems, maintain regular backups of your configurations, and keep your firewall rules updated as your infrastructure evolves. With proper implementation and maintenance, firewalld can serve as a cornerstone of your Linux security strategy.