LFCS 106 ๐ง Firewalld โ Concepts
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
| Zone | Trust Level | Default Services |
|---|---|---|
public | Untrusted | ssh, dhcpv6-client |
trusted | Fully trusted | All traffic allowed |
drop | Untrusted | All incoming dropped silently |
block | Untrusted | All incoming rejected with ICMP |
home | Mostly trusted | ssh, mdns, samba-client |
work | Mostly trusted | ssh, dhcpv6-client |
Commands
| Command | Purpose |
|---|---|
firewall-cmd --state | Check if firewalld is running |
firewall-cmd --get-default-zone | Show default zone |
firewall-cmd --list-all | Show all settings for default zone |
firewall-cmd --add-service=<svc> | Allow service in runtime |
firewall-cmd --add-service=<svc> --permanent | Allow service permanently |
firewall-cmd --add-port=<port>/<proto> | Open raw port |
firewall-cmd --reload | Reload permanent config into runtime |
firewall-cmd --runtime-to-permanent | Save runtime to permanent |
Configuration Files
| Path | Purpose |
|---|---|
/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
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Rule disappears after reboot | Added without --permanent | Add --permanent and --reload |
Rule not active after --permanent | No reload executed | firewall-cmd --reload |
| Cannot connect after adding service | Service added to wrong zone | Check --get-active-zones |
| SSH connection lost | Panic mode enabled or zone changed | Use console access; --panic-off |
| Zone assignment not persistent | Used --permanent with --change-interface | Interface 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
| Item | Value |
|---|---|
| Daemon | firewalld |
| Default zone | public |
| Zone purpose | Trust level for interfaces |
| Service purpose | Named set of ports/protocols |
| Runtime config | Active, lost on reload |
| Permanent config | Written to disk, requires reload |
| Add permanent | --permanent flag |
| Apply permanent | firewall-cmd --reload |
| Save runtime | firewall-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 onlysshanddhcpv6-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
--permanentis active immediately but is lost on reload. A change with--permanentis written to disk but does not affect the running firewall until a reload . - The reload cycle is the synchronization mechanism.
firewall-cmd --reloaddiscards runtime changes and loads the permanent configuration.firewall-cmd --runtime-to-permanentcopies the runtime configuration to disk . - Interface assignments are persistent. Changing an interface’s zone with
--change-interfaceis stored in NetworkManager and survives reboots without the--permanentflag .
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.
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!