Block wp-login.php and xmlrpc.php via fail2ban on RunCloud
How to ban IP addresses that are brute forcing your wp-login.php
and xmlrpc.php
on a WordPress install with fail2ban on a RunCloud server. Email yourself any fail2ban IP addresses.
Add a WordPress fail2ban filter
Create a wordpress.conf
file in /etc/fail2ban/filter.d/
[Definition] failregex = ^<HOST> .* "POST .*wp-login.php ^<HOST> .* "POST .*xmlrpc.php ignoreregex =
If using OpenLiteSpeed use instead:
[Definition] failregex = <HOST>.*] "POST /wp-login.php <HOST>.*] "POST /xmlrpc.php ignoreregex =
If you just want to ban only one of them just remove one.
Add a WordPress fail2ban Jail config
Create a wordpress.conf
file in /etc/fail2ban/jail.d/
[wordpress] enabled = true usedns = no port = http,https filter = wordpress banaction = firewallcmd-new logpath = /home/*/logs/nginx/*_access.log maxretry = 4 findtime = 1200 bantime = 86400
If using OpenLiteSpeed change the log path to not include nginx, like so:
logpath = /home/*/logs/*_access.log
Change the maxretry or bantime or findtime if needed.
The actual login of a legitimate account will count towards a retry so don’t put in too small a number as a user may login/logout a number of times in a space of time – so in the above I have 4 logins within a 20minute span, if this is exceeded then the IP will be banned, it is good practice to whitelist any known static IP addresses belonging to regular users.
The logpath uses RunCloud log paths and the banaction value of firewallcmd-new hooks in nicely with iptables
to show fail2ban banned IPs in iptables
.
Restart fail2ban
service fail2ban restart
If fail2ban fails to start, make sure you have at least one site configured as this will validate the log path by adding the nginx log – otherwise fail2ban won’t start.
Check fail2ban Log
Check the fail2ban log to ensure everything loads without error
tail -f /var/log/fail2ban.log
Check wordpress Jail status
You can check the WordPress jail status
fail2ban-client status wordpress
This will give you the log file list and any banned IP addresses.
Manually ban an IP address
fail2ban-client set wordpress banip 1.2.3.4
Manually unban an IP address
fail2ban-client set wordpress unbanip 1.2.3.4
See banned IPs in iptables from fail2ban
See the lot.
iptables -v -L f2b-wordpress
Or search for a particular one
iptables -nL | grep -i 1.2.3.4
Permanently Whitelist an IP address in fail2ban
You may want to permanently allow your IP address, add this in /etc/fail2ban/jail.local as a value in ignoreip – for multiple addresses just space separate them. Also add in the host machines IP address.
[DEFAULT] ignoreip = 127.0.0.1/8 1.2.3.4 bantime = 86400 findtime = 43200 maxretry = 6 ...
Then restart fail2ban
service fail2ban restart
Send Email Fail2Ban Reports
With a server able to send emails such as Postfix, you can email reports of banned IP addresses as they happen. In the WordPress conf file add some more mail variables…
[wordpress] enabled = true port = http,https filter = wordpress banaction = firewallcmd-new logpath = /home/*/logs/nginx/*_access.log maxretry = 2 findtime = 10800 bantime = 86400 destemail = [email protected] sender = [email protected] sendername = Fail2ban.`hostname -f` mta = sendmail action = %(action_mwl)s
Change the email settings and you should be good to go.
Neil, thank you for the guide! It’s useful.
Does banaction = firewallcmd-new “send” banned IPs to Runcloud panel (Security –> Fail2Ban tab) in your case?
In mine, it doesn’t. IPs are blocked but they aren’t shown in the Runcloud tab…
i got this result :
# fail2ban-client status wordpress
NOK: (‘wordpress’,)
Sorry but the jail ‘wordpress’ does not exist
Hello and thank you. I am not able to understand this:
`iptables -v -L f2b-wordpress`
It returns to me: `iptables: No chain/target/match by that name.“
Thank you
Unfortunately this bans based on login attempts, not failed logins, and I have multiple sites running on the same server so I happened to hit the ban threshold just by logging in successfully to my websites.
You can whitelist your IP address in the
ignoreip
attributeCould you tell me how to update the failregex to also catch failed logins at a sub directory of /my-account/?
You could do….
.* "POST .*wp-login.php .* "POST .*/my-account/
[Definition]
failregex = ^
^