CrackOps
Interview PrepTracksLinuxAWS LabSoonInterview RoomSoon
Sign inStart free
CrackOps

Interview prep for the people who keep production up.

[email protected]
ProductInterview PrepTracksDashboardInterview Room
RolesDevOpsSREPlatformCloud
CompanyAboutContactPrivacyTerms
© CrackOps
Linux / Network Transfer & Tools / firewall-cmd

firewall-cmd

Manage firewalld zones, services and ports

Intermediatefirewallsecurityrhel

firewall-cmd controls firewalld, the default firewall manager on RHEL, Rocky, Alma, CentOS and Fedora. Instead of raw rules you open services and ports in zones, and every change is either runtime (immediate, lost on reload) or permanent (saved, applied on reload).

Syntaxfirewall-cmd [--permanent] [--zone=ZONE] --add-service=S | --add-port=P/PROTO | --add-rich-rule='...' | --list-all | --reload

Watch it run

You log in to a RHEL-family server for the first time and need to know what the firewall lets in.

devops@devops-lab: ~ — zsh — 96×28
➜ ~
Step 1 of 3
firewall-cmd --list-all

firewalld asks polkit whether you may query it; a normal user over SSH may not. Use sudo.

Anatomy of a command

$
commandsudo

Changes need root (or polkit authorisation); without it you get 'Authorization failed'.

How it works

firewalld is a daemon that owns the host's netfilter rules (through nftables on current releases); firewall-cmd sends it requests over D-Bus. Its model is zones: each network interface or source address range belongs to one zone (public, internal, trusted, drop...), and each zone lists what is allowed in: services (named bundles of ports from /usr/lib/firewalld/services/*.xml, such as ssh = 22/tcp), plain ports, rich rules for finer conditions, masquerading and port forwards. A packet is handled by the zone of its source address if one matches, otherwise by the zone of the interface it arrived on. Every setting exists twice: the runtime configuration in the kernel right now, and the permanent configuration in /etc/firewalld/zones/*.xml. --permanent edits only the latter; --reload replaces the runtime with the permanent one, discarding runtime-only changes. firewalld 2.x (Fedora, RHEL 10, Ubuntu 24.04) also prints ingress/egress priorities in --list-all; RHEL 9's 1.x output doesn't have those lines.

Options you'll actually use

--stateIs firewalld running?
--get-default-zone / --get-active-zonesDefault zone / zones in use with their interfaces and sources
--list-all [--zone=Z]Everything a zone allows
--add-service=S / --remove-service=SOpen or close a named service (ssh, http, https...)
--add-port=N/tcpOpen a port or range (8000-8100/tcp)
--permanentChange the saved config instead of the running one
--reloadLoad the permanent config into the runtime
--runtime-to-permanentSave the current runtime config as permanent
--zone=Z --add-source=CIDRSend traffic from a source range to zone Z
--add-rich-rule='rule ...'Detailed rule: source, port, log, limit, accept/reject/drop
--get-services / --info-service=SAll service names / ports of one service
--add-forward-port=...Port forwarding (DNAT) in a zone
--timeout=5mRuntime change that removes itself after the time (safe testing)

Common mistakes

sudo firewall-cmd --add-port=8080/tcp and moving on

It's a runtime-only change: the next --reload or reboot silently removes it.

sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload
sudo firewall-cmd --permanent --add-service=http and expecting it to work now

Permanent changes don't touch the running firewall until a reload.

Follow it with sudo firewall-cmd --reload (or apply both with and without --permanent).
Adding iptables rules by hand on a firewalld host

firewalld owns the rule set and rebuilds it on reload, dropping your manual rules.

Use rich rules or direct firewalld configuration instead.
--add-port=5432/tcp to let the app servers reach the database

That opens the port to every source that reaches the zone, including the internet if the host is exposed.

A rich rule with source address=10.0.2.0/24, or a source-based zone.

Interview questions

Practice

Try these on a Linux machine of your own. Each task has a hint and a solution.

  1. 1

    Write the commands to permanently open HTTPS in the default zone and apply the change.

  2. 2

    Write the command to permanently allow TCP 9100 (node exporter) only from 10.0.5.0/24.

  3. 3

    Read this output and explain what's reachable from outside: 'services: dhcpv6-client ssh ports: 8080/tcp'. Then write the command to close 8080 permanently.

Related commands

