Linux·8 min read·

firewalld Zones and Services: The RHEL-Family Firewall Guide

firewalld ships enabled on every RHEL-family install, so learn zones, services, permanent rules, and rich rules before an open port becomes an incident.

NB

Netbay Cloud Team

Netbay Engineering

On this page

firewalld is active from the first boot of every RHEL-family system, which means your Rocky or AlmaLinux server is never unprotected — but it is also not configured for your application until you touch it. The tool's zone model trips up people who learned on bare iptables, yet the idea is small: zones are named rulesets, every interface or source belongs to exactly one zone, and services are reusable bundles of ports. Learn the model plus a handful of commands and firewall work stops being folklore.

One host, two zones INTERNET eth0 ZONE: public (default) iface: eth0 services: ssh, http, https unmatched packets: DROP 10.0.0.0/8 ZONE: internal services: ssh, 5432/tcp rich rule: ssh from mgmt IP zones are per-interface or per-source, never both

Zones: Named Rulesets, Not Magic

A zone is a trust level: a set of allowed services plus a default target for everything else. EL systems ship about twenty predefined zones — public, internal, trusted, home, work, dmz, drop — and public is the default on every fresh install. Packets that match no rule fall through to the zone's target, which for public means DROP. The trusted zone accepts everything and exists for interfaces and sources you genuinely control, like a private management network.

bash
firewall-cmd --get-zones
firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
firewall-cmd --list-all

The last command is the one to memorize: it prints the zone, the interfaces and sources bound to it, and exactly which services and ports are open. When someone asks whether a port is open, --list-all is the honest answer, not memory. If a service listens on an interface you did not expect, its zone assignment — not the service definition — is the first thing to check.

Runtime Versus Permanent: The One Trap

Every rule exists in two layers, and confusing them is the classic firewalld mistake.

bash
sudo firewall-cmd --add-service=https              # runtime: live now, gone on reload
sudo firewall-cmd --permanent --add-service=https  # persistent: survives, not yet live
sudo firewall-cmd --runtime-to-permanent           # promote current runtime state
sudo firewall-cmd --reload                         # apply the permanent set

A runtime rule takes effect immediately and disappears on reload or reboot — useful for tests, dangerous as a habit. A permanent rule survives restarts but does nothing until a --reload activates it. The safest workflow: add with --permanent, then --reload, then verify with --list-all. If you tested something at runtime and it works, --runtime-to-permanent promotes the entire current state before any reload wipes it.

Services: Reusable Port Bundles

Rather than remembering that a web server wants 80/tcp and 443/tcp, firewalld ships XML definitions mapping a name to ports, protocols, and kernel helpers. For your own application, define one instead of scattering raw port rules.

bash
firewall-cmd --info-service=https
sudo firewall-cmd --permanent --new-service=myapp
sudo firewall-cmd --permanent --service=myapp --add-port=8443/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --permanent --add-service=myapp

Now the rule reads --add-service=myapp everywhere — in runbooks, in provisioning scripts, in --list-all output — instead of a bare port number nobody remembers the purpose of a year later.

Ports, Sources, and Rich Rules

When no service definition fits, open raw ports. When access should depend on who is asking, bind subnets to zones or write a rich rule.

bash
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --zone=internal --add-source=10.0.0.0/8
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.7/32" port port="22" protocol="tcp" accept'
sudo firewall-cmd --reload

The rich rule is the pattern worth adopting immediately: SSH restricted to one management address instead of open to the world with fail2ban as the only brake. Source assignments do the same job at subnet scale — the range above lands in the internal zone with its own, softer ruleset, while the public interface stays hostile to everything.

Panic Mode: The Seatbelt

Rich rule syntax has a learning curve, and mistakes over SSH are how people get locked out. firewalld ships an emergency brake — and a way to make it self-cancelling.

bash
sudo systemd-run --on-active=300 firewall-cmd --panic-off
sudo firewall-cmd --panic-on

While panic is on, the kernel drops every packet in and out, your session included — which is why the systemd-run timer comes first and lifts the panic in five minutes no matter what. It is a blunt but effective way to experiment with a ruleset you do not trust yet.

Takeaway: think in zones, express intent in named services, make everything permanent deliberately, and verify with --list-all before you reload. A Netbay VPS gives you root on a clean Rocky or AlmaLinux image with firewalld already active — deploy one in under 60 seconds at netbayhosts.in and practice on a disposable box, not on production.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance