aoitcloud

AlmaLinux

firewalld Basics on RHEL-Family Linux

A practical introduction to firewalld - zones, services, and ports - with the firewall-cmd commands you need to open ports safely on a new VPS.

4 October 2024 5 min read

Every RHEL-family distribution – AlmaLinux, Rocky Linux, Oracle Linux, VzLinux, Fedora – ships with firewalld enabled by default. If you’ve just provisioned a VPS and can’t reach a service you’ve installed, firewalld blocking the port is one of the first things to check. This guide covers the concepts and the commands you need to manage it confidently.

How firewalld thinks: zones

Unlike a flat list of allow/deny rules, firewalld organises things around zones. A zone is a named set of rules that defines how much a network interface is trusted. Each network interface is assigned to exactly one zone, and the rules for that zone apply to any traffic arriving on it.

Common predefined zones include:

  • public – for use in untrusted public networks; the default zone on most installs, and almost always the one your VPS’s network interface is in
  • trusted – accepts all traffic; rarely appropriate on a public-facing server
  • internal / home / work – for trusted local networks
  • drop / block – very restrictive, drops or rejects almost everything inbound

On a typical VPS, you’ll do almost all your work in the public zone and never need to touch the others.

Services vs. ports

Within a zone, you can allow traffic two ways:

  • Services – predefined, named rules that bundle the correct port(s) and protocol for a common piece of software, e.g. allowing the ssh service opens TCP port 22. These are just XML definitions under /usr/lib/firewalld/services/, and firewalld ships with definitions for dozens of common services.
  • Ports – raw port/protocol combinations, e.g. 8080/tcp, for anything that doesn’t have (or doesn’t match) a predefined service.

Using the named service is preferable when one exists, since it’s self-documenting – --add-service=http is clearer than --add-port=80/tcp to anyone reading your config later.

Checking firewalld’s status

Confirm firewalld is running:

sudo firewall-cmd --state

See which zone your interfaces are actually using:

firewall-cmd --get-active-zones

Which will typically show something like:

public
  interfaces: eth0

Check which zone is the default (used for interfaces that aren’t explicitly assigned elsewhere):

firewall-cmd --get-default-zone

And see the full rule set for a zone – services, ports, and everything else currently allowed:

firewall-cmd --zone=public --list-all

Output looks something like this:

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: cockpit dhcpv6-client ssh
  ports:
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

Note that a fresh AlmaLinux or Rocky Linux VPS typically has ssh allowed by default – that’s what’s kept your existing SSH session working. Don’t remove it without opening another way in first, or you’ll lock yourself out.

Runtime vs. permanent changes – the part that trips people up

This is the single most important thing to understand about firewalld. By default, firewall-cmd changes are runtime only – they take effect immediately, but disappear the next time firewalld restarts or the server reboots.

To make a change stick, add the --permanent flag. But permanent changes don’t take effect immediately – they’re written to the on-disk configuration and only applied on the next reload or restart.

In practice, this means you either:

  • Run the command twice – once without --permanent to apply it now, and once with --permanent to save it for next time, or
  • Run it once with --permanent, then run firewall-cmd --reload to apply the saved configuration immediately (a reload doesn’t drop existing connections, so it’s safe to run over SSH)

The second approach is generally cleaner and is what we’ll use below.

Worked example: opening port 443 for a web server

Say you’ve just installed nginx and configured TLS, and you need to let HTTPS traffic through. HTTPS is a predefined firewalld service, so use it rather than the raw port number:

sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload

Verify it’s there:

firewall-cmd --zone=public --list-services
cockpit dhcpv6-client http https ssh

If you’d rather work with the raw port instead (say, for a service without a predefined firewalld entry), the equivalent is:

sudo firewall-cmd --permanent --zone=public --add-port=443/tcp
sudo firewall-cmd --reload

Check open ports the same way:

firewall-cmd --zone=public --list-ports

To remove a rule you no longer need, swap --add- for --remove-, again with --permanent and a reload:

sudo firewall-cmd --permanent --zone=public --remove-service=https
sudo firewall-cmd --reload

Listing available predefined services

To see every service firewalld knows about before deciding whether to use a named service or a raw port:

firewall-cmd --get-services

This returns a long space-separated list including things like http, https, ssh, ftp, mysql, postgresql, and smtp. If the service you need isn’t listed, use --add-port with the correct port and protocol from the software’s own documentation.

A quick reference

TaskCommand
Check firewalld is runningfirewall-cmd --state
Show active zonesfirewall-cmd --get-active-zones
Show default zonefirewall-cmd --get-default-zone
List everything allowed in a zonefirewall-cmd --zone=public --list-all
Open a service permanentlyfirewall-cmd --permanent --zone=public --add-service=https
Open a port permanentlyfirewall-cmd --permanent --zone=public --add-port=443/tcp
Apply saved changesfirewall-cmd --reload
List available servicesfirewall-cmd --get-services

The rule of thumb: only open what you actually need running, use the named service where one exists, and always pair --permanent changes with a --reload so what you tested is actually what survives a reboot.

Get in touch

Drop our team a message today