Docs / Security / How to Implement Rate Limiting at the OS Level with iptables

How to Implement Rate Limiting at the OS Level with iptables

By Admin · Mar 15, 2026 · Updated Apr 23, 2026 · 275 views · 3 min read

Rate limiting at the OS level with iptables provides a powerful defense against brute-force attacks, DDoS attempts, and resource abuse before traffic even reaches your application. Unlike application-level rate limiting, iptables operates at the kernel level with minimal overhead.

Basic Connection Rate Limiting

# Limit new SSH connections to 3 per minute per IP
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
  -m recent --set --name SSH
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
  -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP

# Limit new HTTP connections to 50 per second per IP
sudo iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j DROP
sudo iptables -A INPUT -p tcp --dport 443 -m connlimit --connlimit-above 50 -j DROP

Using the hashlimit Module

# hashlimit is more flexible than the limit module
# It tracks limits per source IP automatically

# Limit HTTP requests to 100/minute per IP
sudo iptables -A INPUT -p tcp --dport 80 -m hashlimit \
  --hashlimit-above 100/min --hashlimit-mode srcip \
  --hashlimit-name http_limit -j DROP

# Limit SSH to 3/minute per IP
sudo iptables -A INPUT -p tcp --dport 22 -m hashlimit \
  --hashlimit-above 3/min --hashlimit-mode srcip \
  --hashlimit-name ssh_limit -j DROP

# Limit ICMP (ping) to prevent ping floods
sudo iptables -A INPUT -p icmp --icmp-type echo-request -m hashlimit \
  --hashlimit-above 1/sec --hashlimit-mode srcip \
  --hashlimit-name ping_limit -j DROP

SYN Flood Protection

# Enable SYN cookies (kernel level)
echo 1 | sudo tee /proc/sys/net/ipv4/tcp_syncookies

# Limit SYN packets
sudo iptables -A INPUT -p tcp --syn -m hashlimit \
  --hashlimit-above 100/sec --hashlimit-mode srcip \
  --hashlimit-name syn_limit -j DROP

# Make SYN cookies persistent
echo "net.ipv4.tcp_syncookies=1" | sudo tee -a /etc/sysctl.d/99-security.conf

Connection Limits

# Limit total concurrent connections from a single IP
sudo iptables -A INPUT -p tcp --dport 80 -m connlimit \
  --connlimit-above 100 --connlimit-mask 32 -j REJECT

# Limit concurrent connections to SSH
sudo iptables -A INPUT -p tcp --dport 22 -m connlimit \
  --connlimit-above 3 --connlimit-mask 32 -j DROP

Logging Rate-Limited Traffic

# Log dropped traffic for analysis
sudo iptables -A INPUT -p tcp --dport 22 -m hashlimit \
  --hashlimit-above 3/min --hashlimit-mode srcip \
  --hashlimit-name ssh_log -j LOG --log-prefix "SSH-RATELIMIT: " --log-level 4

# Then drop
sudo iptables -A INPUT -p tcp --dport 22 -m hashlimit \
  --hashlimit-above 3/min --hashlimit-mode srcip \
  --hashlimit-name ssh_drop -j DROP

# View logs
grep "SSH-RATELIMIT" /var/log/kern.log

Saving Rules

# Save iptables rules permanently
sudo apt install iptables-persistent
sudo netfilter-persistent save

# Or manually
sudo iptables-save | sudo tee /etc/iptables/rules.v4
sudo ip6tables-save | sudo tee /etc/iptables/rules.v6

nftables Alternative

# nftables is the modern replacement for iptables
# Rate limiting in nftables:
sudo nft add table inet filter
sudo nft add chain inet filter input '{ type filter hook input priority 0; }'
sudo nft add rule inet filter input tcp dport 22 ct state new \
  meter ssh_meter '{ ip saddr limit rate 3/minute }' accept
sudo nft add rule inet filter input tcp dport 22 ct state new drop

Was this article helpful?