| |

LFCS 106 ๐Ÿง Firewalld โ€” Concepts

โฑ๏ธ Estimated read: 10 min | |

A firewall is not a single rule. It is a system of trust boundaries, and firewalld is the daemon that enforces them on most modern Linux distributions, including RHEL, CentOS, Fedora, and SUSE. Unlike raw iptables or nftables, firewalld introduces a layer of abstraction: zones, services, and policies. These abstractions simplify the configuration of common scenarios, but they also introduce a conceptual model that must be understood before any rule is written. The LFCS exam tests this modelโ€”the relationship between zones, services, and the runtime-versus-permanent configuration splitโ€”because a misunderstanding of the model produces rules that appear to work and then vanish after a reboot.

Key point: firewalld maintains two separate configurations: runtime and permanent. A change made without --permanent is active immediately but is lost on reload or restart. A change made with --permanent is written to disk but does not affect the running firewall until firewall-cmd --reload is executed.


Why firewalld exists

The dynamic configuration problem. The legacy iptables service required a full flush and reload of all rules whenever a single rule changed. firewalld was designed to be dynamic: rules can be added, modified, and removed without interrupting established connections or restarting the daemon. This is achieved through a D-Bus interface that communicates with the firewall backend (nftables on modern systems) and applies changes incrementally .

The zone abstraction problem. Raw firewall rules operate on interfaces, IP addresses, and ports. There is no concept of “this interface is on an untrusted network” or “this interface is on a trusted internal network.” firewalld introduces zones to represent levels of trust. An interface is assigned to a zone, and the zone defines what traffic is permitted. When a laptop moves from a corporate network to a coffee shop Wi-Fi, the interface can be reassigned to a different zone, and the entire ruleset changes without rewriting individual rules .

The service abstraction problem. Opening a port for a service often requires more than one rule. A web server might need TCP port 80, TCP port 443, and ICMP echo requests. Instead of writing three rules, the administrator adds the http and https services to the zone. A service is a named, predefined set of ports, protocols, and helper modules. firewalld ships with dozens of service definitions, and custom services can be created .

The persistence problem. The iptables service persisted rules by saving them to a file and restoring them at boot. firewalld makes persistence explicit: every command operates on either the runtime configuration or the permanent configuration. The --permanent flag writes to disk; the absence of the flag writes only to memory. The --runtime-to-permanent command copies the running configuration to disk, and --reload discards runtime changes and reloads from disk .

The trade-off. firewalld is not a universal replacement for raw nftables. Complex, high-performance, or highly customized rulesets are better expressed directly in nftables. firewalld covers the majority of typical host-firewall scenarios, but it is an abstraction, and the abstraction leaks when the scenario is unusual .


a. Zones: the trust boundaries

A zone is a named collection of rules that defines the level of trust for the network traffic that enters through it. Every network interface is assigned to exactly one zone. Every packet that arrives on that interface is evaluated against the rules of that zone .

firewalld defines several predefined zones. The most important for the exam are public, trusted, home, work, drop, and block.

The public zone is the default zone on a fresh installation. It is intended for untrusted networks, and it allows only the ssh and dhcpv6-client services by default. The trusted zone allows all traffic. The drop zone silently drops all incoming packets without sending a response. The block zone rejects incoming packets with an ICMP error message .

An interface can be moved between zones with firewall-cmd --zone=work --change-interface=enp0s3. The change takes effect immediately and is persistent across restarts because firewalld forwards the assignment to NetworkManager, which stores the configuration .

The --get-active-zones command shows which zones are currently active and which interfaces are assigned to them. A zone is active only if it has an interface or a source assigned to it. The public zone is a special case: it is always active as the default zone, even if no interface is explicitly assigned to it .


b. Services and ports: the allowed traffic

A service is a named definition of the ports, protocols, and modules required to allow a specific application. The ssh service, for example, opens TCP port 22. The http service opens TCP port 80. The https service opens TCP port 443 .

Services are added to a zone with firewall-cmd --add-service=http. This opens the ports defined by the service within the specified zone. The --list-services command shows which services are allowed in the current zone. The --get-services command lists every service definition available on the system .

When a service definition does not exist, a raw port can be opened instead. firewall-cmd --add-port=8080/tcp opens TCP port 8080 in the zone. The port is specified as <port>/<protocol>, where the protocol is tcp, udp, sctp, or dccp. The --list-ports command shows the raw ports that have been opened .

