Prevent DOS with iptables

After a recent conversation on the Ubuntu Forums I wanted to post an example of using iptables.

Of course there are several types of DOS attacks , in this post I will demonstrating the use if iptables to limit the traffic on port 80.

The goal is to keep your web server “responsive” to legitimate traffic, but to throttle back on excessive (potential DOS) traffic.

In this demonstration iptables is configured :

  1. The default policy is ACCEPT (to prevent lockout in the event of flushing the rules with iptables -F).
  2. “Legitimate” traffic is then allowed. In this example I am allowing traffic only on port 80.
  3. All other traffic is then blocked at the end of the INPUT chain (the final rule in the INPUT chain is to DROP all traffic).

The rules I will demonstrate are as follows:

First rule : Limit NEW traffic on port 80

sudo iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m limit --limit 50/minute --limit-burst 200 -j ACCEPT

Lets break that rule down into intelligible chunks.

-p tcp --dport 80 => Specifies traffic on port 80 (Normally Apache, but as you can see here I am using nginx).

-m state NEW => This rule applies to NEW connections.

-m limit --limit 50/minute --limit-burst 200 -j ACCEPT =>This is the essence of preventing DOS.

  • “--limit-burst” is a bit confusing, but in a nutshell 200 new connections (packets really) are allowed before the limit of 50 NEW connections (packets) per minute is applied.

For a more technical review of this rule, see this netfilet page. Scroll down to a bit to the “limit” section.

Second rule – Limit established traffic

This rule applies to RELATED and ESTABLISHED all traffic on all ports, but is very liberal (and thus should not affect traffic on port 22 or DNS).

If you understood the above rule, you should understand this one as well.

sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -m limit --limit 50/second --limit-burst 50 -j ACCEPT

In summary, 50 ESTABLISHED (and/or RELATED) connections (packets really) are allowed before the limit of 50 ESTABLISHED (and/or RELATED) connections (packets) per second is applied.

Do not let that rule fool you, although it seems very open, it does put some limits on your connections.

Test it for yourself, try using the first rule with and without the second rule.

Full set of rules

After the above commands, here is the complete set of rules I am testing:

iptables-save
# Generated by iptables-save v1.4.4 on --
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
# Completed on --
# Generated by iptables-save --
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
# Completed on --
# Generated by iptables-save v1.4.4 on --
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -m limit --limit 50/sec \
--limit-burst 50 -j ACCEPT
-A INPUT -p icmp -m limit --limit 1/sec -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -m state --state NEW -m limit --limit 50/min \
--limit-burst 200 -j ACCEPT
-A INPUT -j LOG
-A INPUT -j DROP
-A FORWARD -j DROP
-A OUTPUT -o lo -j ACCEPT
COMMIT
# Completed on --

This rule set is for demonstration only and is NOT a complete set of rules for a web server. Do no use this rule set unmodified on a production server.

Testing the rule set

Human interaction

Open Firefox, point it to your web page. The web page should load nice and fast.

Hit F5 repetitively, load the page as fast as you can. Your web site should remain nice and responsive.

So far, so good, we want our site to remain responsive.

Simulated DOS

Actual DOS attacks are many times faster then humans, here I will use ab.

See this link or the Apache documentation for information of ab.

Baseline, without the above 2 rules

ab -n 100 -c 10 http://bodhi's_test_server.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking bodhi's_test_server.com (be patient).....done


Server Software:        nginx
Server Hostname:       bodhi's_test_server.com
Server Port:            80

Document Path:          /
Document Length:        59786 bytes

