Protecting Your WordPress Installations With Fail2ban
There is no two ways about it: having your server compromised sucks. Seeing your website defaced or infected with malicious scripts feels like a punch in the gut. Did you know that modern brute force tools can test millions of passwords per second? It takes around 15 minutes to crack an average password (eight symbols in length, consisting of mixed-case letters, numbers, and special symbols). Is there anything you can do to protect yourself?
Luckily, the answer is yes. Plesk 12 comes with a comprehensive set of security tools. We have got the ModSecurity support to protect web applications, and the automatic security hardening for WordPress. But today I would like to tell you about a different tool called Fail2ban. Fail2ban is effective against brute force attacks, and can be used to protect any service running on your server.
Here is how Fail2ban works:
- Fail2ban constantly monitors logs of the services it protects, matching every new log entry against a pre-defined set of rules.
- Once a suspicious entry is found in a log, Fail2ban notes the IP of the potential attacker and starts counting. Every time the IP performs suspicious activity, Fail2ban adds one to the counter.
- Once a pre-defined number of attempts is reached, Fail2ban can do two things:
- Send an email notification, and/or
- Ban the attacker’s IP for a pre-defined length of time.
In this article we will give step-by-step instructions illustrating how you can use Fail2ban to protect your WordPress installation from brute force attacks. To do so, we will need to follow these steps:
- Create a filter, which is a set of one or more regular expressions. The filter is used to search the logs for suspicious activity.
- Create a jail, which is a set of rules covering an individual scenario. The settings of the jail determine what is to be done once an attack is detected.
Step 1: Creating the filter.
To create a filter for WordPress, go to Tools & Settings > IP Address Banning (Fail2Ban), open the Jails tab, and click Manage filters > Add Filter. Give the filter a name, and paste the following into the Content field:
failregex = ^<HOST> .* "POST .*wp-login.php HTTP/.*" 200
so that it looks like this:
As you can see, the filter contains a single regular expression, and it will trigger every time the WordPress login page is loaded – for example, after a failed authentication attempt.
Step 2: Creating the jail
To create the jail, return to the Jails tab and click Add Jail. Start by naming your jail and selecting the filter you have just created from the Filter menu. Once you are done, it is time to add the most important component of the jail – the actions.
Actions define what happens when a jail is activated. There are four preconfigured actions in Fail2ban:
- Ban the attacker on a single port.
- Ban the attacker on multiple ports.
- Ban the attacker on all ports.
- Send a notification email to a specified email address.
To add an action, select it from the Action menu and click Add. You can add any number of actions to a jail. You may need to customize the action to suit your needs (for example, to provide the desired mail address to send notifications to, or to specify what ports should be closed to the offending IP).
Once the actions are configured, you need to specify one or more log files Fail2ban will check for the signs of an attack – those go in the Log path field. To protect a specific WordPress installation, specify the path to its Apache access log files, found at:
/var/www/vhosts/<WordPress installation domain name>/logs/access_log
/var/www/vhosts/<WordPress installation domain name>/logs/access_ssl_log
You can specify more than a single log to protect multiple WordPress installations. Alternatively, you can use the * mask to protect all of them, like this:
Finally, there are two optional parameters you can set: the maximum number of failed login attempts and the IP address ban period. The first is the number of “strikes”, unsuccessful login attempts, leading to a ban; the second is the length of the resulting ban in seconds. For example, if you set the value of the first parameter to 3, and the second to 300, after a third unsuccessful login attempt the jail will trigger and ban the attacker for five minutes. If these values are left undefined for a jail, server-level Fail2ban settings are used.
You can see an example of a fully configured jail on the screenshot below:
Note that jails are created on a per-service basis (as in, one for SSH, one for SMTP etc.), but there can be multiple jails for a single service, covering different scenarios.
Once the jail is created, all that remains is to enable Fail2ban:
1. Go to Tools & Settings > Services Management and make sure that the IP Address Banning (Fail2ban) service is running.
2. Go to Tools & Settings > IP Address Banning (Fail2Ban), open the Settings tab and select the Enable intrusion detection checkbox.
3. Finally, open the Banned IP Addresses tab and click Switch On IP Address Banning.
Step 3: Action!
Now it is the time to test Fail2ban to make sure its protection works (let us assume that the settings of your jail match those on the screenshot above). Open the login page of your WordPress install and try logging in with incorrect login and/or password. Then do it again. And one more time for good measure. If you have set up everything correctly, you will not get another chance – the jail you created will activate and ban you for five minutes. And here is what was happening “under the hood” in the meantime:
- You try authenticating with incorrect credentials for the first time. The “POST /wp-login.php HTTP/1.0” entry gets written to the Apache access log. As Fail2ban monitors this log, and the entry matches the regular expression defined in the filter, Fail2ban notices the authentication attempt and starts counting. Okay, maybe you mistyped your password. Mistakes happen.
- You try authenticating for the second time. Same as above, only the counter is now at two. This is getting suspicious, but Fail2ban gives you one more chance.
- You try authenticating for the third time. Okay, now this is getting downright fishy. Three strikes, you are out! Fail2ban creates a temporary rule in the iptables barring you from accessing the server and sends a notification to “[email protected]”.
If you do not actually get banned, it means that there is a misconfiguration somewhere. Here are some troubleshooting steps that may help:
- Make sure that the Fail2ban service is running, that intrusion detection is enabled, and that IP banning is turned on, as described above.
- Make sure that the jail is activated (by the way, all newly created jails are activated by default).
- Make sure that the filter you created actually catches the relevant log entries with the fail2ban-regex command.
The syntax of fail2ban-regex is as follows:
fail2ban-regex <path to the access_log file> /etc/fail2ban/filter.d/<filter name>
Look for the Failregex value in the output. If it is zero, the filter is configured incorrectly.
Naturally, Fail2ban can be used to protect any service on the server, not just WordPress. Using the examples provided above as reference, you can create custom filters and jails to fit your scenario.
Further information about Fail2ban is available here: