🛡️ firewalld Advanced Configuration
Rich Rules In-Depth
Rich Rules are firewalld's most powerful feature — they can combine ports, sources, actions, logging, and other conditions in a single rule.
bash
# Rich rule syntax structure
firewall-cmd --add-rich-rule='
rule family="ipv4"
source address="192.168.1.0/24"
port port="3306" protocol="tcp"
accept'
# Reject rule with logging
firewall-cmd --add-rich-rule='
rule family="ipv4"
source address="10.0.0.100"
port port="22" protocol="tcp"
log prefix="SSH-BLOCK: " level="info"
reject'
# Rate limiting rule (anti-brute force)
firewall-cmd --add-rich-rule='
rule family="ipv4"
source address="192.168.1.0/24"
port port="22" protocol="tcp"
accept
limit value="5/m"'
# Port forwarding (DNAT)
firewall-cmd --add-rich-rule='
rule family="ipv4"
source address="192.168.1.0/24"
forward-port port="8080" protocol="tcp"
to-port="80" to-addr="10.0.0.50"'
# View all rich rules
firewall-cmd --list-rich-rules
# Add permanently (persists across reboots)
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port port="9090" protocol="tcp" accept'
firewall-cmd --reloadPort Forwarding
bash
# First enable IP forwarding (masquerading)
firewall-cmd --permanent --add-masquerade
firewall-cmd --reload
# Forward external port 8080 to internal 10.0.0.50:80
firewall-cmd --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=10.0.0.50
firewall-cmd --permanent --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=10.0.0.50
# Forward external port 3306 to internal database server
firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="192.168.1.0/24"
forward-port port="3306" protocol="tcp"
to-port="3306" to-addr="10.0.0.100"'
# Verify forwarding rules
firewall-cmd --list-forward-ports
# Test from outside
curl http://your-server:8080
# Should see content from internal 10.0.0.50:80Integration with Other Services
bash
# firewalld automatically loads predefined rules for services
# View what ports a service defines
cat /etc/firewalld/services/ssh.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>SSH</short>
<port protocol="tcp" port="22"/>
</service>
# Create a custom service
cat > /etc/firewalld/services/myapp.xml << 'EOF'
xml version="1.0" encoding="utf-8"?>
MyApp
My Custom Application
EOF
# Now you can use the service name directly
firewall-cmd --permanent --add-service=myapp
firewall-cmd --reload
# Docker and firewalld conflicts
# Docker bypasses firewalld and directly manipulates iptables
# Solution: Set in /etc/docker/daemon.json
# { "iptables": false }
# Then manually manage Docker's port forwarding