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 sudo access
  • firewalld installed and running (dnf install -y firewalld if 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.