Keep WordPress Safe From Brute Force Attacks with Fail2ban

Security plugins for WordPress are very popular these days, I bet you have a list of must-have security plugins on your WordPress sites.

Among all the common security issues related to WordPress, I personally hate brute force attacks most, which cost one of my clients’ sites down and a painful customer service experience. So last year when I started some new WordPress sites on a Media Temple VPS hosting, I chose to use Fail2ban to deal with such attacks.

Why Fail2ban?

To be honest, there are no particular reasons that I can say why I choose Fail2ban to deal with brute-force login attacks, though it does very powerful. To me, it’s just because I want to explore features that I can’t have on a shared hosting. And I don’t have extra budget on a cloud proxy service, which would be a better solution I suppose.

Installing Fail2ban

If you are on Ubuntu or Debian, you can install Fail2ban with:

sudo apt-get install fail2ban

If you are on CentOS, Fail2ban doesn’t come with it, you’ll need to download the repository first. You can download it with this command if you are on CentOS 6:

rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

Then installing Fail2ban:

yum install fail2ban

Please refer to the knowledge base from your hosting provider. If you’re on a Media Temple DV like me, you can check this article for more detail.

Creating the configuration file

Now let’s create the configuration file by copying a default config file to a new file:

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

We’ll come back later to add our own filter rule.

Start Fail2ban service

We can start Fail2ban now:

service fail2ban start

How Fail2ban keeps us safe from brute force attacks?

According to its official website, Fail2ban works in these ways to keep us safe from brute-force login attacks:

  1. Fail2ban scans log files (e.g. /var/log/apache/error_log) and bans IPs that show the malicious signs — too many password failures, seeking for exploits, etc.
  2. Generally Fail2Ban is then used to update firewall rules (iptables) to reject the IP addresses for a specified amount of time, although any arbitrary other action (e.g. sending an email) could also be configured.
  3. Out of the box Fail2Ban comes with filters for various services (apache, courier, ssh, etc).

From above we understand Fail2ban needs to know which logs it should keep eyes on, and besides services like ssh login, we can create custom filter rules, to ban brute-force login attacks on WordPress, Drupal or Joomla, etc.

We should also keep in mind that Fail2ban only reduces the rate of incorrect authentications attempts but not guarantees your websites 100% safe especially if they have weak authentication mechanism.

Creating the custom filter rule

The filter rule we create to detect brute-force login attacks looks like this:

In line 3 we define the failregex to tell Fail2ban what to watch in a log file. I adjust the the expression to make it work on a multisite network. You can replace it with code below for a standard WordPress:

failregex = ^ .* "POST /wp-login.php

The rule is plain simple. Now save it to Fail2ban’s filter directory /etc/fail2ban/filter.d/ and name it as wp-login.conf

Testing the custom filter

We can test if the filter works with the following command:

The command is in this format:

fail2ban-regex log-file filter-to-test

And the test results would looks like this:

Fail2ban regex test results

If you’re experiencing brute force attacks at the time of this testing, the matched lines should be greater than 0, or it could still be 0.

Add the rule to jail.local

Now let’s append the rule to the jail.local:

Let’s take a look at these options:

  1. Line 2: enable must be true to make the rule work.
  2. Line 3: if you’ve got a SSL certificate for your domain, the port should be http, https.
  3. Line 4: we set 2 actions here. The iptables-multiport action will add a new rule to iptables that bans IPs perform the brute force attacks. The sendmail-whois action will send notifications to the specified email address. You can change the name in both actions to values different from mine.
  4. Line 6: the filter must be the same as the filter’s file name. We set it to wp-login because we named the file wp-login.conf.
  5. Line 7: logpath is the key that we must provide Fail2ban with the correct path of server logs, so it can monitor the attacks for us. The path in my example shows the path of access logs on an Nginx server. Note that I use access*log to catch logs both for http and https.
  6. Line 8: maxretry means how many times the fail login can be tolerated. If the retry times exceeds the limits, the IP will be banned.

Fail2ban bans each IP for an hour by default. You can add a bantime option to set a different time span in seconds.

Restart Fail2ban service

Whenever you update the config files, please remember to restart Fail2ban:

service fail2ban restart


With this tutorial, I hope you’ve learned how to set up Fail2ban and make it work with WordPress.

If you have any question when following the steps in this tutorial, please let me know. I’d love to help.

15 responses

  1. Well, recently Brute force Attacks has immensely increased, becoming a dangerous factor for all WordPress users, but it is a thing, which is fight-able, I mean, by using security methods, we can move brute force attacks out of the window. Although, it can be difficult for newbies, who just got started with WordPress, but he/she can learn by reading posts online and then can implement security.
    In my view, implementing only three tricks works very well, Changing Login Slug, A content Delivery network (CDN) and a Plugin like fail2ban.

    1. I too use WP fail2ban plugin. Do we still need to change login slug?

  2. Great post! Explained including testing.

    kind regards,

    Rudger Gravestein

  3. works fine but how about multiple wordpress sites ?
    like we have 40 Wp sites on the server

    1. Yoren Chang Avatar
      Yoren Chang

      Hi Jack, you can just set multiple logs in your logpath, like:
      logpath = /var/www/vhosts/your.domain.here/logs/*/access*log
      /var/www/vhosts/second.domain.here/logs/*/access*log

      1. Will wildcard for domains work too? Like: logpath = /var/www/vhosts/*/logs/*/access*log

        1. Yoren Chang Avatar
          Yoren Chang

          Hello Liew, yes wildcard should work for domain too. Did you encounter any issue?

  4. This method only works on IPv4 as Fail2Ban doesn’t support IPv6 addresses.

  5. hi i use cloudflare and banned the ip from cloudflare, what can i do?

    1. Yoren Chang Avatar
      Yoren Chang

      Hey David, Sorry I’m no expert on this and couldn’t help.

    2. David, you may want to take a look at WP-fail2ban plugin, which has the setting that works with Cloudfare and proxy.

  6. Thanks for the tutorial. I’m using the WP Fail2ban Redux and it is working great!

    I see few IPs are now banned. Hopefully this can stop skiddies from attacking my blog.

  7. […] trying to set up a custom filter for fail2ban on a wordpress site. I’ve been following this tutorial but when I try to test my custom filter, I get the error: server.failregex.RegexException: No […]

Leave a Reply

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