Since this post I have tried to also implement Firewall DDOS Attack prevention – this did not work as well as my host would null route my IP if the attack was too large.

I believe that the only way to really protect my website/server against DDOS Attacks is to use a DDOS Attack prevention provider.

 The easiest and cheapest for me has been to use CLOUDFLARE – its really simple to set up.

You can find my Guide here: http://kiteplans.info/2014/04/19/virtualmin-cloudflare-secure-hidden-ip-ddos-protection-google-apps/


You can find my basic Fail2Ban setup guide here:


I recently suffered a minor DDOS attack and decided to setup Fail2Ban to prevent this in the future.

As you can see, this method will work for any http server you have, so lets start.

How to: CentOS 6 Virtualmin – fail2ban protect Apache from DDOS Attack

Edit your /etc/fail2ban/jail.conf file and add this section:

vim  /etc/fail2ban/jail.conf
enabled = true 
port = http,https 
filter = http-get-dos 
#Path to your logs
#To add all logs in a folder add Wildcard (*) expression 
logpath = /var/log/virtualmin/*_access_log
#Max number of requests
maxretry = 500
#Findtime in seconds
findtime = 120 
#Bantime in seconds - set negative to ban forever 
bantime = -1
#Action - change sendmail to send to your email
action = iptables[name=HTTP, port=http, protocol=tcp]
         sendmail-whois[name=httpd-get-dos, [email protected], [email protected]]

Now we need to create the filter, to do that, create the file /etc/fail2ban/filter.d/http-get-dos.conf and copy the text below in it:

vim /etc/fail2ban/filter.d/http-get-dos.conf
# Fail2Ban configuration file
# Author: http://www.go2linux.org

# 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 =



Be sure to adjust maxretry, findtime and bantime to values that fits your needs.

  • maxretry Is the maximum amount of requests before the originating IP gets blocked.
  • findtiem Is the time window (in seconds) to check for the amount of maxretries before the IP gets blocked
  • bantime is the amount of time the IP will be blocked

As you can see in my example, I have set up 500 maxretry and 120 for findtime, so, we need to have 500 GETs from the same IP in a time window of 120 seconds to have the originating IP blocked.

Remember that you will have one GET for each css, js, html, ico and other files that are part of your webpage, so if you have 20 components, some client needs only to load 15 pages in 5 minutes to get blocked. Be sure to adjust those values to fit your needs.

How to Find your perfect Maxentry + Findtime value for DDOS attacks:

To find the perfect value you will need to try out values and keep an eye on it.

I also ran a command to check the top requests on my server

awk '/Mar\/2013/ {print $1};' /var/log/virtualmin/domain.com_access_log | sort | uniq -c | sort -rn | head

And got this output:

12662 1xx.82.138.121 << DDOS
7413 4x.114.213.100 << DDOS
1475 12x.6x.14x.66  << Normal User
1343 << Normal User
1210 << Normal User
621 << Normal User
587 << Normal User
561 << Normal User
500 << Normal User

From that I could see what would be a normal amount for a very active user on my site – about 1475 hits 

I then went into the log and filtered by the users IP “12x.6x.14x.66” and checked how long it too the user to do 500 GET requests.

In my case the user took the user about 38min to do 500 GET requests – so he would not have been banned with my rule of 2min / 120 seconds.

While the DDOS user did 500 GET requests in less than 2 seconds – and THATS what I want to ban!

How to check if Fail2ban is working and if its blocking DDOS attacks:

You will need to test a few things:

1. If the Fail2ban filter is working on your system

2. If Fail2ban is blocking the IP after your Maxentry value in your Findtime timeframe

So lets check – If the Fail2ban filter is working on your system – with this command

fail2ban-regex /path/to/logfile /etc/fail2ban/filter.d/http-get-dos.conf

Then if you can see that IPS are being picked up (It should pick up every GET entry) then its working.

So then lets check – if Fail2ban is blocking the IP after your Maxentry value in your Findtime timeframe

The easiest way to do this is use Apaches AB testing tool.

Run this command for a different CentOS server that has Apache installed

ab -n 1000 -c 2 http://www.domaini.com/

The IP should be banned after 500 GET retries

Then you can just restart the fail2ban service to unban yourself.

If you are not banned check that you did not exclude the IP in the jail.conf


You can also Remove a ban from the Fail2ban SSH chain (change IP address):

fail2ban-client set sshd unbanip


How to: CentOS 6 Virtualmin – fail2ban protect Apache from DDOS Attack
Tagged on:                                                                                                                                 

Leave a Reply

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

8 thoughts on “How to: CentOS 6 Virtualmin – fail2ban protect Apache from DDOS Attack

  • Dear sir,

    I have configured fail2ban for apache and ssh. Fail2ban work well in ssh but for apache does not work.

    sandeep rawat.

    1. Are you getting any error messages? Have you tried to use the testing commands? – As I said on the top of the post I would suggest using a proper DDOS protector…

  • DOS and DDOS are different things. Your solution looks good againts DOS attacks or soft DDOS attacks but will never work under heavy DDOS attacks. Heavy DDOS can’t be stopped with any software solution.

    1. With these settings I have only blocked one Chinese Search engine – so I changed the settings down a bit. Nothing else yet! Let me know if you have any other fail2ban questions – I will be glad to help where I can!

      1. Ok, I’m trying to use this for a long time.
        In fact it works… Using a rule for each domain.
        I really can’t get it to work using /var/log/virtualmin/*_access_log

        Any idea why?
        Thank you…

        1. Hi, make sure that you are actually able to view that log? Does the log exist and Does the log have the correct permissions?