38

We have an Ubuntu 12.04 server with httpd on port 80 and we want to limit:

  • the maximum connections per IP address to httpd to 10
  • the maximum new connections per second to httpd to 150

How can we do this with iptables?

3 Answers 3

52
+50
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 --connlimit-mask 32 -j REJECT --reject-with tcp-reset  

This will reject connections above 15 from one source IP.

iptables -A INPUT -m state --state RELATED,ESTABLISHED -m limit --limit 150/second --limit-burst 160 -j ACCEPT  

In this 160 new connections (packets really) are allowed before the limit of 150 NEW connections (packets) per second is applied.

7
  • 1
    Can the above be set up to work on all ports, not just port 80? Mar 7, 2015 at 6:00
  • 1
    Are you sure this is per IP?
    – LatinSuD
    Jun 9, 2015 at 6:41
  • 2
    To set this rule for all ports, just remove the --dport 80.
    – Dan Pritts
    Jun 11, 2015 at 15:11
  • 5
    The second rule does NOT work on "new connections". It explicitly affects existing ("ESTABLISHED") connections. To do new connections, you would want --state NEW. You might also consider using -m conntrack --ctstate in place of -m state --state. conntrack is new and improved vs. state.
    – Dan Pritts
    Jun 11, 2015 at 15:14
  • 3
    the comment above for adding the 2nd rule to NEW connections - do not do that - it effectively turns your INPUT chain into a default accept !!! Apr 23, 2017 at 5:40
10

You want the following rules in your iptables to answer both requirements in your question:

iptables -t filter -I INPUT -p tcp --dport 80 -j ACCEPT

iptables -t filter -I INPUT -p tcp --dport 80 -m state \
  --state RELATED,ESTABLISHED -j ACCEPT

# Adjust "--connlimit-above NN" to limit the maximum connections per IP
#   that you need.
iptables -t filter -I INPUT -p tcp --syn --dport 80 -m connlimit \
  --connlimit-above 10 --connlimit-mask 32 -j DROP

# Adjust "--connlimit-above NNN" to the maximum total connections you
#   want your web server to support
iptables -t filter -I INPUT -p tcp --syn --dport 80 -m connlimit \
  --connlimit-above 150 -j DROP

Because we are using -I (as per the OP request) we have to do them in reverse order so 'read' them from the bottom up.

I also suggest considering --connlimit-mask NN change from 32 to 24. This will limit a full Class-C network (max 256 IP addresses in the same range) to 10 connections. You could also use any other classless number like 22 or 30 depending on how you think your service might be used.

Also depending on how you want the client to behave, you might want to use "-j REJECT --reject-with tcp-reset" instead of "-j DROP" in the two rules above, or even only in the 150 connections max rule.

If you REJECT the connection the browser or software using port 80 will show a "not available" status immediately, but the DROP option will cause the client to wait and retry a few times before reporting the site as not available. I tend to lean to the DROP myself as it behaves more like a bad connection than an offline server.

Also, if the connection limit drops back down below 150 (or 10) while it is still retrying, then it will finally get through to your server.

The REJECT option will cause a fraction less traffic to your site however, as DROP will cause it to send additional packets while it retries. Probably not all that relevant.

If on the other hand your port 80 traffic is part of a cluster then REJECT will tell the cluster controller that it's down and to stop sending traffic to it for the duration of it's retry timeout.

The RELATED,ESTABLISHED rule is there under the assumption your default rule is to block all traffic (iptables -t filter -P INPUT DROP). This just accepts futher packets belonging to accepted connections.

Also --syn tells it to pay attention to (or count) the packets that set up a TCP connection.

3
  • Thanks for walking through the minutia of these commands.
    – txyoji
    Feb 19, 2016 at 20:30
  • Can i get --connlimit-mask to only block that specific IP address and not an entire range ?
    – Analog
    Feb 26, 2016 at 16:55
  • The --connlimit-mask 32 is a single address limit. Ie, it is like a /32 netmask. Anything less, like 24 is like a /24 netmask, ignoring the lower 8 bits. Feb 26, 2016 at 20:39
5

You need to use the connlimit modules which allows you to restrict the number of parallel TCP connections to a server per client IP address (or address block).

/sbin/iptables -I INPUT -p tcp --syn --dport 80 -m connlimit \
      --connlimit-above 10 -j DROP
2
  • I updated your answer, i hope it's still OK (why is "--syn " needed?). +And how about the "The maximum connection per second (port 80, tcp) to 150"? Thank you! Jun 26, 2014 at 12:39
  • --syn means that the rule only looks at TCP packets with the syn flag - which means new connections. You could do roughly the same with -m state --state NEW, but this is probably faster.
    – Dan Pritts
    Jun 3, 2015 at 15:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .