4.2.1. firewalld: Zones, Rules, and NAT
💡 First Principle: firewalld organizes rules using zones — named security contexts assigned to network interfaces or source addresses. An interface in the public zone gets restrictive rules; an interface in the trusted zone allows all traffic. This zone-based model lets you write rules once per zone and apply them to multiple interfaces.
Zone Management:
firewall-cmd --get-default-zone # Current default zone
firewall-cmd --get-active-zones # Zones with assigned interfaces
firewall-cmd --list-all # All rules in default zone
firewall-cmd --list-all --zone=public # Rules for specific zone
firewall-cmd --zone=public --change-interface=eth0 # Assign interface to zone
Service and Port Rules:
# Allow by service name (uses /etc/firewalld/services/ definitions)
firewall-cmd --add-service=http # Runtime: allow HTTP
firewall-cmd --add-service=https # Runtime: allow HTTPS
firewall-cmd --permanent --add-service=http # Permanent: allow HTTP
firewall-cmd --permanent --remove-service=http # Permanent: remove HTTP
# Allow by port
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --permanent --add-port=3000-3100/tcp # Port range
firewall-cmd --permanent --remove-port=8080/tcp
# Apply permanent changes immediately
firewall-cmd --reload
# List active rules
firewall-cmd --list-services
firewall-cmd --list-ports
Rich Rules — Fine-Grained Control:
# Allow SSH only from specific subnet
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept'
# Drop traffic from a specific IP
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.5" drop'
# Rate-limit connections
firewall-cmd --permanent --add-rich-rule='rule service name="http" limit value="25/m" accept'
NAT with firewalld:
# Enable masquerading (SNAT — share one public IP)
firewall-cmd --permanent --zone=public --add-masquerade
# Port forwarding (DNAT — redirect incoming port)
firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toaddr=192.168.1.5:toport=80
NAT Types:
| Type | Acronym | Direction | Purpose |
|---|---|---|---|
| Source NAT | SNAT | Outbound | Change source IP (masquerade = dynamic SNAT) |
| Destination NAT | DNAT | Inbound | Redirect to internal host/port (port forwarding) |
| Port Address Translation | PAT | Both | Multiple internal IPs share one external IP (NAT overload) |
| Masquerade | — | Outbound | Dynamic SNAT using interface's IP |
Logging with firewalld:
firewall-cmd --permanent --add-rich-rule='rule service name="ssh" log prefix="SSH-ATTEMPT " level="info" limit value="5/m" accept'
⚠️ Exam Trap (M6): The most common firewalld exam mistake is applying a --permanent change and not reloading. firewall-cmd --permanent --add-service=http writes to the permanent config but the running firewall is unchanged until firewall-cmd --reload. Conversely, firewall-cmd --add-service=http (no --permanent) takes immediate effect but won't survive a reload or reboot.
Reflection Question: You need to allow HTTPS traffic permanently and apply the change immediately without a reboot. Write the minimum number of commands to accomplish this using firewall-cmd.