How To: Stop Apache DOS attacks with Fail2Ban

I had to install and configure fail2ban yesterday to stop some hacking attempts on my FTP server, and when I was looking through the fail2ban configs I saw that you could stop DOS (Denial of Service) attacks with it too. As this site’s been hit by the occasional DOS from people with an axe to grind and too much time on their hands, I thought I may as well set up a DOS mitigation strategy while I was at it. Here’s how:

  1. Install fail2ban through the method of your choice.
  2. Edit the file /etc/fail2ban/jail.local and add the following section:
    [http-get-dos]
    enabled = true
    port = http,https
    filter = http-get-dos
    logpath = /var/log/apache2/YOUR_WEB_SERVER_ACCESS_LOG
    # maxretry is how many GETs we can have in the findtime period before getting narky
    maxretry = 300
    # findtime is the time period in seconds in which we're counting "retries" (300 seconds = 5 mins)
    findtime = 300
    # bantime is how long we should drop incoming GET requests for a given IP for, in this case it's 5 minutes
    bantime = 300
    action = iptables[name=HTTP, port=http, protocol=tcp]
  3. Don’t forget to replace YOUR_WEB_SERVER_ACCESS_LOG with the actual access log for your webserver! Note: This doesn’t have to be an apache log, I just happen to be using apache.

  4. Now we need to create the filter file, so create the file /etc/fail2ban/filters.d/http-get-dos.conf and place the following contents in it:
    # Fail2Ban configuration file
    #
    # Author: http://www.go2linux.org
    #
    [Definition]
     
    # Option: failregex
    # Note: This regex will match any GET entry in your logs, so basically all valid and not valid entries are a match.
    # You should set up in the jail.conf file, the maxretry and findtime carefully in order to avoid false positives.
     
    failregex = ^<HOST> -.*"(GET|POST).*
     
    # Option: ignoreregex
    # Notes.: regex to ignore. If this regex matches, the line is ignored.
    # Values: TEXT
    #
    ignoreregex =
  5. Now we just need to restart fail2ban for the new jail & filter to come into affect:
    /etc/init.d/fail2ban restart
  6. Or if your machine is on systemd, use:

    systemctl start fail2ban

    Also on systemd, if you want fail2ban to start on boot (and the chances are that you do), run the additional:

    systemctl enable fail2ban

    With all that done your site should be pretty safe from casual DOS attacks, although you’d likely need more stringent maxretry and findtime settings to really help against Distributed DOS (DDOS) attacks.

Testing

To check if fail2ban is seeing the logs, check out /var/log/fail2ban.log and you should see things like:

[http-get-dos] Found w.x.y.z

showing up as visitors view your site.

If you want to test if it’s really working, a nice way to do so is to use ab (Apache Benchmark – part of the apache2-utils package), like this:

ab -n 500 -c 10 http://your-web-site-dot-com/

This will kick off 500 page-loads in 10 concurrent connections against your site. When the ban kicks in the page-loads will stop (as incoming GET requests from your IP will be dropped), then when the bantime expires you’ll be able to access the site again. If you then take a look in your /var/log/fail2ban.log file you should see something like this:

2013-06-22 05:37:21,943 fail2ban.actions: WARNING [http-get-dos] Ban YOUR_IP_ADDRESS
2013-06-22 05:42:22,341 fail2ban.actions: WARNING [http-get-dos] Unban YOUR_IP_ADDRESS

Pretty neat, huh?

Many thanks to the authors of the following great articles for helping me to get this set up in no-time:
http://www.dedmeet.com/software-projects-mainmenu-12/fail2ban-to-limit-ddos-attacks– on-webserver.html
http://go2linux.garron.me/linux/2011/05/fail2ban-protect-web-server-http-dos-attack-1084.html

Cheers! =D