I'm using iptables on Ubuntu Server. It's a web server on a VPS.
I'd like to know if I should rate-limit packets. If so, what should I rate-limit? And should I do so globally or per IP address?

I saw people suggesting this:

# Limit packet traffic on a TCP or UDP port:
iptables -A INPUT -p $proto --destination-port $port --syn -m state --state NEW -m limit --limit $lim/s --limit-burst $lb -j ACCEPT

# Limit established/related packet traffic:
iptables -A INPUT -m state --state RELATED,ESTABLISHED -m limit --limit $lim/s --limit-burst $lb -j ACCEPT

The above, a global rate-limit don't seem very useful, at least for the cases I can imagine. Is there any case where I should rate-limit globally?
I believe that a rate-limit per IP is usually better:

# Add the IP to the list:
iptables -A INPUT -p $proto --destination-port $port --syn -m state --state NEW -m recent --set --name RATELIMITED
# Drop if exceeded limit:
iptables -A INPUT -p $proto --destination-port $port --syn -m state --state NEW -m recent --update --seconds $sec --hitcount $hc --rttl --name RATELIMITED -j DROP
# Accept if inside limit:
iptables -A INPUT -p $proto --destination-port $port --syn -m state --state NEW -j ACCEPT

Additional question: Remote IPs may be spoofed. How to limit them properly?
Added another question for this:

The goal
I'm trying to mitigate the risk of some D/DoS attacks and general abuse.

How can I rate limit SSH connections with iptables?

PS: I have just opened a related question just for ICMP and it includes rate-limiting for this protocol: iptables | Types of ICMP: which ones are (potentially) harmful?


A rate limit is not a prevention but rather an invitation to DoS - especially in the flavor presented above where packets are going to be dropped if a certain rate of unauthenticated packets without state information has been exceeded. Since everybody can forge packets (including source IP addresses) at this connection state without greater effort, a new DoS attack vector leveraging your rate limit facility will arise.

A rate limit generally will only make sense if you have

  1. either a predictable hard or a soft connection limit in your configuration
  2. set the rate limit for general traffic below this limit in order to be able to set up connections for priority or administrative traffic regardless of the load

While 1. often is hard enough to determine to even bother, 2. will obviously only work if you are able to reliably differentiate "priority or administrative" traffic from the rest upon connection setup - e.g. if it is coming through a different network interface.

In other cases, it would rather reduce your system's resiliency than add to it.

| improve this answer | |
  • Hi syneticon-dj. I undestand and agree that a misconfigured firewall is another tool for a DoS attack. Thanks for the heads up! – ML-- Dec 12 '11 at 22:43
  • Per-ip or per-ip-port rate limiting also seems to make sense when defending from legitimate traffic that is too massive for one's server but whose originator isn't likely to exploit the problem you mention, say, abusive behaviour from the Bingbot or Facebook bots. – Ján Lalinský Jan 12 '19 at 11:19

The problem with -m limit is the limitation of all TCP packets whatever the source IP addresses. So, if you have a low limitation for syn packets like

-A INPUT -p tcp  --syn -m limit --limit 30/s --limit-burst 30 -j ACCEPT
-A INPUT -p tcp --syn -j DROP

only one client with the hping command line can take down your server by sending as many tcp packets with SYN flag because the limit rule will match and it will drop many packets whatever the sources IP addresses. limit does not make difference between good traffic and bad traffic. It will take the down the good incoming traffic too.

hping could be something like:

hping thetargetedhostip -p 80 -S -c 1000 -i u20000

It is better to use hashlimit to limit incoming tcp connections per IP address. The following rule will match only if 30 packets per seconds will be received reducing the number of authorized packet per IP to 15 packets per second.

-A INPUT -p tcp --syn -m hashlimit --hashlimit 15/s --hashlimit-burst 30 --hashlimit-mode srcip --hashlimit-srcmask 32 --hashlimit-name synattack -j ACCEPT 
-A INPUT -p tcp --syn -j DROP

In Fact, I am CONVINCED that many servers that are taken down today aren't taken by being out of resources during an attack but because of the limit module dropping all the incoming traffic.

| improve this answer | |

I typically limit rate limiting rules to servers that I expect to have:

  • low amounts of expected traffic
  • authentication services

For example, a hosting control panel's login page, POP3, IMAP, SSH, etc. I usually leave HTTP services wide open and only block if there is an issue.

You do not want to drop good web traffic. A link on slashdot could send you tons of traffic and with global rules, you may not realize an issue.

With regard to spoofed IPs, they cannot be blocked using this method and are typically not a concern since these rules mainly focus on limiting established TCP connections. With a spoof IP the TCP connection can never be established.

| improve this answer | |
  • Hi jeffatrackaid, thanks for your answer! I'm inclined, too, to rate-limit (globally) these types of services (SSH etc). Regarding HTTP traffic, that's why I don't intend to apply a global limit. In this question I expect to see whether there are cases when a limit per IP can be interesting. Regarding spoofed IPs (I opened a separated question on that) although connections can't be established, there's the possibility of a DoS by using a SYN flood. I remain interested in hearing how this could be mitigated. – ML-- Dec 12 '11 at 22:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.