Saturday, April 23, 2011

DDoS-Wall Script -- Automatic detection and mitigation of DDoS attack on HTTP

Application


The name of the post is pretty much self explanatory. So before introducing DDoS wall script further, I want to save your time by starting straight away with an application or usefulness of this script, so that you dont end up reading whole post and then come to know this is not suitable for your scenario :)


1. This script (or rather the heart of the script i.e. actual commands which play an important role in blocking DDoS attack) is meant to be used in ,shared web hosting environment, where one of the hosted domains on server gets ddos attacked, and due to which whole server becomes unable to serve http requests for any other domain hosted on that server.

2. This script is tested and used for Linux 2.6.18 running Apache web server.


3. DDoS mitigation is actually nothing but completely placing blanket block for all requests for ddos'ed domain at firewall level (iptables), thereby making the ddos'ed domain inaccessible at all, and allowing other domains to remain unaffected. So, from the perspective of shared web hosting company, its a mitigation, and from the perspective of customer whose web site is under attack, its web service suspension.


4. This script will help your server withstand the ddos attack, upto the extent that your server is capable of handling malicious traffic and blocking it at iptables level. If the ddos malicious traffic volume is really large which your server can not handle at all, you need a hardware firewall solution anyways.


Introduction

Now let there be a formal introduction.

Linux shared web hosting servers, many times face ddos attack on particular domain hosted on server, due to which all sites hosted on the server dont get served. Sign of such kind of attack is, all the apache client processes are used up, trying to serve request for same domain. As a preventive measure, you might think of below options:

* Putting hardware firewall in place (if there is not one already, for cost reason) and filter out malicious traffic. Not right option to go for in case of emergency, time consuming.

* Bring down the IP under attack, so that no traffic hit our server. Not right option if you have many virtualhosts using that IP.

* Use OS firewall to prevent attack. There was no known effective way to put blanket block on all traffic coming for particular domain till now (using iptables at least).


Well, as far as last point is concerned, we now have a way to filter out malicious traffic for particular domain in effective way using iptables, which ddos_wall script uses. And if you are just interested in iptables rule, and want to try it out yourself, without automation script, here it is.


# modprobe ipt_recent ip_list_tot=2500
# iptables -I INPUT -p tcp --dport 80 -m recent --update --seconds 60 --name HTTP -j DROP
# iptables -I INPUT 2 -p tcp --dport 80 -m string --algo bm --string 'domainname' -m recent --set --name HTTP -j DROP


You might want to google for iptables recent and string modules to understand above rules. Or if you trust me, you can simply use these rules right away, substituting below values :P

ipt_recent_tot: This is a number of dynamic IPs kernel will maintain, which are participating in ddos attack
domainname: substitute this with a domainname hosted on your server which is under attack.
--dport, --seconds: as per your requirement.

But above values work best for me.


Now that you know above rule will just save your day, if ddos attack volume is below or as much as your server can handle it at iptables level, you would definitely want to have something to keep monitoring your server-status, detect ddos attack (especially distinguish ddos attack from dos attack), and isolate ddos'ed domain automatically. Well, here is my little attempt to do it for you. The ddos_wall.sh script.

How does it work?


This script analyzes apache's server-status output to detect ddos/dos attack. Server-status is very useful as its the runtime data from the point of view of application and easy to analyze as well. Below is the flow of this script as it executes.

1. Scritpt stores current server-status in memory.

2. DDoS attack check

* From server status, it calculates count for various domain-URI combination. If particular domain-URI combination is greater than its threshold limit, and the number of source IPs for those requests is greater than its threshold limit it's treated as DDoS attack and that domain will be blocked.

3. Check for DoS attack.

* All IPs are ignored which are participating in DDoS attack detected earlier, as there is different rule for them.
* From server-status output, calculates count for various IP-domain-URI combination. If particular combination of IP-domain-URI is greater than certain threshold, it treats it as DoS attack and block the IP.


Well, this is my logic, however there is a lot of scope for this script to improve, and you are welcome to contribute to that...


Deployment

1. You can download DDoS-Wall script from here

PS: You may be required to log in to google account to download from above link.

2. You need to have below rules in your firewall script. These rules should be placed in proper order in INPUT chain, so that all http traffic goes through it.

modprobe ipt_recent ip_list_tot=2500
/sbin/iptables -N DDOS_BLOCK
/sbin/iptables -N DOS_BLOCK
/sbin/iptables -A INPUT -p tcp --dport 80 -j DDOS_BLOCK
/sbin/iptables -A INPUT -p tcp --dport 80 -j DOS_BLOCK


3. Have a cron job to run this script every minute. (crontab -u root -e)

* * * * * /script/path/ddos_wall.sh > /var/log/ddos_wall.log 2>&1


configuration


There are some configuration variables in ### CONFIG VARIABLES ### section at the top of the script, like threshold limits etc.


Misc


* /proc/net/ipt_recent/domainname file can be used as any other normal text file for analysis.

* /var/log/ddos_wall.log can be used to see logs.

* iptables -F DDOS_BLOCK, iptables -F DOS_BLOCK can be used to flush all blocks

1 comment:

  1. If there are man requests for certian domain..


    for i in `seq 1 15`;
    do
    /sbin/iptables -A DDOS_BLOCK -m recent --update --seconds 60 --name domainname${i} --rsource -j DROP
    /sbin/iptables -A DDOS_BLOCK -m string --string $i --algo bm --to 65535 -m recent --set --name domainname${i} --rsource -j DROP


    while [ ! "`wc -l /proc/net/ipt_recent/domainname${i} | awk '{print $1}'`" == "3000" ]
    do
    sleep 5
    done

    /sbin/iptables -D DDOS_BLOCK -m string --string $i --algo bm --to 65535 -m recent --set --name domainname${i} --rsource -j DROP
    done

    ReplyDelete