Back to Learn

How to Rate Limit with IPTables | NOC.org

Understanding Rate Limiting with IPTables

Rate limiting is a critical firewall technique that restricts the number of connections a client can make to your server within a given time period. IPTables, the standard Linux firewall utility, provides several mechanisms for implementing rate limits, with the recent module being one of the most flexible and widely used approaches. Rate limiting is essential for protecting against brute force attacks, DDoS attacks, and general abuse of your server's resources.

Without rate limiting, an attacker can attempt thousands of SSH login combinations per minute, flood your web server with requests, or overwhelm your services with connection attempts. The IPTables recent module tracks source IP addresses and their connection timestamps, allowing you to create rules that limit how many new connections an IP can establish within a specified window.

The Recent Module

The recent module (-m recent) maintains a list of IP addresses along with timestamps for each connection attempt. This allows you to create rules based on the frequency of connections from a particular source. The module stores its data in /proc/net/xt_recent/, and each named list you create appears as a file in that directory.

Key Flags

  • --set — Adds the source IP address to the named list. If the address is already in the list, the timestamp is updated. This flag always returns true, so it does not affect whether the packet matches the rule.
  • --rcheck — Checks whether the source IP address is in the list. Returns true if the address is found. Does not update the timestamp.
  • --update — Like --rcheck, but also updates the timestamp if the address is found. This means the rate limit window resets with each new connection attempt, making it harder for attackers to work around the limit by spacing their attempts.
  • --remove — Removes the source IP from the list if present.
  • --name — Specifies the name of the list to use. You can maintain multiple separate lists for different services (e.g., one for SSH, one for HTTP).
  • --seconds — Used with --rcheck or --update to only match addresses that have been seen within the specified number of seconds.
  • --hitcount — Used with --rcheck or --update to only match addresses that have been seen at least the specified number of times within the --seconds window.

Rate Limiting SSH Connections

SSH brute force attacks are one of the most common threats facing any internet-facing Linux server. Attackers use automated tools to try thousands of username and password combinations. Rate limiting SSH connections is one of the most effective countermeasures, alongside other SSH hardening techniques.

Basic SSH Rate Limit

The following ruleset limits new SSH connections to 4 attempts per 60 seconds per IP address:

# Create the tracking rule: add source IP to the SSH list for new connections
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH

# Drop connections that exceed 4 attempts in 60 seconds
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP

# Allow SSH connections that pass the rate limit
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

How this works step by step:

  1. When a new TCP connection to port 22 arrives, the first rule adds the source IP to the "SSH" list (or updates its timestamp if already present).
  2. The second rule checks whether this IP has made 4 or more connection attempts in the last 60 seconds. If yes, the packet is dropped.
  3. The third rule accepts SSH connections that have not exceeded the limit.

With --update, each dropped attempt also resets the timer, so an attacker who continues to send packets will remain blocked. If they stop, their entry will age out after 60 seconds of inactivity.

SSH Rate Limit with Logging

Adding logging helps you monitor and audit rate-limited connections:

# Track new SSH connections
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH

# Log rate-limited connections before dropping
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name SSH -j LOG --log-prefix "SSH-RATELIMIT: " --log-level 4

# Drop the rate-limited connections
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP

# Accept connections within the limit
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

Log entries will appear in /var/log/messages or /var/log/syslog with the "SSH-RATELIMIT:" prefix, making them easy to filter and analyze.

Rate Limiting HTTP/HTTPS Connections

Rate limiting HTTP connections is useful for protecting web servers from automated scanners, scrapers, and certain types of DDoS attacks. However, HTTP rate limiting requires more careful tuning because legitimate users often make many concurrent connections to load page resources.

Basic HTTP Rate Limit

# Track new HTTP connections
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --set --name HTTP

# Drop connections exceeding 50 new connections per 10 seconds
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 10 --hitcount 50 --name HTTP -j DROP

# Accept connections within the limit
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT

# Same rules for HTTPS (port 443)
iptables -A INPUT -p tcp --dport 443 -m state --state NEW -m recent --set --name HTTPS
iptables -A INPUT -p tcp --dport 443 -m state --state NEW -m recent --update --seconds 10 --hitcount 50 --name HTTPS -j DROP
iptables -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT

The limits above (50 connections per 10 seconds) are generous enough for normal browsing but will catch aggressive automated tools. Adjust the values based on your server's expected traffic patterns.

Using the hashlimit Module for HTTP

For more sophisticated HTTP rate limiting, the hashlimit module offers finer-grained control:

# Limit new HTTP connections to 50 per minute per source IP
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m hashlimit --hashlimit-above 50/minute --hashlimit-burst 60 --hashlimit-mode srcip --hashlimit-name http_limit -j DROP

