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:

  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:

  5. Now we just need to restart fail2ban for the new jail & filter to come into affect:

  6. Or if your machine is on systemd, use:

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

    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:

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:

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:

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

29 thoughts on “How To: Stop Apache DOS attacks with Fail2Ban”

  1. This is a simple solution, right.

    But what would you do, if u have a website with much content and each item is processed by a simple request, so u have e.g. 20 or more request within few seconds from each user?
    You will be going to drop a lot of users from visiting your site!

  2. Hi,

    Is there anyway to find the optimal values for maxretry and findtime for all DOS attacks ? The default maxretry 300 and findtime 600 doesn’t seems to work most of the time.

    1. I’m not aware of a way to find optimal values beyond trial and error, sorry – although that doesn’t mean there isn’t one.

      Perhaps the fail2ban docs might say something about it?

  3. But why is not working for me? Is it possible to missing some file from fail2ban? The jail is starting, access log is set. Maybe the regex is not right for me? If I hit F5 like crazy nothing happens. Nothing in the fail2ban log.

  4. I have the same problem that Gabo had:

    I seemed to have installed everything and configured all the config files file (keeping in mind to set the log file location), but it doesn’t seem to log or block(?) DDOS attacks?

    I used the exact filter stated above. I am sure the jail is nominally working because I get:

    [root@myhost filter.d]# fail2ban-client status
    Status
    |- Number of jail: 2
    `- Jail list: http-get-dos, sshd

    But when I try the ab command, none of the requests are blocked, and nothing is logged in the log file. Any ideas, please?

    1. Hmm, perhaps look at:
      – Are the page gets showing up in your apache log? i.e. is every page GET being logged?
      – Are permissions on the log file such that it can be read?
      – Perhaps try a more stringent maxretry to make sure you’re hitting the limit?

  5. Hi. Thanks for your reply. I’ve solved it.

    For your readers:

    I mistakenly thought the log file in the jail.local file was the output log file for fail2ban. Instead, it’s the input log file that fail2ban needs in order to make rules.

    So first I changed it to /var/log/apache_access.log, and that didn’t work. But then I realised that we configured apache to log to another file.

    Once I had the correct log file, it worked beautifully. Thanks!

  6. anyway, “me” is not so wrong…

    the correct failregex is another

    failregex = (?i)^ -.*”(GET|POST)(?!.*\.css|.*\.js|.*\.gif|.*\.jpg|.*\.jpeg|.*\.ico|.*\.png).* HTTP\/1\.1 .*

    so, case insensitive to exclude elements indirectly called by pages.

    So, ban IPs which request many pages in the findtime period, not just elements from the pages… really difficult that the bot/offender accesses those elements without calling the relative page at first.

    then, for others… you need to check your access log and put them in the badbots jail and/or create another jail/filter for excessive 404 requests. That’s all.

  7. Please, forgot to remove “POST”… if you use my failregex, that’s for GET only… and you need to separate the filter for POST, which may remain intact as it is

  8. It looks like I’ve installed everything and configured all the config file files (remember to set the log file location), and already logged on access.log but did not block (?) DDOS Attacks?

    I am using the appropriate filter mentioned above. I’m sure the prison works nominally because I get the log file on acces.log and already get:

    [root @ myhost filter.d] # status fail2ban-client
    Status
    | – Number of prisons: 4
    `- prison list:, apache, vsftpd, http-get-dos, ssh

    But when I try ab command, there is no blocked request, but log file already recorded in access.log, please help thank you?

    1. Hmm… Is your webserver logging get requests? That is, is the logging level of the server sufficiently verbose? If it’s only logging errors or such then it won’t see the ‘get’ messages that fail2ban parses to put the temporary ban in place.

      Alternatively, is your site running HTTPS (typically port 443)? This setup is just for straight HTTP (port 80) and I haven’t tried it with https, despite moving this site to use https. It’s likely you’d have to modify the last line of the jail.local file to make sure it’s looking for the right thing.

  9. please help me, i have implementation of ssh, ftp, http authentication and everything is working. but for http-get-dos configrations can not, ip address is not blocked and there is already a log file in /var/log/apache/access.log.

    this is my jail.local config

    [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]
    [http-get-dos]
    enabled = true
    port = http, https
    filter = http-get-dos
    logpath = /var/log/apache2/error.log
    maxretry = 300
    findtime = 300
    bantime = 300
    action = iptables [name = HTTP, port = http, protocol = tcp]

    failregex on /etc/fail2ban/filter.d/http-get-dos.cof
    failregex = ^ -. * “(GET | POST). *

    my implementation on vmware using ubuntu version 14.04. .

    thank you, your help I hope so much. .

  10. please help me, i have implementation of ssh, ftp, http authentication and everything is working. but for http-get-dos configrations can not, ip address is not blocked and there is already a log file in /var/log/apache/access.log.

    this is my jail.local config
    [http-get-dos]
    enabled = true
    port = http, https
    filter = http-get-dos
    logpath = /var/log/apache2/error.log
    maxretry = 300
    findtime = 300
    bantime = 300
    action = iptables [name = HTTP, port = http, protocol = tcp]

    failregex on /etc/fail2ban/filter.d/http-get-dos.cof
    failregex = ^ -. * “(GET | POST). *

    my implementation on vmware using ubuntu version 14.04. .

    thank you, your help I hope so much. .

  11. Okay, I’m going to take the second one of those as your actual jail.local (not the first one that duplicates sections with the same name).

    Some questions:

    – Why is your fail regex different from the one provided (it’s missing

    – oh, because it gets filtered in HTML, haha – ignore this one):
    failregex = ^ -.*”(GET|POST).*

    – I really hope your http-get-dos.cof file is called http-get-dos.conf

    – Why is your action in the jail.local specifying only HTTP and http for name and port, respectively if you’re trying to jail https accesses?

    I don’t mean to be rude, but I really think you should read the fail2ban documentation – you can find it here: https://www.fail2ban.org/wiki/index.php/Main_Page.

    Look at the Documentation section – it has links to all possible installation / configuration details.

    Cheers & best of luck!

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.