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 DROPUsing 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 DROPSYN 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.confConnection 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 DROPLogging 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.logSaving 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.v6nftables 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