19.1 Configure Firewall Settings with firewall-cmd and firewalld

Key Takeaways

  • firewalld is the RHEL host firewall; keep the service enabled and use firewall-cmd for runtime and permanent policy.
  • Zones define trust (public, trusted, drop, internal, …); bind interfaces or sources, then open services/ports in the correct zone.
  • Always pair --permanent changes with firewall-cmd --reload so runtime matches saved policy after reboot.
  • Prefer predefined services (--add-service=http) when available; use --add-port=PORT/PROTO for custom listeners; rich rules cover source-limited allows.
  • Verify with --get-active-zones, --list-all, --list-services, and --list-ports; prove persistence by checking permanent config, not only live state.
Last updated: August 2026

19.1 Configure Firewall Settings with firewall-cmd and firewalld

Quick Answer: Keep firewalld running and enabled. Open what the task requires with firewall-cmd --permanent --add-service=… or --add-port=…/tcp (in the right zone), then firewall-cmd --reload. Inspect with --get-active-zones and --list-all. For tighter policy, assign interfaces/sources to zones and use rich rules when you must allow only specific sources.

Why this is a security objective (not only networking)

Chapter 17.4 introduced firewalld as the way to restrict network access under Manage basic networking. Under Manage security, EX200 still expects competent firewall settings: correct zone, permanent rules, reload, and verification that the host only exposes intended services. Lab language looks like:

  • “Configure the firewall so HTTP and HTTPS are permanently allowed.”
  • “Open TCP port 8443 in the default zone.”
  • “Assign the interface to the internal zone and allow only ssh and cockpit.”
  • “Allow NFS-related services from subnet 192.168.10.0/24 only.”

You are graded on end state after reboot: firewalld active, permanent configuration contains the required allows, and runtime matches after reload.

firewalld service baseline

systemctl status firewalld
systemctl is-enabled firewalld
systemctl is-active firewalld
sudo systemctl enable --now firewalld

If firewalld is stopped or masked, permanent XML never becomes live policy. Prefer firewalld on RHEL 10 training systems; do not replace the exam path with hand-built raw iptables/nft rule sets unless a task forces it (unlikely for standard EX200 wording).

firewall-cmd --state
# running

Runtime vs permanent vs reload

ModeWhat it changesSurvives reload/reboot?
Runtime (default firewall-cmd without --permanent)Live policy nowUntil reload/restart/reboot (not saved)
Permanent (--permanent)On-disk zone/service configAfter reload or service restart
firewall-cmd --reloadLoads permanent → runtimeMakes permanent rules active without full reboot

Exam habit: for lasting change, always:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
firewall-cmd --list-services

Optional dual-write (runtime now and permanent) without waiting for reload of only permanent:

sudo firewall-cmd --add-service=http
sudo firewall-cmd --permanent --add-service=http
# or after a series of runtime tweaks:
sudo firewall-cmd --runtime-to-permanent

--runtime-to-permanent snapshots current runtime into permanent files—useful after experimental runtime testing, dangerous if runtime is messy. Prefer explicit --permanent + --reload for clean exam steps.

sudo firewall-cmd --complete-reload   # harder reset; can drop connections

Prefer ordinary --reload on the exam unless something is stuck.

Zones: trust model

Zones are named policy buckets. Each zone has a default target (accept/reject/drop behavior for unmatched traffic) and a set of allowed services/ports/rich rules. Interfaces and source addresses are assigned to zones.

firewall-cmd --get-zones
firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
firewall-cmd --list-all-zones | less

Common zones you will meet:

ZoneTypical use
publicDefault-ish external: limited services (often ssh, dhcpv6-client)
trustedAccept almost everything (very open)
dropDrop incoming (stealthy deny)
blockReject incoming with ICMP/TCP reset
internal / work / homeMore services allowed for trusted networks
dmz / externalEdge/gateway-style policies