Concurrency Level:      10
Time taken for tests:   13.174 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      6002700 bytes
HTML transferred:       5978600 bytes
Requests per second:    7.59 [#/sec] (mean)
Time per request:       1317.369 [ms] (mean)
Time per request:       131.737 [ms] (mean, across all concurrent requests)
Transfer rate:          444.98 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      122  129   2.2    128     134
Processing:  1151 1182  19.1   1177    1260
Waiting:      125  132   8.2    128     170
Total:       1280 1310  19.3   1305    1390

Percentage of the requests served within a certain time (ms)
  50%   1305
  66%   1313
  75%   1316
  80%   1321
  90%   1328
  95%   1354
  98%   1386
  99%   1390
 100%   1390 (longest request)

Notice:
Requests per second: 7.59 [#/sec] .
Total time for requests: 13 seconds .
(Data) Transfer rate: 444.98 [Kbytes/sec] .

With the above rules

First attempt:

ab -n 100 -c 10 http://bodhi's_test_server.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking bodhi's_test_server.com (be patient)...
apr_poll: The timeout specified has expired (70007)
Total of 99 requests completed

Oh no ! timed out, LOL

Second attempt (I reduced the number of requests to 90):

ab -n 90 -c 10 http://bodhi's_test_server.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking bodhi's_test_server.com (be patient).....done


Server Software:        nginx
Server Hostname:       bodhi's_test_server.com
Server Port:            80

Document Path:          /
Document Length:        59786 bytes

Concurrency Level:      10
Time taken for tests:   69.684 seconds
Complete requests:      90
Failed requests:        0
Write errors:           0
Total transferred:      5402430 bytes
HTML transferred:       5380740 bytes
Requests per second:    1.29 [#/sec] (mean)
Time per request:       7742.658 [ms] (mean)
Time per request:       774.266 [ms] (mean, across all concurrent requests)
Transfer rate:          75.71 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      123  128   4.3    127     155
Processing:  1036 6269 10081.4   1921   51059
Waiting:      125 1240 5908.7    128   49656
Total:       1159 6396 10081.1   2044   51186

Percentage of the requests served within a certain time (ms)
  50%   2044
  66%   2981
  75%   5478
  80%   7047
  90%  20358
  95%  27356
  98%  48218
  99%  51186
 100%  51186 (longest request)

Notice :
Requests per second: 1.29 [#/sec] (mean)
Total time for requests: 69 seconds.
(Data) Transfer rate: 75.71 [Kbytes/sec] [Kbytes/sec].

For those unfamiliar with ab, that is a “minor” DOS

For comparison, here is what ab can do to the server (iptables was flushed [disabled]):

ab -n 1000 -c 100 http://bodhi's_test_server.com/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking bodhi's_test_server.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        nginx
Server Hostname:       bodhi's_test_server.com
Server Port:               80

Document Path:          /
Document Length:        58708 bytes

Concurrency Level:      100
Time taken for tests:   59.324 seconds
Complete requests:      1000
Failed requests:        945
   (Connect: 0, Receive: 0, Length: 945, Exceptions: 0)
Write errors:           0
Total transferred:      59190450 bytes
HTML transferred:       58945935 bytes
Requests per second:    16.86 [#/sec] (mean)
Time per request:       5932.368 [ms] (mean)
Time per request:       59.324 [ms] (mean, across all concurrent requests)
Transfer rate:          974.37 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      127  908 817.9    788    8016
Processing:   735 4779 1805.2   4368   15707
Waiting:      128  981 827.2    811   12143
Total:       1058 5687 1880.8   5269   17450

Percentage of the requests served within a certain time (ms)
  50%   5269
  66%   5899
  75%   6340
  80%   6863
  90%   8078
  95%   9001
  98%  10937
  99%  11730
 100%  17450 (longest request)


Notice :
Requests per second: 16.86 [#/sec]
Total time for requests: 69 seconds.
(Data) Transfer rate: 974.37 [Kbytes/sec] .

As you can see, the server has no problem dishing out 974.37 [Kbytes/sec] !!!

Closing remarks

Hopefully you now understand this “simple” example limiting a DOS on port 80.

With these rules your web site remains responsive to human interaction in firefox. Go ahead, hit F5 (refresh the page) as fast as you can, see if you can get your web page to slow down =) .

The difference is that as with a DOS attack, ab is hitting the server faster then you can with F5 , so your site is responsive to “normal” activity, but blocks DOS.

Obviously this is but one example and there are several types of DOS attacks. The goal is to demonstrate the use of iptables using a few “simple” rules.

You task is to take this knowledge and apply it to you own server.

This entry was posted in Linux and tagged . Bookmark the permalink.

30 Responses to Prevent DOS with iptables

  1. Pingback: LINUX TUTORIALS : Centos/Redhat 5 Installation on Vmware - Installation, Linux, Centos, Games, LinuxPerformous, Software - CPanel Administration

  2. Tapas Mishra says:

    This was really helpful.I have been looking for this type of information.
    I have added this to my bookmarks.

  3. Ovidiu says:

    Your examples are correct (and useful), but they will not protect you against any serious DOS. All they do is move the load from the application to netfilter – which is fine, because your machine will most likely be responsive and not crash on you.

    However, a real DOS’s purpose is not to crash your machine, but to make it unavailable for valid users. It is realatively easy and cheap for a determined attacher to fill your server’s bandwidth. I have seen 10-20 MBit or more floods. “Professionals” have botnets who can produce tens of gigs. And they rent their services…

    Your machine will be up, but valid requests will not get through. And let’s also mention that most ISPs and colocation companies will just filter your IPs from upstream in order to protect their other customers.

    Unfortunatly, there is no 100% working way of protecting against a DOS.

  4. bodhi.zazen says:

    @Ovidiu – Your points are well taken and I agree.

    Just to clarify, My point was to demonstrate how to use iptables. As you point out, Apache remains responsive and so this technique can be helpful against one type of DOS.

    It is not a magic bullet and would not help as much against other types of DOS and as you point out, “there is no 100% working way of protecting against a DOS.”

  5. Shai says:

    Nice one! Keep’em coming :)

  6. kvz says:

    Nice one!
    I did a similar article that also shows restore on boot & a trick for lot locking yourself out
    http://kevin.vanzonneveld.net/techblog/article/block_brute_force_attacks_with_iptables/

  7. bodhi.zazen says:

    Thank you =)

    I have a web page on iptables :

    http://bodhizazen.net/Tutorials/iptables/

    To prevent lock outs I prefer:

    1. Keep the default policy “ACCEPT” and make the last rule in your chains to DENY all.

    2. Use iptables-apply

    root@wyverin:~ iptables-apply /etc/iptables.save

    Applying new ruleset… done.

    Can you establish NEW connections to the machine? (y/N) n
    Timeout. Something happened (or did not). Better play it safe…
    Reverting to old ruleset… done.

    See how that asks for confirmation ?

  8. Pingback: Protection against incoming attacks

  9. Pingback: how to fight back attacks on my web service - Admins Goodies

  10. Pingback: Game server under attack - Page 2

  11. Chris says:

    Thanks for the guide but for me isnt working well in practice, I used your values for burst etc. But Apachebench is blocked after just 1 connection, just one and I cannot browse using my browser. So even tho the burst is set to 200 and 50 per minute it seems to be blocking very agressively allowing just one connection.

  12. bodhi.zazen says:

    @Chris – Sounds as if your iptables rules need to be fine tuned a bit.

    I suggest you post them on a support forums.

  13. Chris says:

    Hi.

    The rules were only what you posted here.

    I found the cause of the problem.

    these rules are a global limit not per source ip. So they worked ok when it was 5am, but when the web server started getting busy they were blocking too much traffic, because of that they not suitable for varying loads.

    Instead I used the ips_recent rules which work on a per source ip basis which means it doesnt matter if the web server is quiet or busy as its per source ip and not destination ip.

    With the -m limit rules even when I did 10x your limit it was blocking traffic during the day.

    Here is what I am using now instead (bear in mind images are not rate limited by these and this is just the index html requests only as images are on a different ip/server).

    iptables -v -A INPUT -i eth0 -p tcp –syn –match multiport –dports 80 -m recent –rcheck –seconds 5 –hitcount 10 –name HTTP -j LOG –log-prefix “HTTP Rate Limit: ”
    iptables -v -A INPUT -i eth0 -p tcp –syn –dport 80 -m recent –update –seconds 5 –hitcount 10 –name HTTP -j DROP

    above those I have a rule allowing traffic to port 80 on the images server so this is only filtering the static content http, with images as well the limit would have to be higher.

    I hope this helps others who discovered the same problem.

  14. bodhi.zazen says:

    @Chris – Thank you for your post. As you found, you sort of need to fine tune the rules.

  15. Driver says:

    Perfect guide! Very helpful and simple, Thanks!

  16. Example says:

    Limiting simultaneous connections may also be useful to protect a webserver with limited resourses. These rules could probably get better default values, but I use these on an Apache server. Then at least a simple attacker (or proxy gone berzerk or autodownloader gone crazy) will be blocked.. The network rules protect from clients with dynamic IP.

    /sbin/iptables -A INPUT -p tcp –syn –dport 80 -m connlimit –connlimit-above 20 -j REJECT –reject-with tcp-reset
    /sbin/iptables -A INPUT -p tcp –syn –dport 80 -m connlimit –connlimit-mask=24 –connlimit-above 500 -j REJECT –reject-with tcp-reset
    /sbin/iptables -A INPUT -p tcp –syn –dport 80 -m connlimit –connlimit-mask=16 –connlimit-above 100 -j REJECT –reject-with tcp-reset
    /sbin/iptables -A INPUT -p tcp –syn –dport 80 -m connlimit –connlimit-mask=8 –connlimit-above 200 -j REJECT –reject-with tcp-reset

  17. Pingback: Linux VPS 安全策略记录 | 水景一页

  18. Pingback: After putting Bastille Linux on Ubuntu: Module is unknown when logging in

  19. Pingback: iptables - limit amount of tcp connections

  20. David B says:

    Hello. Could I apply this rule only to a specific network segment, instead of all the incomming connections?

  21. Pingback: Prevent DOS with iptables | Shadows of epiphany » Rambles of Ev

  22. hi Can any one you please help me to set the chain rule for iptable (linux redhat) , I want to restricted per source IP address for some limit of connection say 2 connection per sec.
    My existing IPtables had some rules like we already have connection limit but its not per source IP address, Iits needs to be enhanced to make it per source IP of client ip.

    So requirement is :->
    connection rate shall per source IPconnection

    I have below rules but its not per source IP address
    iptables -I INPUT -p tcp –syn –dport 22 -m state –state NEW,ESTABLISHED -m recent –set -j ACCEPT
    iptables -I INPUT -p tcp –syn –dport 22 -m state –state NEW -m recent –update –seconds 60 –hitcount 3 -j REJECT –reject-with tcp-reset
    I want to update this rule plz help

  23. bodhi.zazen says:

    @Manjeet Singh Just add the option “-s ip_address” to your rules.

    iptables -I INPUT … -s 11.22.33.44 -j ACCEPT

    You may want to use a custom chain for a whitelist of allowed ip.

    See also : http://fedorasolved.org/Members/kanarip/iptables-howto

    http://bodhizazen.net/Tutorials/iptables

  24. Pingback: Iptables screening | Freelifeblog's Blog

  25. Pingback: Vps problem

  26. Gerry Tan says:

    Thanks for the great article, but I find some of your explanation about limit and burst a bit contradictory to what iptables manual (http://netfilter.org/documentation/HOWTO/packet-filtering-HOWTO-7.html#ss7.3) says.

    -m limit --limit 50/minute --limit-burst 200

    Should mean 200 * 50 = 10000 packets per minutes allowed before 50/minute limit is applied.

    The example on the manual said Edge of DoSAm I wrong?

  27. bodhi.zazen says:

    @Gerry Tan – I do not think you understand, I am not sure why you are multiplying 200 * 50 .

    When a browser, such as firefox, connects to a http server there will be an initial high number of packets. So by allowing this initial “burst” of activity you do not slow down legitimate traffic.

    — limit 50/minute is an AVERAGE.

    See also:

    http://www.cyberciti.biz/tips/howto-limit-linux-syn-attacks.html

    and

    http://thelowedown.wordpress.com/2008/07/03/iptables-how-to-use-the-limits-module/

  28. Lavoiesl says:

    Very nice, I like your take on limit established traffic.

    I encourage you to take a look at this article I wrote where I put more emphasis on individual IPs

  29. bodhi.zazen says:

    @Lavoiesl – Nice write up ;)

  30. Pingback: Iptables antiabuso | Freelifeblog's Blog

Add Comment Register



Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>