firewalld
firewalld is the standard firewall management daemon for RHEL, AlmaLinux, Rocky Linux, Fedora, and related distributions. It organizes rules using the concepts of "zones" and "services", and lets you dynamically open, close, and persist ports with the firewall-cmd command. Because changes take effect immediately without a restart, you can safely modify firewall settings even while a production server is running.
Syntax
# -----------------------------------------------
# Zone-related
# -----------------------------------------------
# firewall-cmd --get-default-zone
# Displays the default zone.
# Example: firewall-cmd --get-default-zone
# firewall-cmd --get-zones
# Lists all available zones.
# firewall-cmd --get-active-zones
# Displays currently active zones and their associated interfaces.
# firewall-cmd --set-default-zone={zone}
# Changes the default zone (takes effect immediately and persists).
# Example: firewall-cmd --set-default-zone=public
# -----------------------------------------------
# Adding and removing services
# -----------------------------------------------
# firewall-cmd --zone={zone} --add-service={service}
# Adds a service to the specified zone (temporary; lost on restart).
# Example: firewall-cmd --zone=public --add-service=http
# firewall-cmd --zone={zone} --remove-service={service}
# Removes a service from the specified zone (temporary).
# Example: firewall-cmd --zone=public --remove-service=ftp
# firewall-cmd --zone={zone} --add-service={service} --permanent
# Adds a service permanently (survives reboots).
# --permanent only writes to the config file; --reload is required to apply it at runtime.
# Example: firewall-cmd --zone=public --add-service=https --permanent
# -----------------------------------------------
# Adding and removing ports
# -----------------------------------------------
# firewall-cmd --zone={zone} --add-port={port}/{protocol}
# Adds a port to the specified zone (temporary).
# Example: firewall-cmd --zone=public --add-port=8080/tcp
# firewall-cmd --zone={zone} --remove-port={port}/{protocol}
# Removes a port from the specified zone (temporary).
# Example: firewall-cmd --zone=public --remove-port=8080/tcp
# firewall-cmd --zone={zone} --add-port={port}/{protocol} --permanent
# Adds a port permanently.
# Example: firewall-cmd --zone=public --add-port=3306/tcp --permanent
# -----------------------------------------------
# Restricting by source IP
# -----------------------------------------------
# firewall-cmd --zone={zone} --add-source={IP/CIDR}
# Assigns a specific IP address or network to a zone (temporary).
# The rules of that zone are then applied to matching traffic.
# Example: firewall-cmd --zone=trusted --add-source=192.168.1.0/24
# firewall-cmd --zone={zone} --add-source={IP/CIDR} --permanent
# Assigns a source IP to a zone permanently.
# Example: firewall-cmd --zone=trusted --add-source=10.0.0.5/32 --permanent
# -----------------------------------------------
# Checking and persisting configuration
# -----------------------------------------------
# firewall-cmd --list-all
# Displays all current settings for the default zone.
# firewall-cmd --zone={zone} --list-all
# Displays all settings for the specified zone.
# firewall-cmd --reload
# Applies settings written with --permanent to the runtime configuration.
# Existing connections are not dropped.
# firewall-cmd --runtime-to-permanent
# Saves the current runtime configuration to disk (the reverse direction).
Option reference
| Option | Description |
|---|---|
--get-default-zone | Displays the default zone. Rules of this zone are applied when no other zone matches. |
--get-zones | Lists all zone names defined on the system. |
--get-active-zones | Displays currently active zones and the network interfaces associated with each. |
--set-default-zone={zone} | Changes the default zone. The change persists even without --permanent. |
--list-all | Displays all settings for a zone, including services, ports, and sources. |
--add-service={service} | Adds a predefined service (such as http, https, or ssh) to a zone. The change is temporary. |
--remove-service={service} | Removes a service from a zone. The change is temporary. |
--add-port={port}/{protocol} | Adds a port directly by number to a zone. Use this when no service definition exists for the port. |
--remove-port={port}/{protocol} | Removes a port from a zone. The change is temporary. |
--add-source={IP/CIDR} | Assigns a specific IP address or network range to a zone. Used to route traffic by source IP. |
--remove-source={IP/CIDR} | Removes a source IP assignment from a zone. |
--permanent | Writes the change to the configuration file for persistence. The change does not take effect at runtime until --reload is run. |
--reload | Applies settings written with --permanent to the runtime configuration. Existing connections are preserved. |
--runtime-to-permanent | Saves all current runtime settings to disk at once. Useful when you want to persist temporary changes after the fact. |
--query-service={service} | Checks whether the specified service has been added to a zone. Returns yes or no. |
--query-port={port}/{protocol} | Checks whether the specified port has been added to a zone. |
Examples
Open HTTP and HTTPS permanently in the public zone
# ----------------------------------------------- # Expose a web server to the outside world # ----------------------------------------------- # Check the current settings of the public zone firewall-cmd --zone=public --list-all # Add HTTP (port 80) and HTTPS (port 443) permanently # --permanent only writes to the config file sudo firewall-cmd --zone=public --add-service=http --permanent sudo firewall-cmd --zone=public --add-service=https --permanent # Apply the permanently saved settings to the runtime configuration sudo firewall-cmd --reload # Confirm the settings have taken effect firewall-cmd --zone=public --list-services
Run the following command:
$ firewall-cmd --zone=public --list-all public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: cockpit dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: $ sudo firewall-cmd --zone=public --add-service=http --permanent success $ sudo firewall-cmd --zone=public --add-service=https --permanent success $ sudo firewall-cmd --reload success $ firewall-cmd --zone=public --list-services cockpit dhcpv6-client http https ssh
Allow MySQL (port 3306) only from a specific IP address
# ----------------------------------------------- # Allow MySQL connections only from the app server at 192.168.10.20 # ----------------------------------------------- # Assign the app server (192.168.10.20) to the trusted zone permanently. # The trusted zone accepts all traffic from assigned sources. sudo firewall-cmd --zone=trusted --add-source=192.168.10.20/32 --permanent # No MySQL port is opened in the public zone. # Simply assigning the IP to the trusted zone is enough — # all connections from 192.168.10.20 will be accepted. # Apply the settings sudo firewall-cmd --reload # Verify the trusted zone configuration firewall-cmd --zone=trusted --list-all
Run the following command:
$ sudo firewall-cmd --zone=trusted --add-source=192.168.10.20/32 --permanent success $ sudo firewall-cmd --reload success $ firewall-cmd --zone=trusted --list-all trusted (active) target: ACCEPT icmp-block-inversion: no interfaces: sources: 192.168.10.20/32 services: ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
Open a custom port temporarily, verify it, then make it permanent
# ----------------------------------------------- # Expose a development app on port 8080 in stages # ----------------------------------------------- # First, add 8080/tcp temporarily (lost on restart). # It's safe to test this way since the change can be rolled back at any time. sudo firewall-cmd --zone=public --add-port=8080/tcp # Confirm the port was opened firewall-cmd --zone=public --list-ports # After confirming the app works correctly, make the change permanent sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent sudo firewall-cmd --reload # Confirm the port is now persisted firewall-cmd --zone=public --query-port=8080/tcp
Run the following command:
$ sudo firewall-cmd --zone=public --add-port=8080/tcp success $ firewall-cmd --zone=public --list-ports 8080/tcp $ sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent success $ sudo firewall-cmd --reload success $ firewall-cmd --zone=public --query-port=8080/tcp yes
Remove a service to close a port
# ----------------------------------------------- # Stop and close the FTP service # ----------------------------------------------- # Check whether the FTP service is currently open firewall-cmd --zone=public --query-service=ftp # Remove FTP permanently sudo firewall-cmd --zone=public --remove-service=ftp --permanent # Apply the change to the runtime configuration immediately sudo firewall-cmd --reload # Confirm it was removed (a "no" response means success) firewall-cmd --zone=public --query-service=ftp
Run the following command:
$ firewall-cmd --zone=public --query-service=ftp yes $ sudo firewall-cmd --zone=public --remove-service=ftp --permanent success $ sudo firewall-cmd --reload success $ firewall-cmd --zone=public --query-service=ftp no
Overview
firewalld is a dynamic firewall management daemon that runs on top of nftables (or iptables) as its backend. A "zone" is a named ruleset representing a trust level — for example, public (external networks), trusted (fully trusted), and internal (internal networks). A "service" is a group of ports defined in XML files under /usr/lib/firewalld/services/; for instance, http maps to 80/tcp and mysql maps to 3306/tcp. Changes made with the --permanent flag are written to the configuration files and take effect at runtime after --reload is run. Changes made without --permanent apply to the runtime immediately but are lost when firewalld or the OS is restarted. For low-level rule management, see the iptables page. For the lightweight firewall commonly used on Debian and Ubuntu systems, see the ufw page.
If you find any errors or copyright issues, please contact us.