17.4 Restrict Network Access Using firewalld and firewall-cmd
Key Takeaways
- firewalld implements host firewall policy; manage it with firewall-cmd and ensure the firewalld service is running and enabled when permanent rules must apply after reboot.
- Runtime vs permanent: --permanent writes lasting config; always firewall-cmd --reload (or --runtime-to-permanent patterns) so active policy matches what you saved.
- Open access with --add-service=NAME or --add-port=PORT/PROTOCOL, optionally scoped to a zone; verify with --list-all and connection tests.
- Zones (public, trusted, drop, etc.) define trust level and interfaces/sources; know the active zone for your NIC with firewall-cmd --get-active-zones.
- This section meets the networking objective to restrict access; the security chapter deepens firewalld scenarios—here focus on service/port rules, zones, permanence, and reload.
17.4 Restrict Network Access Using firewalld and firewall-cmd
Quick Answer: Keep
firewalldenabled and running. Allow needed traffic withfirewall-cmd --permanent --add-service=…or--add-port=…/tcp, thenfirewall-cmd --reload. Checkfirewall-cmd --list-all(and active zones). Default zones restrict unsolicited inbound access; you open only what the task requires.
Objective scope (networking vs security)
Under Manage basic networking, you must restrict network access using firewalld/firewall-cmd. Typical tasks:
- “Allow HTTP and HTTPS through the firewall permanently.”
- “Open TCP port 8080 in the default zone.”
- “Ensure firewalld is running and the
sshservice is allowed.”
A later security chapter deepens firewalld (richer policy, tighter scenarios). Here, master the network-restrict essentials: daemon up, zones awareness, add-service/add-port, permanent + reload, and verification.
Start from a working firewalld
systemctl status firewalld --no-pager
sudo systemctl enable --now firewalld
firewall-cmd --state
# should print: running
If firewalld is stopped, firewall-cmd fails and permanent rules do not protect or allow traffic as expected after boot.
systemctl is-enabled firewalld
systemctl is-active firewalld
Runtime vs permanent vs reload
| Mode | Flag / action | Survives reload? | Survives reboot? |
|---|---|---|---|
| Runtime | default firewall-cmd --add-… | Until reload/restart may drop | No (unless also permanent) |
| Permanent | --permanent --add-… | After --reload becomes active | Yes (with firewalld enabled) |
| Reload | firewall-cmd --reload | Applies permanent set to runtime | — |
# Runtime only (good for a quick test):
sudo firewall-cmd --add-service=http
# Permanent (exam default when “persist” is implied):
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
Critical exam pattern:
- Make changes with
--permanent. firewall-cmd --reload.- Verify with
--list-all(runtime view after reload).
Forgetting reload is a top failure mode: permanent XML is updated but the running firewall still blocks (or still allows) the old set.
# See permanent configuration without relying only on runtime:
firewall-cmd --permanent --list-all
firewall-cmd --list-all
Zones: trust buckets
firewalld organizes rules into zones. Interfaces (and/or sources) bind to a zone; the zone’s services/ports apply.
firewall-cmd --get-zones
firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
firewall-cmd --list-all
firewall-cmd --list-all-zones | less
| Zone (examples) | Typical idea |
|---|---|
public | Default-ish external: ssh often allowed, little else |
trusted | Accept most traffic (very open) |
home / work / internal | More services pre-associated |
drop / block | Highly restrictive inbound |
dmz / external | Specialized edge roles |
# Which zone is my NIC using?
firewall-cmd --get-active-zones
nmcli -f GENERAL.ZONE device show ens192 2>/dev/null
Add a service to a specific zone:
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --reload
If you omit --zone, commands use the default zone (or the zone context firewall-cmd applies—prefer being explicit when the task names a zone).
Change default zone (only when required):
sudo firewall-cmd --set-default-zone=public
Assign interface to zone permanently:
sudo firewall-cmd --permanent --zone=public --change-interface=ens192
sudo firewall-cmd --reload
(NetworkManager may also store connection.zone; keep NM and firewalld consistent if both are in play.)
sudo nmcli connection modify ens192 connection.zone public
sudo nmcli connection up ens192
Allow by service name
Predefined services map names to ports/protocols:
firewall-cmd --get-services | tr ' ' '\n' | head
firewall-cmd --info-service=http
firewall-cmd --info-service=https
firewall-cmd --info-service=ssh
firewall-cmd --info-service=nfs
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
firewall-cmd --list-services
Prefer --add-service when a predefined service exists (http, https, ssh, smtp, cockpit, …). It tracks the correct ports if definitions update.
Remove if you opened the wrong thing:
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload
Allow by port/protocol
When no service name fits or the task gives a raw port:
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --add-port=53/udp
sudo firewall-cmd --reload
firewall-cmd --list-ports
Syntax is port/protocol (tcp or udp). Ranges use 1000-2000/tcp form when needed.
sudo firewall-cmd --permanent --remove-port=8080/tcp
sudo firewall-cmd --reload
Restrict means default deny + explicit allow
firewalld’s usual zone posture blocks unsolicited inbound except listed services/ports (and related connection tracking for replies). “Restrict network access” on EX200 often means:
- Leave firewalld on (do not
stop/disableit to “make things work”). - Open only required services/ports.
- Optionally move hostile interfaces to stricter zones if the task says so.
Do not solve connectivity by systemctl stop firewalld unless a task explicitly demands firewalld off (rare for this objective).
Verification and testing
firewall-cmd --state
firewall-cmd --get-active-zones
firewall-cmd --list-all
firewall-cmd --permanent --list-all
# From another host or with local tools when appropriate:
curl -I http://SERVER_IP
ss -tlnp | grep 80
Symptom traps: service listens (sshd, httpd) but firewall closed → connection timeout; firewall open but service not running → connection refused. Check both.
systemctl is-active httpd
firewall-cmd --query-service=http
# query returns yes/no exit status
Runtime-to-permanent helper
If you tested with runtime adds and want to keep them:
sudo firewall-cmd --runtime-to-permanent
sudo firewall-cmd --reload # still good hygiene after major edits
Prefer deliberate --permanent adds during the exam so you do not copy experimental runtime junk.
Exam workflows
Workflow A — Permanent HTTP/HTTPS
sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
firewall-cmd --list-services
firewall-cmd --query-service=http && echo http-allowed
Workflow B — Custom TCP port
sudo firewall-cmd --permanent --add-port=8443/tcp
sudo firewall-cmd --reload
firewall-cmd --list-ports
Workflow C — Zone-specific allow
firewall-cmd --get-active-zones
sudo firewall-cmd --permanent --zone=public --add-service=nfs
sudo firewall-cmd --reload
firewall-cmd --zone=public --list-all
Workflow D — Accidentally runtime-only; fix permanence
firewall-cmd --list-services # shows http
firewall-cmd --permanent --list-services # missing http
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
Workflow E — Lock down mistake (opened too much)
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reload
Panic buttons (use carefully)
sudo firewall-cmd --panic-on # severe cut-off; can lock you out
sudo firewall-cmd --panic-off
Avoid panic mode on a remote exam unless you fully understand the impact. Prefer precise --add/--remove.
SELinux vs firewalld (do not confuse)
| Layer | Symptom if wrong |
|---|---|
| firewalld | Timeout / no route to peer from outside |
| SELinux | Local service denial; AVC in audit; often connection refused or app error even when port “open” |
| Service down | Connection refused |
Open the port and run the service and fix SELinux when serving content—but this section’s skill is firewall-cmd restriction/allow rules.
Common traps
--permanentwithout--reload.- Runtime-only open — works until reload/reboot, then fails grading.
stop firewalldto allow traffic — fails “restrict with firewalld.”- Wrong zone — rule in
workwhile interface is inpublic. --add-port=80without/tcp.- Allowing
httpbut testing HTTPS only (or the reverse). - firewalld disabled at boot — permanent files exist but daemon never loads them.
- Assuming
trustedis default — oftenpublicor environment-specific; always check. - Opening ports but forgetting
enable --nowon the application service. - Confusing this checklist with deep rich-rule mastery — learn basics here; security chapter expands.
Relationship to other content
| Skill | Where |
|---|---|
| IP addressing / DNS | 17.1–17.2 |
| NM at boot | 17.3 |
| firewalld services/ports/zones/reload | 17.4 |
| Deeper firewall settings | Security chapter (firewalld-security) |
| SELinux ports/booleans | Security SELinux chapters |
| sshd/httpd enable | Deploy services chapter |
Section checkpoint
You should enable and run firewalld, inspect default and active zones, permanently --add-service or --add-port, --reload, verify with --list-all / --query-service, remove mistaken openings, and keep the firewall on as the restriction mechanism. That meets the EX200 networking objective to restrict network access with firewalld and firewall-cmd on RHEL 10, with richer firewall scenarios reserved for the security material that follows.
You need HTTP allowed after every reboot. Which sequence best matches RHEL firewalld practice?
What does firewall-cmd --reload do after you run firewall-cmd --permanent --add-port=8080/tcp?
Which command opens TCP port 9090 in the permanent configuration for the default zone workflow taught here?
Why might firewall-cmd --add-service=https appear to work now but fail after reboot?