The recommendation is to use services whenever possible. A service definition documents its purpose, and the name is self-explanatory. A raw port number is opaque: six months later, no one remembers why port 8443 was opened .


c. Runtime, permanent, and the reload cycle

The distinction between runtime and permanent is the most common source of confusion in firewalld. Every command that modifies the configuration operates on the runtime configuration by default. The change is applied immediately to the running firewall. If the system reboots, or if firewall-cmd --reload is executed, the runtime configuration is discarded and the permanent configuration is loaded .

To make a change permanent, the --permanent flag must be added to the command. The change is written to the XML files under /etc/firewalld/ but does not affect the running firewall. To apply the permanent change, firewall-cmd --reload must be executed .

The --runtime-to-permanent command is the inverse: it copies the current runtime configuration to the permanent configuration, making all active changes persistent without a reload .

The default zone is an exception to the flag rule. firewall-cmd --set-default-zone=home is permanent even without the --permanent flag. The same applies to interface assignments: firewall-cmd --zone=work --change-interface=enp0s3 is persistent because it is stored in NetworkManager, not in the firewalld runtime configuration .


Complete Example Session

# ============================================
# PART 1: CHECK THE CURRENT STATE
# ============================================

firewall-cmd --state
# Output: running
# ============================================
# PART 2: LIST THE DEFAULT ZONE
# ============================================

firewall-cmd --get-default-zone
# Output: public
# ============================================
# PART 3: LIST SERVICES IN THE DEFAULT ZONE
# ============================================

firewall-cmd --list-services
# Output: ssh dhcpv6-client
# ============================================
# PART 4: ADD A SERVICE (RUNTIME ONLY)
# ============================================

firewall-cmd --add-service=http
# Output: success
# The change is active immediately.
# ============================================
# PART 5: VERIFY THE RUNTIME CHANGE
# ============================================

firewall-cmd --list-services
# Output: ssh dhcpv6-client http
# ============================================
# PART 6: RELOAD AND OBSERVE THE LOSS
# ============================================

firewall-cmd --reload
# Output: success
firewall-cmd --list-services
# Output: ssh dhcpv6-client
# The http service is gone because it was runtime-only.
# ============================================
# PART 7: ADD A SERVICE PERMANENTLY
# ============================================

firewall-cmd --add-service=http --permanent
# Output: success
firewall-cmd --list-services
# Output: ssh dhcpv6-client
# The permanent change is not yet active.
# ============================================
# PART 8: RELOAD TO APPLY THE PERMANENT CHANGE
# ============================================

firewall-cmd --reload
# Output: success
firewall-cmd --list-services
# Output: ssh dhcpv6-client http
# ============================================
# PART 9: SAVE RUNTIME CHANGES TO PERMANENT
# ============================================

firewall-cmd --add-service=https
firewall-cmd --runtime-to-permanent
# The runtime change is now written to disk.

The nine parts trace the runtime-permanent distinction: checking state, listing services, adding a runtime service, verifying it, observing its loss on reload, adding a permanent service, reloading to apply it, and saving runtime changes to permanent.


Quick Reference

Zones

ZoneTrust LevelDefault Services
publicUntrustedssh, dhcpv6-client
trustedFully trustedAll traffic allowed
dropUntrustedAll incoming dropped silently
blockUntrustedAll incoming rejected with ICMP
homeMostly trustedssh, mdns, samba-client
workMostly trustedssh, dhcpv6-client

Commands

CommandPurpose
firewall-cmd --stateCheck if firewalld is running
firewall-cmd --get-default-zoneShow default zone
firewall-cmd --list-allShow all settings for default zone
firewall-cmd --add-service=<svc>Allow service in runtime
firewall-cmd --add-service=<svc> --permanentAllow service permanently
firewall-cmd --add-port=<port>/<proto>Open raw port
firewall-cmd --reloadReload permanent config into runtime
firewall-cmd --runtime-to-permanentSave runtime to permanent

Configuration Files

PathPurpose
/usr/lib/firewalld/zones/Default zone definitions
/etc/firewalld/zones/Custom zone definitions (override defaults)
/usr/lib/firewalld/services/Default service definitions
/etc/firewalld/services/Custom service definitions (override defaults)

Best Practices

โœ… Do This:

firewall-cmd --add-service=http --permanent
firewall-cmd --reload
<!-- Add permanently, then reload to apply -->      # โœ…
firewall-cmd --add-service=ssh
<!-- Test in runtime before making permanent -->     # โœ…
firewall-cmd --runtime-to-permanent
<!-- Save a tested runtime configuration -->        # โœ…

