firewall-cmd — quick reference
Status and reload
Check whether firewalld is running and apply configuration changes.
| When to use | Command |
|---|---|
| Check if firewalld is active | sudo firewall-cmd --state |
| Reload runtime rules from permanent config | sudo firewall-cmd --reload |
| Full reload (drops connections; severe issues only) | sudo firewall-cmd --complete-reload |
| Copy working runtime rules into permanent config | sudo firewall-cmd --runtime-to-permanent |
| Show firewalld version | firewall-cmd --version |
Zones
Zones group rules by trust level (public, internal, trusted, drop, …).
| When to use | Command |
|---|---|
| List all zone names | sudo firewall-cmd --get-zones |
| Show zones bound to interfaces right now | sudo firewall-cmd --get-active-zones |
| Show the default zone for new interfaces | sudo firewall-cmd --get-default-zone |
| Change the default zone | sudo firewall-cmd --set-default-zone=public |
| Show full config for the default zone | sudo firewall-cmd --list-all |
| Show full config for one zone | sudo firewall-cmd --list-all --zone=public |
| Dump every zone | sudo firewall-cmd --list-all-zones |
| See which zone owns an interface | sudo firewall-cmd --get-zone-of-interface=eth0 |
| Assign an interface to a zone (runtime) | sudo firewall-cmd --zone=public --add-interface=eth0 |
| Move an interface to another zone | sudo firewall-cmd --zone=internal --change-interface=eth0 |
Services and ports
Open application traffic with predefined services or explicit port/protocol pairs.
| When to use | Command |
|---|---|
| Allow HTTP in the active zone (runtime) | sudo firewall-cmd --add-service=http |
| Allow HTTPS permanently | sudo firewall-cmd --add-service=https --permanent |
| Allow SSH permanently | sudo firewall-cmd --add-service=ssh --permanent |
| Remove a service | sudo firewall-cmd --remove-service=http --permanent |
| Open TCP port 8080 permanently | sudo firewall-cmd --add-port=8080/tcp --permanent |
| Open UDP port 53 permanently | sudo firewall-cmd --add-port=53/udp --permanent |
| Remove a port | sudo firewall-cmd --remove-port=8080/tcp --permanent |
| List allowed services | sudo firewall-cmd --list-services |
| List open ports | sudo firewall-cmd --list-ports |
After --permanent changes, run sudo firewall-cmd --reload so runtime matches disk.
Sources, forwarding, and NAT
| When to use | Command |
|---|---|
| Trust traffic from one IP in the zone | sudo firewall-cmd --add-source=192.168.1.100 --permanent |
| Trust a subnet | sudo firewall-cmd --add-source=192.168.1.0/24 --permanent |
| Enable masquerading (NAT) in a zone | sudo firewall-cmd --zone=public --add-masquerade --permanent |
| Forward local port 80 to 8080 | sudo firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080 --permanent |
| Forward port 80 to another host | sudo firewall-cmd --add-forward-port=port=80:proto=tcp:toaddr=192.168.1.10 --permanent |
| List forward-port rules | sudo firewall-cmd --list-forward-ports |
Rich rules and logging
Fine-grained allow/drop/reject by source, port, or rate limit. To verify whether inbound ICMP still works before blocking echo-request, use ping command from a client host.
| When to use | Command |
|---|---|
| Allow SSH from one IP | sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept' --permanent |
| Drop traffic from one IP | sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="203.0.113.50" drop' --permanent |
| List rich rules | sudo firewall-cmd --list-rich-rules |
| Log all denied packets | sudo firewall-cmd --set-log-denied=all |
| Block inbound ping (ICMP echo-request) | sudo firewall-cmd --add-icmp-block=echo-request --permanent |
Permanent zones and service control
firewalld runs as a systemd unit; start and enable it with the systemctl command before relying on firewall-cmd rules at boot.
| When to use | Command |
|---|---|
| Create a new permanent zone | sudo firewall-cmd --permanent --new-zone=appzone |
| Delete a permanent zone | sudo firewall-cmd --permanent --delete-zone=appzone |
| Start firewalld now | sudo systemctl start firewalld |
| Enable firewalld at boot | sudo systemctl enable firewalld |
firewall-cmd — command syntax
Synopsis from firewall-cmd(1) on firewalld.org:
firewall-cmd [OPTIONS...]Runtime changes apply immediately but are lost on reboot unless you also pass --permanent and run --reload. Permanent rules live under /etc/firewalld/ (zones, services, policies). firewalld on RHEL 8+ uses nftables as the backend; older releases used iptables.
firewall-cmd — command examples
Essential Inspect the active firewall zone
Start troubleshooting by seeing which zone is default, which interfaces are bound, and what services and ports are already open.
Run the commands:
sudo firewall-cmd --state
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-allSample output:
running
public
public
interfaces: eth0
services: cockpit dhcpv6-client ssh
ports:
protocols:
forward: no
masquerade: no
rich rules:The list-all block is for the default zone unless you pass --zone=NAME.
Essential Open SSH and a web server permanently
On a fresh server, allow remote admin and HTTP/HTTPS, then reload so rules survive reboot.
Run the commands:
sudo firewall-cmd --add-service=ssh --permanent
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reloadConfirm services are listed:
sudo firewall-cmd --list-servicesSample output:
cockpit dhcpv6-client http https sshAlways keep SSH open before tightening the default zone to something restrictive like drop.
Essential Open a custom TCP port
When an app listens on a non-standard port (8080), add an explicit port rule — predefined services will not cover it.
Run the commands:
sudo firewall-cmd --add-port=8080/tcp --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-portsSample output:
8080/tcpMatch the protocol: /udp for DNS-like traffic, /tcp for HTTP-like traffic.
Common Test a rule at runtime, then save it
Runtime rules let you test without reboot risk. When the test works, promote them to permanent config.
Run the commands:
sudo firewall-cmd --add-port=9000/tcp
sudo firewall-cmd --list-ports
sudo firewall-cmd --runtime-to-permanentSample output:
9000/tcp
successAfter --runtime-to-permanent, the open port is stored under /etc/firewalld/ and survives reboot without repeating --add-port.
Common Allow SSH only from a trusted IP
Restrict SSH to one admin workstation instead of the whole internet — use a rich rule with source address and service name.
Run the commands:
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept' --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-rich-rulesSample output:
rule family="ipv4" source address="192.168.1.100" service name="ssh" acceptRich rules stack with normal service rules; review the full effective policy with --list-all.
Common Drop traffic from a hostile address
Block a known scanner or abusive IP with a drop rich rule — silent discard with no reply.
Run the commands:
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="203.0.113.50" drop' --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-rich-rulesSample output:
rule family="ipv4" source address="203.0.113.50" dropUse reject instead of drop when you want the sender to receive an ICMP unreachable response.
Advanced Enable NAT and port forwarding
Turn a RHEL host into a simple gateway: masquerade outbound traffic and forward inbound port 80 to an internal web server.
Run the commands:
sudo firewall-cmd --zone=public --add-masquerade --permanent
sudo firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toaddr=192.168.1.50:toport=8080 --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --zone=public --query-masquerade
sudo firewall-cmd --list-forward-portsSample output:
yes
port=80:proto=tcp:toport=8080:toaddr=192.168.1.50Ensure IP forwarding is enabled in the kernel (net.ipv4.ip_forward=1) when routing between subnets.
Advanced Create a zone for application traffic
Isolate an application NIC in its own zone with a tighter service list than public.
Run the commands:
sudo firewall-cmd --permanent --new-zone=appzone
sudo firewall-cmd --reload
sudo firewall-cmd --zone=appzone --add-service=http --permanent
sudo firewall-cmd --zone=appzone --add-interface=eth1 --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --zone=appzone --list-allSample output:
appzone (active)
interfaces: eth1
services: http
ports:
protocols:
forward: no
masquerade: no
rich rules:Custom zones live as XML under /etc/firewalld/zones/.
Advanced Verify rules when a service is unreachable
When connectivity fails, confirm the interface zone, open ports, and whether firewalld is running.
Run the commands:
sudo firewall-cmd --get-zone-of-interface=eth0
sudo firewall-cmd --list-all --zone=public
sudo firewall-cmd --list-ports
sudo journalctl -u firewalld --no-pager -n 20Sample output:
public
public (active)
interfaces: eth0
services: ssh
ports: 8080/tcp
...If the service is allowed in permanent config but not runtime, run sudo firewall-cmd --reload.
firewall-cmd — when to use / when not
| Use firewalld / firewall-cmd when | Use something else when |
|---|---|
|
|
firewalld vs ufw vs iptables
| firewalld | ufw | iptables / nftables | |
|---|---|---|---|
| Default on | RHEL, Fedora, Rocky, Alma | Ubuntu, Debian | Universal (manual setup) |
| Model | Zones + services + rich rules | Simple allow/deny profiles | Raw rule chains |
| Runtime vs permanent | Built-in dual config | ufw rules persist in one layer |
Depends on save mechanism |
| Backend | nftables (RHEL 8+) | iptables/nftables via alternatives | Direct kernel rules |
firewalld is a manager — it translates zone changes into nftables/iptables rules. On RHEL 8+, inspect the backend with sudo firewall-cmd --info-zone=public.
Related commands
Host firewall and network troubleshooting nearby.
| Command | One line |
|---|---|
| firewall-cmd | firewalld CLI (this page) |
| ss | See listening sockets and ports |
| nmcli | Manage interfaces that firewalld zones bind to |
| tcpdump | Capture packets when rules behave unexpectedly |
Browse the full index in our Linux commands reference.
firewall-cmd — interview corner
What is firewalld and how does it differ from iptables?
firewalld is a dynamic firewall manager on RHEL-family Linux. You define zones (public, internal, trusted, …), services (ssh, http), ports, and rich rules. firewalld pushes those definitions into nftables (RHEL 8+) or iptables without a full service restart for most changes.
iptables/nftables are the low-level rule engines. firewalld sits above them so admins think in trust zones instead of chain syntax.
Check state:
sudo firewall-cmd --stateA strong answer is:
"firewalld is the high-level host firewall on RHEL and Fedora — zones, services, and rich rules — backed by nftables. iptables is the low-level rule engine; firewalld translates zone policy into kernel rules."
What is the difference between runtime and permanent firewall rules?
firewalld keeps two configurations:
| Layer | Lifetime | Storage |
|---|---|---|
| Runtime | Until reboot or --reload |
Active in memory |
| Permanent | Survives reboot | Files under /etc/firewalld/ |
Example workflow:
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --reloadUse runtime-only for quick tests; add --permanent and --reload (or --runtime-to-permanent) for production.
A strong answer is:
"Runtime rules apply immediately but disappear on reboot. Permanent rules live in /etc/firewalld and need --reload to hit runtime. I test with runtime, then --permanent plus reload for persistence."
What is a firewalld zone?
A zone is a named rule set describing how much you trust traffic arriving on attached interfaces. Examples:
| Zone | Typical use |
|---|---|
| public | Default untrusted LAN or internet-facing NIC |
| internal | Trusted office LAN |
| trusted | Accept nearly everything |
| drop | Silently discard inbound |
List bindings:
sudo firewall-cmd --get-active-zonesEach interface maps to one zone; all traffic on that NIC inherits that zone's services and rich rules.
A strong answer is:
"A zone is a trust profile — public, internal, trusted, drop. Interfaces bind to one zone; their traffic gets that zone's allowed services and rules. I check bindings with get-active-zones."
When do you use firewalld rich rules?
Rich rules express conditions plain --add-service cannot — source IP, port + protocol together, rate limits, logging, reject vs drop.
Example — SSH from one admin IP only:
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept' --permanentUse services/ports for simple holes; rich rules for micro-segmentation and logging.
A strong answer is:
"Rich rules handle fine-grained policy — source IP, port/protocol combos, logging, rate limits. I use --add-service for simple cases and rich rules when I need allow-from-one-IP or drop-with-log."
What do you use instead of firewalld on Ubuntu?
Ubuntu and Debian ship ufw (Uncomplicated Firewall) as the friendly front end, backed by nftables or iptables. There is no firewall-cmd unless you install firewalld manually.
Rough mapping:
| Task | firewalld | ufw |
|---|---|---|
| Allow HTTP | firewall-cmd --add-service=http --permanent |
ufw allow 80/tcp |
| Allow SSH | firewall-cmd --add-service=ssh --permanent |
ufw allow OpenSSH |
| Status | firewall-cmd --state |
ufw status |
On either distro you can still drop to nft/iptables for advanced cases.
A strong answer is:
"Ubuntu defaults to ufw, not firewalld. Same job — allow ports and services — different CLI. I match the tool to the distro rather than assuming firewall-cmd everywhere."
Troubleshooting
| Symptom | Likely cause | What to try |
|---|---|---|
firewall-cmd: command not found |
firewalld not installed (common on Ubuntu) | Install on RHEL/Fedora with dnf install firewalld; on Ubuntu use ufw |
| Rule missing after reboot | Added at runtime only, not --permanent |
firewall-cmd --list-all; re-add with --permanent and --reload |
| Service still blocked | Wrong zone or interface binding | --get-zone-of-interface=NIC; --list-all --zone=NAME |
--permanent change not active |
Forgot --reload |
sudo firewall-cmd --reload |
| SSH lost after hardening | Removed ssh service or set default zone to drop | Console access; restore ssh service in permanent config |
| Rich rule syntax error | Quoting or XML special characters | Copy from firewall-cmd --list-rich-rules; test runtime first |
Package installs and updates in this section use dnf command.
References
- Firewalld documentation — zones, services, policies
- Red Hat Enterprise Linux — Using firewalld — enterprise workflows

