Using fail2ban to block Wordpress login attempts

If you are being brute force attacked by someone trying to login to your website, more specifically your WordPress blog, you could certainly block them in the firewall by their ip adress, with iptables like this:

iptables -A INPUT -s 13.22.33.12 -j DROP

However, this gets quite cumbersome to do everytime your site is under attack, so the best solution would be to have an automated blocking system.  This is where fail2ban comes in.

Using fail2ban to block login attempts

fail2ban is a tool that monitors logfiles for certain events, like too many login attempts, and takes action by creating firewall rules (like above) to block the attackers brute force attempt.

If you haven’t installed fail2ban, you can do it from the package manager:

sudo apt-get install fail2ban

(This is for a server running an ubuntu distro. Here is an ok introduction post on how to setup fail2ban the first time)

Finding the attacker to block

For fail2ban to help us with wordpress login attacks, we have to setup a fail2ban rule. But first, we should find the log entries for the attack that we want to block.

This depends a little bit on your setup.
You should check you webserver logfile for login attempts.

To check your nginx logfile you can run:

tail -100 /var/log/nginx/access.log

to get the 100 last log lines. Look for “POST to wp-login.php”.

It should be similar to this line (this is for nginx, for apache, see last section):

12.34.33.22 - - [07/Jun/2014:11:15:29 +0000] "POST /wp/wp-login.php HTTP/1.0" 200 4523 "-" "-"

If there isnt any, do a login on your own wordpress blog, so it will be logged.

This shows the attackers ip adress, the date of the request, and a loginrequest to the wp-login.php file.

Creating a fail2ban rule

We now have to create a regular expression, called failregex that matches that log line, for fail2ban to use.

Copy a line from the logfile, to a regex testing tool, perhaps online, or sublime text, to test that the failregex matches on the logline, so it will register in fail2ban.

You may not have the wordpress login file at this path: /wp/wp-login.php as I do.

For the above log line, this failregex will work for fail2ban:

^<HOST> .* "POST /wp/wp-login.php 

The part indicates the ip adress on the logline, and it is picked up by fail2ban.

Creating a fail2ban filter rule

Create the file /etc/fail2ban/filter.d/wp-auth.conf

# WordPress brute force auth filter: /etc/fail2ban/filter.d/wp-auth.conf:
#
# Block IPs trying to auth wp wordpress
#
# Matches e.g.
# 12.34.33.22 - [07/Jun/2014:11:15:29] "POST /wp/wp-login.php HTTP/1.0" 200 4523
#
[Definition]
failregex = ^<HOST> .* "POST /wp/wp-login.php  
ignoreregex =  

Add the rule to jail.local

We could add the rule to the list of other fail2ban rules, in jail.conf, however, the jail.local file is used for custom rules, and it should survive upgrades.

Create /etc/fail2ban/jail.local if it does not already exist:

[wp-auth]
enabled = true  
filter = wp-auth  
action = iptables-multiport[name=NoAuthFailures, port="http,https"]  
logpath = /var/log/nginx/*error*.log  
bantime = 1200  
maxretry = 8  

This uses the filter rule we created, for the nginx logfile in logpath, with a bantime of 1200 seconds (20 minutes).

Testing the rule

You can test the rule with the following syntax:

fail2ban-regex <logfile> <fail2ban rule to test>

For example:

fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wp-auth.conf

If there are any attacks in the logfile, the test should output some matches and ip adresses.

Restart fail2ban with:

service fail2ban restart

Verifying

With the fail2ban rule now active, login attempts to wp-login.php should now get blocked in the iptables firewall.

You can check the list of blocked ip adresses in iptables with this command:

iptables -vnL

or to see the resulting urls of the ip adresses:

iptables -L

A Note on nginx and apache webserver

I am using the nginx webserver in this example.

The method is very similar for blocking attempts on Apache, except for the file paths and the regular expression for finding the right log entries.

comments powered by Disqus