Using fail2ban to block WordPress login attacks

Fail2ban works by filtering a log file with a regular expression triggering a ban action if the condition is met. After a preset time, it will trigger an unban action. Without much effort, we can have WordPress log all authentication events and have fail2ban react on them.

Note: This guide is written for Ubuntu, but most of it should apply to other distributions as well.

Install fail2ban

It doesn’t get much easier than this:

Now, fail2ban works right away detecting any failed login attempts on SSH. The default settings will make 5 failed login attempts within 600 seconds to cause an IP ban via the iptables firewall for 600 seconds.

Logging Authentication Events

So, first of all we will make WordPress log all authentication events to the system authentication log file (the authlog, on Ubunutu found in /var/log/auth.log). You might write your own plugin, but the WP fail2ban plugin does exactly this and have a few very useful features. I usually just download the single PHP file in the plugin into my mu-plugins directory, but you may also install it as a regular plugin. Without any more fuzz, WordPress will now log all authentication events.

Note that if you are behind a reverse proxy, it is extremely important that you set the WP_FAIL2BAN_PROXIES constant. Otherwise you will end up banning your proxy, blocking all incoming requests from everybody. Read the FAQ for info on this.

Setting up the Filter and Jail

First we have to set up the filter. It is really important that the regexes in the filter matches the log entry format from WordPress. Luckily a filter is also provided with the WP fail2ban plugin, so we can just download that:

Feel free to inspect the file so you understand what it does.
(Oh, and btw: Since I first wrote this post, the plugin also includes a “soft” filter. You should check it out.)

Now, we’ll set up the jail. Create the file /etc/fail2ban/jail.d/wordpress.conf with the following content:

Restart fail2ban and you should be all set:

To make sure it is working, try a few bogus logins to WordPress. You should see entries like this appended to your /var/log/auth.log:

Do that more that 5 times, and you should see something like this in your /var/log/fail2ban.log file:

All connections from 123.45.67.89 should now be stopped in iptables. Note that the default iptables-multiport action won’t drop already established TCP connections, so you might still receive requests from your test browser if keepalive is enabled. If you want to make sure all established connections to the offending IP is killed, you have to create your own custom action and include a tool like tcpkill or simply use the provided route action.

Customizing the Jail

Inspect /etc/fail2ban/jail.conf to see what the default settings are, but ever edit this file directly. Do your changes in the jail.local file (you’ll have to create it) or files in the jail.d folder like we did above.

The most important options that you might want to tinker with are these, which you should add to your /etc/fail2ban/jail.d/wordpress.conf file:

Tune these settings to your liking. What my suggestion here does is: If 3 failed login attempts from the same IP is found within 10800 seconds (3 hours), the IP will be banned for 86400 seconds (24 hours).

Optional: Changing the Default Action

The default action is iptables-multiport. I like to use the route action instead. It is extremely fast both for a large number of IPs and since it blocks traffic even before it hits iptables. It also stops any traffic on already established connections immediately.

To change the default action for your WordPress jail, find one you like in /etc/fail2ban/action.d – like route and add the following to the /etc/fail2ban/jail.d/wordpress.conf file:

To inspect what bans are in place with route, issue the following command:

Optional: Custom Action: Using UFW

I like to keep things simple, so I like to use UFW (Uncomplicated FireWall) instead of iptables directly.

Since it is quite easy to create your own custom actions, setting up an action that use UFW is really easy. Just drop the following in /etc/fail2ban/action.d/ufw.conf:

I don’t think it needs an explanation. Now you can use action = ufw in your jail.

Important Note on Reverse Proxies

If you’re using a reverse proxy, but it is on a different host than your WordPress installation – like a load balancer, banning on your WP host isn’t going to do anything, since all the traffic is coming from your reverse proxy. In that case, you will have to set up a custom action (like the previous chapter with UFW), using an API so you can ban the offending IP on the host where your reverse proxy is.

If you happen to be using a Rackspace Cloud LoadBalancer, I have the recipe for you:
Using fail2ban from behind a Rackspace Cloud LoadBalancer
If you’re using something else, you can still use it as a starting point, but you’ll have to provide your own API wrapper.

Caveats

No IPv6 support, but it’s coming. A patch with experimental support is available.

… there’s more

Now, if you haven’t already, go take a look at the FAQ for the WP fail2ban plugin. Because the plugin isn’ t restricted to logging successful and unsuccessful login attempts.

It can also:

  • log pingbacks
  • change the logfile
  • block user enumeration attempts
  • shortcut the login process if a specified username is provided

So go check it out now.

There are 13 comments

I love comments that bring new insights, shares ideas and experiences, and most of all: corrects my mistakes. For support questions, there are other fora, like Stack Overflow, Server Fault and the WordPress support forum.

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