iptablesFilter and NAT packets with netfilter rulesufwManage the host firewall the simple waynmapScan hosts and ports, detect servicessystemctlStart, stop, enable and inspect systemd services
PreviousiptablesNextstrace
Linux / Network Transfer & Tools / firewall-cmd

firewall-cmd

Manage firewalld zones, services and ports

Intermediatefirewallsecurityrhel

firewall-cmd controls firewalld, the default firewall manager on RHEL, Rocky, Alma, CentOS and Fedora. Instead of raw rules you open services and ports in zones, and every change is either runtime (immediate, lost on reload) or permanent (saved, applied on reload).

Syntaxfirewall-cmd [--permanent] [--zone=ZONE] --add-service=S | --add-port=P/PROTO | --add-rich-rule='...' | --list-all | --reload

Watch it run

You log in to a RHEL-family server for the first time and need to know what the firewall lets in.

devops@devops-lab: ~ — zsh — 96×28
➜ ~
Step 1 of 3
firewall-cmd --list-all

firewalld asks polkit whether you may query it; a normal user over SSH may not. Use sudo.

Anatomy of a command

$
commandsudo

Changes need root (or polkit authorisation); without it you get 'Authorization failed'.

How it works

firewalld is a daemon that owns the host's netfilter rules (through nftables on current releases); firewall-cmd sends it requests over D-Bus. Its model is zones: each network interface or source address range belongs to one zone (public, internal, trusted, drop...), and each zone lists what is allowed in: services (named bundles of ports from /usr/lib/firewalld/services/*.xml, such as ssh = 22/tcp), plain ports, rich rules for finer conditions, masquerading and port forwards. A packet is handled by the zone of its source address if one matches, otherwise by the zone of the interface it arrived on. Every setting exists twice: the runtime configuration in the kernel right now, and the permanent configuration in /etc/firewalld/zones/*.xml. --permanent edits only the latter; --reload replaces the runtime with the permanent one, discarding runtime-only changes. firewalld 2.x (Fedora, RHEL 10, Ubuntu 24.04) also prints ingress/egress priorities in --list-all; RHEL 9's 1.x output doesn't have those lines.

Options you'll actually use

--stateIs firewalld running?
--get-default-zone / --get-active-zonesDefault zone / zones in use with their interfaces and sources
--list-all [--zone=Z]Everything a zone allows
--add-service=S / --remove-service=SOpen or close a named service (ssh, http, https...)
--add-port=N/tcpOpen a port or range (8000-8100/tcp)
--permanentChange the saved config instead of the running one
--reloadLoad the permanent config into the runtime
--runtime-to-permanentSave the current runtime config as permanent
--zone=Z --add-source=CIDRSend traffic from a source range to zone Z
--add-rich-rule='rule ...'Detailed rule: source, port, log, limit, accept/reject/drop
--get-services / --info-service=SAll service names / ports of one service
--add-forward-port=...Port forwarding (DNAT) in a zone
--timeout=5mRuntime change that removes itself after the time (safe testing)

Common mistakes

sudo firewall-cmd --add-port=8080/tcp and moving on

It's a runtime-only change: the next --reload or reboot silently removes it.

sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload
sudo firewall-cmd --permanent --add-service=http and expecting it to work now

Permanent changes don't touch the running firewall until a reload.

Follow it with sudo firewall-cmd --reload (or apply both with and without --permanent).
Adding iptables rules by hand on a firewalld host

firewalld owns the rule set and rebuilds it on reload, dropping your manual rules.

Use rich rules or direct firewalld configuration instead.
--add-port=5432/tcp to let the app servers reach the database

That opens the port to every source that reaches the zone, including the internet if the host is exposed.

A rich rule with source address=10.0.2.0/24, or a source-based zone.

Interview questions

Practice

Try these on a Linux machine of your own. Each task has a hint and a solution.

  1. 1

    Write the commands to permanently open HTTPS in the default zone and apply the change.

  2. 2

    Write the command to permanently allow TCP 9100 (node exporter) only from 10.0.5.0/24.

  3. 3

    Read this output and explain what's reachable from outside: 'services: dhcpv6-client ssh ports: 8080/tcp'. Then write the command to close 8080 permanently.

Related commands

iptablesFilter and NAT packets with netfilter rulesufwManage the host firewall the simple waynmapScan hosts and ports, detect servicessystemctlStart, stop, enable and inspect systemd services
PreviousiptablesNextstrace