How to Configure IP Whitelisting with iptables: Allow Specific IP Ranges for Inbound/Outbound Traffic


2 views

When securing a Linux server, implementing IP whitelisting through iptables is one of the most effective ways to control network access. The basic principle is simple: explicitly allow connections from/to specific IP ranges while dropping everything else by default.

If you're starting fresh or want to clear existing rules, begin with:

iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X

The foundation of whitelisting is setting DROP policies:

iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

Always permit local traffic:

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

For inbound connections (users connecting to your server):

# Allow single IP
iptables -A INPUT -p tcp -s 192.168.1.100 --dport 22 -j ACCEPT

# Allow IP range (CIDR notation)
iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 80 -j ACCEPT

# Allow multiple services from specific IP
iptables -A INPUT -p tcp -s 198.51.100.55 -m multiport --dports 22,80,443 -j ACCEPT

For outbound connections (server connecting to other services):

# Allow server to connect to specific IPs
iptables -A OUTPUT -p tcp -d 93.184.216.34 --dport 443 -j ACCEPT

# Allow DNS resolution
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

# Allow NTP time synchronization
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT

To maintain existing connections:

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

On Debian-based systems, persist your rules:

iptables-save > /etc/iptables.rules
apt install iptables-persistent  # If not already installed
netfilter-persistent save

Check your configuration with:

iptables -L -nv --line-numbers
iptables -L -nv --line-numbers -t nat

Here's how to allow AWS EC2 metadata service while blocking other external access:

# AWS metadata service
iptables -A OUTPUT -d 169.254.169.254 -j ACCEPT

# Allow SSH only from office IP
iptables -A INPUT -p tcp -s 203.0.113.42 --dport 22 -j ACCEPT

# Block everything else
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP

When hardening a Debian-based server, implementing proper network segmentation through IP whitelisting is crucial. The goal is to restrict both inbound (INPUT chain) and outbound (OUTPUT chain) connections to specific trusted IP ranges while dropping all other traffic.

Here's a foundational implementation that handles both directions:

# Flush existing rules
iptables -F
iptables -X

# Set default policies to DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

# Allow localhost traffic
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Whitelist inbound connections (example: 192.168.1.0/24 and 203.0.113.15/32)
iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -s 203.0.113.15/32 -j ACCEPT

# Whitelist outbound connections (example: allowed destinations)
iptables -A OUTPUT -d 91.198.174.192/32 -j ACCEPT  # example.org
iptables -A OUTPUT -d 151.101.0.0/16 -j ACCEPT    # common CDN range

# Allow established/related connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

For production environments, consider these enhancements:

# Rate limiting for SSH (allow 3 new connections per minute from whitelisted IPs)
iptables -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP

# Log dropped packets for debugging
iptables -N LOGGING
iptables -A INPUT -j LOGGING
iptables -A OUTPUT -j LOGGING
iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
iptables -A LOGGING -j DROP

# Allow ICMP only from specific monitoring hosts
iptables -A INPUT -s 198.51.100.42 -p icmp -j ACCEPT

For complex whitelists, use ipset for better performance:

# Install ipset if needed
apt-get install ipset

# Create and populate ipset
ipset create allowed_ips hash:net
ipset add allowed_ips 192.168.1.0/24
ipset add allowed_ips 203.0.113.0/28

# Reference ipset in iptables rules
iptables -A INPUT -m set --match-set allowed_ips src -j ACCEPT
iptables -A OUTPUT -m set --match-set allowed_ips dst -j ACCEPT

On Debian systems, save and restore rules:

# Save current rules
iptables-save > /etc/iptables.rules

# Install persistence package
apt-get install iptables-persistent

# For manual saving after changes
netfilter-persistent save
  • Check effective rules with: iptables -L -n -v
  • Test connectivity from whitelisted IPs before production deployment
  • Consider implementing a backup SSH access method during testing
  • Monitor system logs (/var/log/syslog) for dropped packets