# Same for HTTPS
iptables -A INPUT -p tcp --dport 443 -m state --state NEW -m hashlimit --hashlimit-above 50/minute --hashlimit-burst 60 --hashlimit-mode srcip --hashlimit-name https_limit -j DROP

The hashlimit module uses a token bucket algorithm, which is more flexible than the recent module for high-traffic scenarios. The --hashlimit-burst parameter allows short bursts of connections above the limit, which accommodates normal browsing behavior where a browser opens multiple connections simultaneously to load page resources.

The hitcount and seconds Parameters

Choosing the right values for --hitcount and --seconds is critical for effective rate limiting that does not disrupt legitimate users:

hitcount

The --hitcount parameter specifies the threshold number of connection attempts. Note that there is a maximum value for hitcount, controlled by the kernel parameter ip_plist_tot (default is usually 20). If you need a higher hitcount, you can increase this limit:

# Check current limit
cat /proc/sys/net/netfilter/xt_recent/ip_pkt_list_tot

# Increase the limit (add to /etc/sysctl.conf for persistence)
echo 50 > /proc/sys/net/netfilter/xt_recent/ip_pkt_list_tot

seconds

The --seconds parameter defines the time window in seconds. Common configurations include:

  • SSH: 3-5 attempts per 60 seconds — tight enough to stop brute force while allowing legitimate typos
  • HTTP/HTTPS: 30-100 per 10 seconds — allows normal browsing while blocking scanners
  • SMTP: 5-10 per 60 seconds — prevents spam relay attempts
  • DNS: 20-50 per second — prevents DNS amplification abuse

Practical Examples

Protecting Multiple Services

# SSH: 4 attempts per 60 seconds
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP

# FTP: 5 attempts per 60 seconds
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -m recent --set --name FTP
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 --name FTP -j DROP

# SMTP: 10 connections per 60 seconds
iptables -A INPUT -p tcp --dport 25 -m state --state NEW -m recent --set --name SMTP
iptables -A INPUT -p tcp --dport 25 -m state --state NEW -m recent --update --seconds 60 --hitcount 10 --name SMTP -j DROP

Whitelisting Trusted IPs

Rate limits should not apply to trusted IPs such as your own office, monitoring systems, or partner servers:

# Whitelist trusted IPs before rate limiting rules
iptables -A INPUT -p tcp --dport 22 -s 203.0.113.10 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -s 198.51.100.0/24 -j ACCEPT

# Then apply rate limiting for everyone else
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

Viewing and Testing Rules

After implementing rate limiting rules, verify they are in place and working correctly:

# List all rules with line numbers
iptables -L -n --line-numbers

# List rules with packet and byte counters
iptables -L -n -v

# Check the recent module's tracked IPs
cat /proc/net/xt_recent/SSH

# Test SSH rate limiting (from a test machine)
for i in $(seq 1 10); do ssh -o ConnectTimeout=2 user@server.com; done

The counters in iptables -L -n -v show how many packets have matched each rule, which helps you confirm that rate limiting is actively working and understand how much traffic it is blocking.

Difference Between --rcheck and --update

The choice between --rcheck and --update affects how the rate limit behaves:

  • --rcheck: Checks the list without updating timestamps. The time window is based on the initial entries. If an IP makes 4 connections in the first 10 seconds and then continues trying, the rate limit will expire after 60 seconds from the first connection, regardless of ongoing attempts.
  • --update: Checks the list and updates timestamps. The time window slides forward with each attempt. An IP that keeps trying will remain blocked as long as it continues to exceed the rate, because each new packet resets the window. This is the recommended choice for security purposes.

Persisting Rate Limit Rules

IPTables rules are lost on reboot unless you save them. Use iptables-save and iptables-restore to persist your configuration:

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

# Restore rules (typically done on boot via systemd or init script)
iptables-restore < /etc/iptables/rules.v4

# On Debian/Ubuntu, install iptables-persistent
apt install iptables-persistent
netfilter-persistent save

# On RHEL/CentOS
service iptables save

For more on creating a complete firewall configuration, see our guide on creating default blocks with IPTables.

Summary

Rate limiting with IPTables is an essential technique for protecting your server against brute force attacks, automated scanners, and connection flooding. The recent module provides a straightforward way to track and limit connections per source IP, while the hashlimit module offers more sophisticated controls for high-traffic services. Always whitelist trusted IPs, start with conservative limits, and monitor your logs to fine-tune thresholds. Combined with proper SSH hardening and default firewall policies, rate limiting creates a robust first line of defense for your Linux servers.

Need help protecting your infrastructure? Explore NOC.org plans to get started.

Improve Your Websites Speed and Security

14 days free trial. No credit card required.