How to Whitelist Specific IPs in firewalld While Blocking All Others: A Practical Guide for Linux Admins


1 views

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:

  1. Ensure no conflicting rules exist in other zones
  2. Verify interface assignments with firewall-cmd --get-active-zones
  3. Check for direct rules that might bypass zone policies
  4. Confirm changes were made permanent with --permanent flag