Firewalld Advanced
Firewalld is the default firewall management tool for RHEL/CentOS-based distributions. This article dives deep into Rich Rules, Direct Rules, custom zones, port forwarding, IP masquerading, ipsets, and other advanced features to help you build fine-grained network security policies.
Rich Rules
Section titled “Rich Rules”Rich Rules provide more powerful and flexible rule definitions than simple --add-port/--add-service, allowing fine-grained control based on source addresses, destination addresses, ports, and more.
Rich Rules Syntax Structure
Section titled “Rich Rules Syntax Structure”rule [family="ipv4|ipv6"] [source address="address[/mask]" [invert="true"]] [destination address="address[/mask]" [invert="true"]] [service name="service" | port port="port" protocol="tcp|udp" | protocol value="protocol" | icmp-block name="type" | masquerade | forward-port port="port" protocol="tcp|udp" to-port="port" [to-addr="address"]] [log [prefix="prefix"] [level="level"] [limit value="rate"]] [audit] [accept|reject|drop]Common Rich Rules Examples
Section titled “Common Rich Rules Examples”Allow a Specific IP to Access a Specific Port
Section titled “Allow a Specific IP to Access a Specific Port”sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="3306" protocol="tcp" accept'Drop All Traffic from a Specific IP
Section titled “Drop All Traffic from a Specific IP”sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.50" drop'Allow a Subnet to Access SSH
Section titled “Allow a Subnet to Access SSH”sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept'Reject HTTP from a Specific IP and Log It
Section titled “Reject HTTP from a Specific IP and Log It”sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" service name="http" log prefix="HTTP-BLOCKED: " level="warning" limit value="5/m" reject'Allow a Specific IP Range to Access Multiple Ports
Section titled “Allow a Specific IP Range to Access Multiple Ports”sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port port="8080-8090" protocol="tcp" accept'Managing Rich Rules
Section titled “Managing Rich Rules”# View Rich Rules for the current zonesudo firewall-cmd --list-rich-rules
# Remove a Rich Rulesudo firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="10.0.0.50" drop'
# Apply changessudo firewall-cmd --reloadDirect Rules
Section titled “Direct Rules”Direct Rules allow you to insert rules directly into the iptables/nftables backend, suitable for complex scenarios that Rich Rules cannot handle.
Direct Rules Basic Syntax
Section titled “Direct Rules Basic Syntax”sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 <iptables rule parameters>Direct Rules Examples
Section titled “Direct Rules Examples”Rate-Limit ICMP
Section titled “Rate-Limit ICMP”sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 4 -j ACCEPTLog All Dropped Packets
Section titled “Log All Dropped Packets”sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 99 -j LOG --log-prefix "DROPPED: " --log-level 4Block a Specific MAC Address
Section titled “Block a Specific MAC Address”sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -m mac --mac-source AA:BB:CC:DD:EE:FF -j DROPManaging Direct Rules
Section titled “Managing Direct Rules”# View all Direct Rulessudo firewall-cmd --direct --get-all-rules
# Remove a Direct Rulesudo firewall-cmd --permanent --direct --remove-rule ipv4 filter INPUT 0 -m mac --mac-source AA:BB:CC:DD:EE:FF -j DROP
sudo firewall-cmd --reloadCustom Zones
Section titled “Custom Zones”Firewalld comes with built-in zones like public, trusted, and dmz, but you can also create custom zones to meet specific requirements.
Create a Custom Zone
Section titled “Create a Custom Zone”# Create a zone named webserverssudo firewall-cmd --permanent --new-zone=webserverssudo firewall-cmd --reloadConfigure a Custom Zone
Section titled “Configure a Custom Zone”# Set zone descriptionsudo firewall-cmd --permanent --zone=webservers --set-description="Web Server Zone"
# Add allowed servicessudo firewall-cmd --permanent --zone=webservers --add-service=httpsudo firewall-cmd --permanent --zone=webservers --add-service=httpssudo firewall-cmd --permanent --zone=webservers --add-port=8080/tcp
# Bind a network interface to the custom zonesudo firewall-cmd --permanent --zone=webservers --change-interface=eth1
# Bind a source address to the zonesudo firewall-cmd --permanent --zone=webservers --add-source=10.0.1.0/24
sudo firewall-cmd --reloadView Zone Information
Section titled “View Zone Information”# View all zonessudo firewall-cmd --get-zones
# View detailed configuration for a specific zonesudo firewall-cmd --zone=webservers --list-all
# View all active zonessudo firewall-cmd --get-active-zones
# View the default zonesudo firewall-cmd --get-default-zoneDelete a Custom Zone
Section titled “Delete a Custom Zone”sudo firewall-cmd --permanent --delete-zone=webserverssudo firewall-cmd --reloadPort Forwarding
Section titled “Port Forwarding”Port forwarding redirects traffic arriving at one port to another port or another host.
Local Port Forwarding
Section titled “Local Port Forwarding”Forward local port 80 to port 8080:
sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080sudo firewall-cmd --reloadForward to a Remote Host
Section titled “Forward to a Remote Host”Forward traffic on local port 80 to port 8080 on another host:
# Masquerade must be enabled firstsudo firewall-cmd --permanent --add-masquerade
# Add the port forwarding rulesudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=192.168.1.100sudo firewall-cmd --reloadPort Forwarding with Rich Rules
Section titled “Port Forwarding with Rich Rules”sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" forward-port port="443" protocol="tcp" to-port="8443" to-addr="192.168.1.100"'sudo firewall-cmd --reloadView Port Forwarding Rules
Section titled “View Port Forwarding Rules”sudo firewall-cmd --list-forward-portsRemove a Port Forwarding Rule
Section titled “Remove a Port Forwarding Rule”sudo firewall-cmd --permanent --remove-forward-port=port=80:proto=tcp:toport=8080sudo firewall-cmd --reloadIP Masquerading
Section titled “IP Masquerading”Masquerading is a special form of SNAT (Source Network Address Translation), typically used to allow internal network machines to access the internet through the firewall host.
Enable Masquerade
Section titled “Enable Masquerade”sudo firewall-cmd --permanent --add-masqueradesudo firewall-cmd --reloadCheck Masquerade Status
Section titled “Check Masquerade Status”sudo firewall-cmd --query-masqueradeEnable Masquerade for a Specific Zone
Section titled “Enable Masquerade for a Specific Zone”sudo firewall-cmd --permanent --zone=internal --add-masqueradesudo firewall-cmd --reloadLimit Masquerade Scope with Rich Rules
Section titled “Limit Masquerade Scope with Rich Rules”Enable NAT only for a specific source subnet:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" masquerade'sudo firewall-cmd --reloadEnable Kernel IP Forwarding
Section titled “Enable Kernel IP Forwarding”Both masquerading and port forwarding require kernel IP forwarding:
# Enable temporarilysudo sysctl -w net.ipv4.ip_forward=1
# Enable permanentlyecho 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/ip_forward.confsudo sysctl -p /etc/sysctl.d/ip_forward.confIPSet allows you to define collections of IP addresses and reference them in firewall rules, making it ideal for managing large numbers of IPs.
Create an IPSet
Section titled “Create an IPSet”# Create an IPv4 address setsudo firewall-cmd --permanent --new-ipset=blacklist --type=hash:ip
# Create a set that supports subnetssudo firewall-cmd --permanent --new-ipset=trusted_nets --type=hash:netAdd IPs to an IPSet
Section titled “Add IPs to an IPSet”sudo firewall-cmd --permanent --ipset=blacklist --add-entry=203.0.113.50sudo firewall-cmd --permanent --ipset=blacklist --add-entry=198.51.100.0/24sudo firewall-cmd --permanent --ipset=trusted_nets --add-entry=10.0.0.0/8sudo firewall-cmd --reloadBulk Import from a File
Section titled “Bulk Import from a File”Create an IP list file:
cat <<EOF > /tmp/blacklist.txt203.0.113.10203.0.113.20198.51.100.0/24EOFImport into the IPSet:
sudo firewall-cmd --permanent --ipset=blacklist --add-entries-from-file=/tmp/blacklist.txtsudo firewall-cmd --reloadUse IPSets in Rich Rules
Section titled “Use IPSets in Rich Rules”# Block all IPs in the blacklistsudo firewall-cmd --permanent --add-rich-rule='rule source ipset="blacklist" drop'
# Allow IPs in the whitelist to access SSHsudo firewall-cmd --permanent --add-rich-rule='rule source ipset="trusted_nets" service name="ssh" accept'
sudo firewall-cmd --reloadManage IPSets
Section titled “Manage IPSets”# View all IPSetssudo firewall-cmd --get-ipsets
# View IPSet entriessudo firewall-cmd --ipset=blacklist --get-entries
# Remove an entrysudo firewall-cmd --permanent --ipset=blacklist --remove-entry=203.0.113.50
# Delete an IPSetsudo firewall-cmd --permanent --delete-ipset=blacklistsudo firewall-cmd --reloadLogging
Section titled “Logging”Firewall logging is essential for security auditing and troubleshooting.
Log with Rich Rules
Section titled “Log with Rich Rules”# Log rejected SSH connectionssudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="ssh" log prefix="SSH-ACCESS: " level="notice" limit value="3/m" accept'
# Log dropped trafficsudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" log prefix="FW-DROP: " level="warning" limit value="10/m" drop'
sudo firewall-cmd --reloadLog Levels
Section titled “Log Levels”| Level | Description |
|---|---|
emerg | Emergency |
alert | Alert |
crit | Critical |
error | Error |
warning | Warning |
notice | Notice |
info | Informational |
debug | Debug |
Rate-Limit Logging
Section titled “Rate-Limit Logging”limit value prevents log flooding that could fill up disk space:
| Rate Format | Description |
|---|---|
1/s | 1 entry per second |
5/m | 5 entries per minute |
10/h | 10 entries per hour |
100/d | 100 entries per day |
View Firewall Logs
Section titled “View Firewall Logs”# View via journalctlsudo journalctl -k | grep "FW-DROP"
# View via dmesgsudo dmesg | grep "SSH-ACCESS"
# View messages logsudo grep "FW-DROP" /var/log/messagesConfigure LogDenied
Section titled “Configure LogDenied”Firewalld can globally log all denied connections:
# View current settingsudo firewall-cmd --get-log-denied
# Enable (options: all, unicast, broadcast, multicast, off)sudo firewall-cmd --set-log-denied=allHands-On: Building a Web Server Firewall Policy
Section titled “Hands-On: Building a Web Server Firewall Policy”The following example configures a complete firewall policy for a web server, including custom zones, IPSet whitelists, port forwarding, and logging.
-
Create an admin IPSet:
Terminal window sudo firewall-cmd --permanent --new-ipset=admin_ips --type=hash:ipsudo firewall-cmd --permanent --ipset=admin_ips --add-entry=192.168.1.10sudo firewall-cmd --permanent --ipset=admin_ips --add-entry=192.168.1.11 -
Configure basic public zone rules:
Terminal window # Allow HTTP and HTTPSsudo firewall-cmd --permanent --add-service=httpsudo firewall-cmd --permanent --add-service=https# Remove default SSH service (will be restricted via Rich Rule)sudo firewall-cmd --permanent --remove-service=ssh -
Add Rich Rules:
Terminal window # Allow SSH only from admin IPssudo firewall-cmd --permanent --add-rich-rule='rule source ipset="admin_ips" service name="ssh" accept'# Log and drop other SSH attemptssudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="ssh" log prefix="SSH-DENIED: " level="warning" limit value="3/m" drop'# Log HTTP access (sampled)sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" service name="http" log prefix="HTTP: " level="info" limit value="1/m" accept' -
Configure port forwarding (HTTP to backend application):
Terminal window sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080 -
Apply and verify:
Terminal window sudo firewall-cmd --reloadsudo firewall-cmd --list-allsudo firewall-cmd --list-rich-rules
By leveraging Rich Rules, IPSets, port forwarding, and logging, you can build fine-grained firewall security policies that effectively defend against network threats while keeping services running smoothly.