When hardening Linux servers, many admins need to implement strict IP-based access controls where only explicitly whitelisted IPs can connect. The naive approach of adding multiple --add-rich-rule
statements with inverse logic creates a logical conflict that effectively blocks all traffic.
Instead of using negative rich rules, firewalld provides a proper whitelisting mechanism through zone sources. Here's how to implement it correctly:
# Create a new zone for strict access control
firewall-cmd --permanent --new-zone=restricted_access
# Add your whitelisted IPs (space-separated for multiple IPs)
firewall-cmd --permanent --zone=restricted_access --add-source=192.168.56.120
firewall-cmd --permanent --zone=restricted_access --add-source=192.168.56.105
# Only allow specific services (SSH in this example)
firewall-cmd --permanent --zone=restricted_access --add-service=ssh
# Assign the zone to your network interface
firewall-cmd --permanent --zone=restricted_access --change-interface=eth0
# Reload to apply changes
firewall-cmd --reload
To confirm your settings:
firewall-cmd --zone=restricted_access --list-all
Should show output like:
restricted_access (active)
interfaces: eth0
sources: 192.168.56.120 192.168.56.105
services: ssh
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:
For more granular control with multiple exceptions, rich rules can be combined with the 'accept' action:
# First block all traffic
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" drop'
# Then whitelist specific IPs
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.56.120" accept'
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.56.105" accept'
# Reload to apply
firewall-cmd --reload
1. Order matters: Rules are processed top-down, so place accept rules before drop rules
2. Lockout risk: Always test from a whitelisted IP or have console access
3. Persistence: Use --permanent
flag or rules won't survive reboots
When securing a Linux server using firewalld's public zone, many administrators want to implement strict IP whitelisting - allowing only specific addresses while blocking all others. The naive approach of using multiple --add-rich-rule
commands with negative matches creates an "AND" logic that inadvertently blocks everything:
# This creates an accidental "drop all" effect
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source not address="192.168.56.120" drop'
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source not address="192.168.56.105" drop'
The correct approach involves creating a dedicated zone for whitelisted IPs. Here's how to implement it properly:
# Create a new zone
firewall-cmd --permanent --new-zone=secure_access
# Add trusted IP sources (space-separated list)
firewall-cmd --permanent --zone=secure_access --add-source=192.168.56.120/32
firewall-cmd --permanent --zone=secure_access --add-source=192.168.56.105/32
# Assign services/ports to the zone
firewall-cmd --permanent --zone=secure_access --add-service=ssh
firewall-cmd --permanent --zone=secure_access --add-port=6000/tcp
# Set the default public zone to reject all traffic
firewall-cmd --permanent --zone=public --set-target=DROP
# Apply changes
firewall-cmd --reload
After configuration, verify the setup with these commands:
# Check zone configuration
firewall-cmd --zone=secure_access --list-all
# Test connectivity from allowed/blocked IPs
ping -c 1 server_ip # From whitelisted IP should work
ping -c 1 server_ip # From non-whitelisted IP should fail
For managing larger IP whitelists, use firewalld's ipset feature:
# Create a new ipset
firewall-cmd --permanent --new-ipset=whitelist --type=hash:ip
# Add multiple IPs to the ipset
firewall-cmd --permanent --ipset=whitelist --add-entry=192.168.56.120
firewall-cmd --permanent --ipset=whitelist --add-entry=192.168.56.105
# Create a rich rule using the ipset
firewall-cmd --permanent --zone=public --add-rich-rule='rule source ipset=whitelist accept'
firewall-cmd --permanent --zone=public --set-target=DROP
# Apply changes
firewall-cmd --reload
If you encounter problems where unauthorized IPs can still access services:
- Ensure no conflicting rules exist in other zones
- Verify interface assignments with
firewall-cmd --get-active-zones
- Check for direct rules that might bypass zone policies
- Confirm changes were made permanent with
--permanent
flag