RHEL 8 ships with firewalld as its default firewall management layer, replacing the older iptables static ruleset approach with a dynamic, zone-based model. Zones define the level of trust assigned to network interfaces and traffic sources, and rules can be added or removed at runtime without flushing the entire ruleset. This guide covers the essential firewall-cmd operations: managing zones, opening services and ports, removing rules, using rich rules for granular control, and enabling masquerade for NAT. All changes made with --permanent survive reboots; runtime-only changes (without the flag) are lost on restart or reload.
Prerequisites
- A RHEL 8 server with initial setup complete (see the Initial Server Setup guide)
- Root or
sudoaccess firewalldinstalled and running (dnf install -y firewalldif absent)
Step 1 — Start and Enable firewalld
Confirm that firewalld is active and set to start on boot before making any rule changes.
systemctl enable --now firewalld
systemctl status firewalld
# Check the active zone and current rules
firewall-cmd --get-active-zones
firewall-cmd --list-all
By default, the active zone on most RHEL 8 installations is public.
Step 2 — Understand Zones
Zones represent trust levels. The three most commonly used zones are public (default for internet-facing interfaces — only explicitly allowed services pass), trusted (all traffic accepted — use only for fully controlled networks), and drop (all inbound traffic silently dropped — useful for blocking an interface entirely).
# List all available zones
firewall-cmd --get-zones
# Show the default zone
firewall-cmd --get-default-zone
# Change the default zone
firewall-cmd --set-default-zone=public
Step 3 — Allow and Remove Services
Services are named groups of ports defined in /usr/lib/firewalld/services/. Adding a service by name is more readable and maintainable than opening raw port numbers.
# Allow HTTP and HTTPS permanently
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
# Remove a service
firewall-cmd --permanent --remove-service=http
# Reload to apply permanent changes
firewall-cmd --reload
# Confirm what is currently open
firewall-cmd --list-all
Step 4 — Open and Close Specific Ports
When a named service definition does not exist, you can open a port directly. Specify the protocol (tcp or udp) along with the port number.
# Open TCP port 8080
firewall-cmd --permanent --add-port=8080/tcp
# Open a UDP port
firewall-cmd --permanent --add-port=5353/udp
# Remove a port rule
firewall-cmd --permanent --remove-port=8080/tcp
firewall-cmd --reload
firewall-cmd --list-ports
Step 5 — Use Rich Rules for Granular Control
Rich rules let you match on source addresses, destination addresses, ports, and protocols simultaneously — giving you far more precision than simple service or port rules. They support actions of accept, drop, reject, and log.
# Allow SSH only from a specific subnet
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept'
# Drop all traffic from a specific IP
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.5" drop'
# Log and reject traffic to port 3306 from outside the local network
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="mysql" reject'
firewall-cmd --reload
firewall-cmd --list-rich-rules
Step 6 — Enable Masquerade for NAT
Masquerade translates outbound traffic from private network interfaces to the server’s public IP, enabling the server to act as a NAT gateway. This is commonly needed on routers or VPN servers.
# Enable masquerade on the public zone
firewall-cmd --permanent --zone=public --add-masquerade
# Verify masquerade is active
firewall-cmd --zone=public --query-masquerade
firewall-cmd --reload
Conclusion
You have configured firewalld on RHEL 8 using zones, opened and removed services and ports, written rich rules for precise traffic control, and enabled masquerade for NAT. All permanent changes survive reboots, and the zone model makes it straightforward to apply different trust levels to different interfaces as your infrastructure grows.
Next steps: How to Set Up SSH Key-Based Authentication on RHEL 8, How to Configure Fail2Ban to Protect SSH on RHEL 8, and Initial Server Setup with RHEL 8.