Default zone vs active zone

  • Default zone: used for interfaces not explicitly assigned elsewhere.
  • Active zones: zones currently binding interfaces and/or sources that have traffic context.
firewall-cmd --get-default-zone
sudo firewall-cmd --set-default-zone=public
firewall-cmd --get-active-zones

Changing default zone is permanent when done with firewall-cmd --set-default-zone (it writes configuration). Still verify which zone your NIC actually sits in.

Assign interface or source to a zone

# Interface permanently in internal zone
sudo firewall-cmd --permanent --zone=internal --change-interface=ens192
sudo firewall-cmd --reload
firewall-cmd --get-active-zones

# Source network treated as trusted (example)
sudo firewall-cmd --permanent --zone=trusted --add-source=192.168.50.0/24
sudo firewall-cmd --reload

Tip: Opening http in public does nothing useful if the interface is active only in internal without that service. Always --list-all for the zone that owns the NIC.

firewall-cmd --zone=public --list-all
firewall-cmd --zone=internal --list-all
# default zone list-all:
firewall-cmd --list-all

Services vs ports

Predefined services

firewalld ships XML service definitions (ports + protocols + helpers) under /usr/lib/firewalld/services/ (and overrides under /etc/firewalld/services/).

firewall-cmd --get-services
firewall-cmd --info-service=http
firewall-cmd --info-service=https
firewall-cmd --info-service=ssh

Allow a service in a zone:

sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload
firewall-cmd --zone=public --list-services

Remove when a task requires closing:

sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload

Prefer services when Red Hat/firewalld already defines the app (http, https, ssh, samba, nfs, cockpit, postgresql, …). Graders and docs often phrase “allow the http service.”

Ports (custom listeners)

When the task names a bare port (for example TCP 8080 or 8443):

sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --add-port=8443/tcp
sudo firewall-cmd --reload
firewall-cmd --list-ports

UDP example:

sudo firewall-cmd --permanent --add-port=53/udp
sudo firewall-cmd --reload

Port ranges:

sudo firewall-cmd --permanent --add-port=3000-3010/tcp
sudo firewall-cmd --reload

Remove:

sudo firewall-cmd --permanent --remove-port=8080/tcp
sudo firewall-cmd --reload
ApproachWhen
--add-service=NAMENamed application service exists
--add-port=N/tcp or /udpCustom or explicitly numeric port

Do not assume “HTTP is always 80 only via port add”—using --add-service=http is cleaner when the service is standard.

Query and audit commands (memorize)

firewall-cmd --state
firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
firewall-cmd --list-all
firewall-cmd --list-all-zones
firewall-cmd --list-services
firewall-cmd --list-ports
firewall-cmd --list-rich-rules
firewall-cmd --permanent --list-all
firewall-cmd --permanent --zone=public --list-all

--permanent --list-all shows what will load after reload/reboot. --list-all (no permanent) shows runtime. Both should match after a successful permanent change + reload.

Rich rules (introduction for security tasks)

Rich rules express finer policy: allow a service or port only from a source, log, or limit. Syntax is picky—use patterns you can type under pressure.

# Allow SSH only from a management subnet (example)
sudo firewall-cmd --permanent --zone=public \
  --add-rich-rule='rule family="ipv4" source address="192.168.100.0/24" service name="ssh" accept'
sudo firewall-cmd --reload
firewall-cmd --list-rich-rules

Port from one host:

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.25" port port="8443" protocol="tcp" accept'
sudo firewall-cmd --reload

Reject everything from a bad host (illustrative):

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.50" reject'
sudo firewall-cmd --reload

Remove a rich rule by repeating the same rule string with --remove-rich-rule.

Exam note: Many EX200 tasks stop at service/port + zone. Use rich rules when the task requires source restriction. If you only need “open HTTP globally in the zone,” do not invent rich rules.

Interfaces, NetworkManager, and zones

NetworkManager can store a connection’s firewall zone:

nmcli -f connection.zone connection show ens192
sudo nmcli connection modify ens192 connection.zone internal
sudo nmcli connection up ens192
firewall-cmd --get-active-zones

