Chapter Objective: Configure firewalld zones, permit or block services and ports, and write rich rules for more granular network access control.
Key commands: firewall-cmd, firewall-cmd --add-service, firewall-cmd --add-port
RHEL's Firewall: firewalld
firewalld is RHEL's dynamic firewall management service, sitting on top of the kernel's packet filtering (nftables on current RHEL). Unlike editing raw firewall rules directly, firewalld organizes access around zones and named services, and applies changes without dropping existing connections.
| Concept | Meaning |
|---|---|
| Zone | A named trust level applied to one or more network interfaces |
| Service | A predefined, named group of ports/protocols (e.g. "ssh," "http") |
| Runtime config | Active right now; lost on reload/reboot unless also made permanent |
| Permanent config | Saved to disk; takes effect on the next reload or boot |
Zones
Every network interface is assigned to exactly one zone, and each zone has its own set of allowed services, ports, and rules — letting a laptop, for example, trust a home network more than public Wi-Fi.
# Show the default zone
firewall-cmd --get-default-zone
# List all available zones
firewall-cmd --get-zones
# Show full configuration for the active zone
firewall-cmd --list-all
# Show which zone an interface is in
firewall-cmd --get-zone-of-interface=eth0
# Change an interface's zone
sudo firewall-cmd --zone=internal --change-interface=eth0
| Common Zone | Typical Trust Level |
|---|---|
public | Default; limited trust, suitable for untrusted networks |
internal | Trusted internal network |
trusted | All traffic accepted |
drop | All incoming traffic silently dropped |
Managing Services and Ports
# List services allowed in the active zone
firewall-cmd --list-services
# Allow a predefined service by name
sudo firewall-cmd --add-service=http
# Allow a raw port/protocol directly
sudo firewall-cmd --add-port=8080/tcp
# Remove access
sudo firewall-cmd --remove-service=http
# List all predefined service names firewalld knows about
firewall-cmd --get-services
--add-service=http is more self-documenting than --add-port=80/tcp, and updates automatically if the associated port ever changes in a predefined service definition. Use raw ports mainly for custom applications without a predefined service.
Runtime vs. Permanent Configuration
# This change is active immediately, but lost after a reload/reboot
sudo firewall-cmd --add-service=http
# Add --permanent to save it to disk instead (takes effect on next reload)
sudo firewall-cmd --permanent --add-service=http
# Common pattern: apply now AND make it permanent
sudo firewall-cmd --add-service=http
sudo firewall-cmd --permanent --add-service=http
# Or make the permanent config active immediately by reloading
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
--permanent works immediately and looks correct — until the next reboot silently reverts it. If a firewall rule that "was working fine" mysteriously vanishes, this is the first thing to check.
Rich Rules
When a named service or simple port isn't granular enough — restricting access by source IP, for example — rich rules provide more expressive, structured syntax.
# Allow SSH only from a specific subnet
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="192.168.1.0/24"
service name="ssh"
accept'
# Explicitly reject (not just drop) traffic from a specific address
sudo firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="203.0.113.50"
reject'
# List active rich rules
firewall-cmd --list-rich-rules
# Apply the changes
sudo firewall-cmd --reload
reject sends back an explicit refusal (the connection fails fast); drop silently discards the packet with no response at all (the connection hangs until it times out). Which is appropriate depends on whether you want a would-be connector to know immediately that they were denied.
Viewing and Troubleshooting
# Confirm firewalld itself is running
systemctl status firewalld
# Full picture: zone, services, ports, rich rules, all in one place
firewall-cmd --list-all
# Test whether a change is only runtime or also permanent
firewall-cmd --list-services # current runtime state
firewall-cmd --permanent --list-services # saved permanent state
systemctl status)? Is it listening on the expected port (ss -tuln)? Is firewalld actually allowing that port/service? Each layer rules out a different cause.
Key Terms for Chapter 14
- firewalld
- RHEL's dynamic firewall management service
- zone
- A named trust level applied to a network interface, with its own allowed services/ports
- service (firewalld)
- A predefined, named group of ports and protocols
- runtime configuration
- Firewall configuration active immediately, lost on reload unless also made permanent
- permanent configuration
- Firewall configuration saved to disk, applied on the next reload or boot
- rich rule
- A structured firewalld rule offering more granular matching than a simple service or port
- reject / drop
- Denying traffic with an explicit refusal versus silently discarding it
Review Questions
- What is the difference between a firewalld zone and a firewalld service?
- Write a command that permanently allows the "https" service through the firewall.
- What is the single most common mistake administrators make when changing firewalld rules, and how do you avoid it?
- When would you reach for a rich rule instead of a simple
--add-serviceor--add-port? - What is the practical difference between
rejectanddropin a firewall rule? - What command shows the complete current configuration — zone, services, ports, and rich rules — for the active zone?
- A web application seems unreachable from another machine. List, in order, three things you'd check to narrow down the cause.