โŒ Don’t Do This:

firewall-cmd --add-service=http
# Then reboot
<!-- Runtime change is lost -->                     # โŒ
# Open a raw port without documenting why
<!-- Use a service definition or comment -->         # โŒ
# Assume --permanent takes effect immediately
<!-- It requires a reload -->                       # โŒ

Common Pitfalls

PitfallWhy It HappensFix
Rule disappears after rebootAdded without --permanentAdd --permanent and --reload
Rule not active after --permanentNo reload executedfirewall-cmd --reload
Cannot connect after adding serviceService added to wrong zoneCheck --get-active-zones
SSH connection lostPanic mode enabled or zone changedUse console access; --panic-off
Zone assignment not persistentUsed --permanent with --change-interfaceInterface zones are stored by NetworkManager

Real-World Examples

1. Check State

firewall-cmd --state

2. List Default Zone

firewall-cmd --get-default-zone

3. List All in Zone

firewall-cmd --list-all

4. Add Service (Runtime)

firewall-cmd --add-service=http

5. Add Service (Permanent)

firewall-cmd --add-service=http --permanent

6. Reload

firewall-cmd --reload

7. Change Default Zone

firewall-cmd --set-default-zone=home

8. Change Interface Zone

firewall-cmd --zone=work --change-interface=enp0s3

9. Save Runtime to Permanent

firewall-cmd --runtime-to-permanent

10. List Active Zones

firewall-cmd --get-active-zones

Visual

Zone and Interface Relationship

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  NETWORK INTERFACES                          โ”‚
โ”‚  โ”œโ”€โ”€ enp0s3 (wired)                          โ”‚
โ”‚  โ””โ”€โ”€ wlan0 (wireless)                        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ Each interface is assigned
                   โ”‚ to exactly one zone.
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ZONES                                       โ”‚
โ”‚  โ”œโ”€โ”€ public (default)                        โ”‚
โ”‚  โ”‚   โ”œโ”€โ”€ ssh                                 โ”‚
โ”‚  โ”‚   โ””โ”€โ”€ dhcpv6-client                       โ”‚
โ”‚  โ””โ”€โ”€ work                                    โ”‚
โ”‚      โ”œโ”€โ”€ ssh                                 โ”‚
โ”‚      โ””โ”€โ”€ http                                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The zone defines what the interface is allowed to receive.

Runtime vs Permanent

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  firewall-cmd --add-service=http             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  RUNTIME CONFIGURATION                       โ”‚
โ”‚  Active immediately.                         โ”‚
โ”‚  Lost on reload or reboot.                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ”‚ firewall-cmd --runtime-to-permanent
                   โ”‚ or: --add-service=http --permanent
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  PERMANENT CONFIGURATION                     โ”‚
โ”‚  Written to /etc/firewalld/.                 โ”‚
โ”‚  Loaded on boot or reload.                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The two configurations are independent until explicitly synchronized.


Summary

ItemValue
Daemonfirewalld
Default zonepublic
Zone purposeTrust level for interfaces
Service purposeNamed set of ports/protocols
Runtime configActive, lost on reload
Permanent configWritten to disk, requires reload
Add permanent--permanent flag
Apply permanentfirewall-cmd --reload
Save runtimefirewall-cmd --runtime-to-permanent

Key takeaways:

  • Zones define trust. Every interface is assigned to a zone. The zone determines what traffic is allowed. The default zone is public, which allows only ssh and dhcpv6-client .
  • Services are named port sets. Adding a service opens all the ports and protocols it defines. Services are preferable to raw ports because they are self-documenting .
  • Runtime and permanent are separate. A change without --permanent is active immediately but is lost on reload. A change with --permanent is written to disk but does not affect the running firewall until a reload .
  • The reload cycle is the synchronization mechanism. firewall-cmd --reload discards runtime changes and loads the permanent configuration. firewall-cmd --runtime-to-permanent copies the runtime configuration to disk .
  • Interface assignments are persistent. Changing an interface’s zone with --change-interface is stored in NetworkManager and survives reboots without the --permanent flag .

Remember: firewalld is a trust model, not a rule list. The zone is the trust boundary. The service is the allowed traffic. The runtime configuration is the active state; the permanent configuration is the saved state. The reload command is the bridge between them. Without the reload, the permanent configuration is just a file on disk.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!