Alternatively, use firewall-cmd --change-interface as shown earlier. After interface moves, re-check which zone has your services.

SELinux is separate

Opening a port in firewalld does not relabel SELinux port types. If a daemon binds a non-default port, you may also need SELinux port labeling (later security chapters). Conversely, correct SELinux does not open firewalld. On multi-part tasks, fix both when symptoms match each layer.

Panic recovery without locking yourself out

When working over SSH, never permanently remove ssh from the only zone that holds your interface without another access path. Sequence for risky changes:

  1. Add new allows first.
  2. Test.
  3. Remove old rules only after verification.
  4. Prefer temporary runtime test, then permanent.
# Temporary test (gone after reload if not permanent)
sudo firewall-cmd --add-port=8080/tcp
# verify connectivity, then permanent + reload

Exam workflows

Workflow A — Permanent HTTP/HTTPS in default zone

sudo systemctl enable --now firewalld
firewall-cmd --get-default-zone
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
firewall-cmd --list-services
firewall-cmd --permanent --list-services

Workflow B — Custom TCP port

sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
firewall-cmd --list-ports

Workflow C — Zone + services for an interface

sudo firewall-cmd --permanent --zone=internal --change-interface=ens192
sudo firewall-cmd --permanent --zone=internal --add-service=ssh
sudo firewall-cmd --permanent --zone=internal --add-service=cockpit
sudo firewall-cmd --reload
firewall-cmd --get-active-zones
firewall-cmd --zone=internal --list-all

Workflow D — Source-limited allow (rich rule)

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="172.25.250.0/24" port port="9090" protocol="tcp" accept'
sudo firewall-cmd --reload
firewall-cmd --list-rich-rules

Workflow E — Verify permanence mindset

firewall-cmd --state
firewall-cmd --list-all
firewall-cmd --permanent --list-all
systemctl is-enabled firewalld

Common traps

  1. Runtime-only --add-service without --permanent—works now, gone after reboot/reload of permanent-only disk state.
  2. --permanent without --reload—disk updated, runtime still old.
  3. Adding rules to the wrong zone while the NIC is active in another zone.
  4. Using --add-port=80/tcp when the task said allow http service (often both work for port 80, but service name is what docs expect).
  5. Removing ssh permanently over a remote session and locking yourself out.
  6. Assuming firewalld is running—always check after minimal installs or hard problems.
  7. Confusing default zone with active zones.
  8. Opening the firewall but forgetting the daemon/service itself is not installed or not listening.
  9. Expecting rich-rule typos to work—quote carefully; verify with --list-rich-rules.
  10. Treating iptables -F as a firewalld configuration method on modern RHEL exams.

Relationship to other sections

TopicWhere
Restrict network access (intro)17.4
Deep firewall settings (this)19.1
Services listening / systemdOperate / deploy chapters
SELinux ports/booleansSecurity SELinux chapters
SSH access path19.3 and essential SSH

Section checkpoint

You should enable firewalld, choose the correct zone, open services and ports permanently, reload, optionally use interface/source assignment and simple rich rules, and prove runtime and permanent lists match the task. That is the EX200 security bar for firewall settings with firewall-cmd on RHEL 10.

Test Your Knowledge

Which sequence permanently allows the http service and makes it active in the running firewalld policy?

A
B
C
D
Test Your Knowledge

You added a port with firewall-cmd --permanent --add-port=8080/tcp but clients still time out, and firewall-cmd --list-ports does not show 8080/tcp. What is the most likely missing step?

A
B
C
D
Test Your Knowledge

firewall-cmd --list-all shows services in zone public, but your NIC is listed under zone internal in --get-active-zones. You added http only to public. What is wrong?

A
B
C
D
Test Your Knowledge

A task requires allowing TCP 9090 only from 172.25.250.0/24. Which tool feature best matches that requirement?

A
B
C
D