fail2ban for Wordpress and Plesk

I’m hosting quite a bit of pages that run WordPress, and one of the biggest problem that I ran into is that people don’t keep their WordPress or plugin installations updated.

I gave up on having everyone upgrade, because they all use different plugins, customized plugins, and a lot of other stuff that will break if they upgrade.

So here comes fail2ban to the rescue, we can use it to go through the logs, to configure the system to ban the users when they fail to log in, or do some bad stuff, or try to brute force their way into the wordpress installation, either through the login form or through xmlrpc.

You should install fail2ban if you haven’t already, on debian based you would just issue.

apt-get install fail2ban

If you use Plesk you can skip creation of the files, and just use the frontend to create the necessary jails and filters, also replace common.conf with apache-common.conf.

The configuration is located in /etc/fail2ban on most systems.

So firstly let’s create a filter.

In /etc/fail2ban/filter.d, create a file called wordpress-login.conf, and put the following text inside.

# Fail2Ban filter for WordPress Login
#

[INCLUDES]
before = common.conf

[Definition]
_daemon = wordpress
failregex = ^<HOST>.*].*POST.*/wp-login\.php HTTP.*
ignoreregex =

# DEV Notes:
#
# Rule Author: Ilija Matoski

What this does it creates a filter to be used in the next step. Also let’s create one filter for XMLRPC for WordPress in the same directory named wordpress-xmlrpc.conf

# Fail2Ban filter for WordPress XMLRPC
#

[INCLUDES]
before = common.conf

[Definition]
_daemon = wordpress
failregex = ^<HOST>.*].*/xmlrpc\.php.*
ignoreregex =

# DEV Notes:
#
# Rule Author: Ilija Matoski

Now let’s create two new jails, that we gonna use to ban the people who are gonna abuse this.

In the folder /etc/fail2ban/jail.d, wordpress.conf,

[wordpress-xmlrpc]

enabled  = true
filter   = wordpress-xmlrpc
action   = iptables-multiport[name=WordPressXMLRPC, port="http,https"]
logpath  = /var/log/apache2/access_log
maxretry = 10

[wordpress-login]

enabled  = true
filter   = wordpress-login
action   = iptables-multiport[name=WordPressLogin, port="http,https"]
logpath  = /var/log/apache2/access_log
maxretry = 10

If you are running Plesk, then replace the logpath with

logpath  = /var/www/vhosts/system/*/logs/*access*log
           /var/log/apache2/*access.log

So in Plesk, the action will look like.

iptables-multiport[name="<NAME_OF_FILTER>", port="http,https"]

This will read the data from all the hosts in Plesk

So what happens if someone tries to POST to wp-login.php, or hit xmlrpc.php, 10 times in a 10 minute period he will be banned for a day, also there is a jail called recidive in fail2ban, which if you get jailed 5 times with the previous filters, the IP will get ban for a week.

You can adjust the times in the configuration file, if you want to lower or increase them.

Well this should work, now let it run for a while, and you can see what does your, after 15 minutes of running this is what was present in my logs.

$ iptables -L fail2ban-WordPressLogin
Chain fail2ban-WordPressLogin (1 references)
target     prot opt source               destination
REJECT     all  --  189.1.169.141         anywhere            reject-with icmp-port-unreachable
REJECT     all  --  181.140.198.180       anywhere            reject-with icmp-port-unreachable
REJECT     all  --  117.21.191.227        anywhere            reject-with icmp-port-unreachable
RETURN     all  --  anywhere              anywhere

$ iptables -L fail2ban-WordPressXMLRPC
Chain fail2ban-WordPressXMLRPC (1 references)
target     prot opt source               destination
REJECT     all  --  117.21.191.227        anywhere            reject-with icmp-port-unreachable
RETURN     all  --  anywhere              anywhere