How to set-up fail2ban for a WordPress site
What is Fail2ban
Fail2ban is a tool which you can use to reduce the impact of attacks on your servers. Typically you configure it to monitor a log file for suspicious activity. Then once the activity crosses a threshold you can have it take an action, such as block the source IP address in your firewall. It’s a good way to stop attacks early but doesn’t entirely prevent them.
Why use it to protect WordPress
Due to it’s popularity, WordPress is often the target of automated attacks. We often see bruteforce attacks targeting xmlrpc.php or wp-login.php, these rely on making a huge number of requests in the hope that one will eventually be successful. Using strong passwords, especially for accounts with admin access is important to reduce the risk from attacks. Fail2ban can be used to slow attackers down. This helps for two reasons: it makes them less likely to succeed; it reduces the load on the server caused by processing these requests.
Other options
- Using an external Web Application Firewall (WAF) such as Sucuri or Cloudflare.
- Using webserver configuration options to limit requests such as limit_req in Nginx.
- WordPress security plugins such as Wordfence.
Blocking an attack as far upstream as possible is always advantageous to save resources so we would typically favour a Web Application Firewall or Webserver configuration over using fail2ban or a WordPress plugin however every site, server and customer is different so it will depend on the exact configuration used and required.
Install & config fail2ban (for Ubuntu)
sudo apt-get install fail2ban
Fail2ban works by having a jail file which references the log file, a filter and an action. By default fail2ban will protect sshd. If you are restricting SSH access in another way then you might want to turn this off. You can do so by creating the following as /etc/fail2ban/jail.local
[sshd] enabled = false
Fail2ban doesn’t come with a filter for WordPress. I’d like to credit these two articles for providing a good starting point. We see requests to ‘//xmlrpc.php’ (note the double slashes) fairly frequently so tweaked the below to also flag them. As this is detecting any requests to wp-login/xmlrpc it will flag legitimate admin users when they login etc. We’ll look to account for this with the jail configuration.
You can create the filter as /etc/fail2ban/filter.d/wordpress.conf
[Definition] failregex = ^<HOST> .* "(GET|POST) /+wp-login.php ^<HOST> .* "(GET|POST) /+xmlrpc.php
The jail file has most of the configuration options:
- logpath, in this case the path to your Apache access log
- action, adjust this if you’re using a different firewall or want to be sent email instead, you can see available options in /etc/fail2ban/action.d/
- maxretry, the number of requests within findtime seconds to ban after
- bantime, the number of seconds to ban for, with this action how long they’re blocked in iptables
As mentioned, the filter will catch both malicious and legitimate users. We’re configuring maxrety fairly high and bantime relatively low to minimise the probability and impact if we do block a legitimate user. Whilst this allows attackers to make roughly one request every ten seconds this is a fraction of what they’d make without fail2ban.
You can create the jail file as /etc/fail2ban/jail.d/wordpress.conf
[wordpress] enabled = true port = http,https filter = wordpress action = iptables-multiport[name=wordpress, port="http,https", protocol=tcp] logpath = /var/log/apache2/all-sites-access.log maxretry = 12 findtime = 120 bantime = 120
Restart fail2ban to load in your new config
sudo systemctl restart fail2ban
Checking your fail2ban set-up
Show the jails
sudo fail2ban-client status
Show info about the WordPress jail
sudo fail2ban-client status wordpress
List the f2b-wordpress iptables chain (this will be created the first time fail2ban blocks an IP and contain blocked IPs)
sudo iptables -v -n -L f2b-wordpress sudo ip6tables -v -n -L f2b-wordpress
View the log to see any IPs banned or flagged
sudo less /var/log/fail2ban.log
Feature image by Jussie D.Brito licensed CC BY-SA 2.0.
Leave a Reply
Want to join the discussion?Feel free to contribute!