We’ve recently run into a problem with our WordPress site occasionally getting bombarded with login requests. To safeguard against this, we have implemented fail2ban on our Linux Machine to rate limit these requests.
I am using fail2ban against Nginx access logs, and I’ve seen multiple times a recommendation to utilize Nginx’s built-in rate-limiting limit-req (Rate Limiting with Nginx), and their zone idea seems to be what I’m doing when looking for specific requests.
I’m instead implementing fail2ban on its own, and just reading the access logs.
Fail2ban reactively scans log files for requests matching a filter (known as a fail) that (over a findtime duration) break the maxretry limit. If this happens, it locks them in jail for a bantime, stopping further requests.
sudo apt update && sudo apt upgrade
sudo apt install fail2ban
Ensure the package is installed correctly:
fail2ban-client --version
Copy the default files into files that you can safely customize, without risk of overwriting them with a package update.
cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
/etc/fail2ban/filter.d/wordpress-login.conf
[Definition]
# Match any access log line that starts with an IP address and attempts to access the wp-login via POST
# If we do want to limit xml access
# ^ .*"(POST) /xmlrpc\.php.*"
failregex = ^<HOST> .*"(POST) /wp-login\.php.*"
^<HOST> .*"(GET|POST) /wp-admin/.*"
# We don't want to ban people on asset requests, just the authentication requests
ignoreregex = ^<HOST> .*"(GET|POST) /wp-admin/(images|js|css)/.*"
/etc/fail2ban/jail.local
[wordpress-login]
enabled = true
filter = wordpress-login
port = http,https
logpath = /var/log/nginx/*.access.log
action = iptables-multiport[name=http, port="http,https", protocol=tcp]
maxretry = 10
findtime = 60
bantime = 3600
- The
logpathis utilizing a wildcard to scan all site access logs. - The
actionis specifying that we will use theiptablesof the firewall to restrict the requests.
Before booting this up, you can test your individual log files (I believe wildcard is not supported) to see if your filter is reading the “failures” correctly.
fail2ban-regex /var/log/nginx/my.access.log /etc/fail2ban/filter.d/wordpress-login.conf --print-all-matched
Though, keep in mind you’ll have to have logs that will match this filter regex to see anything here.
To Start:
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
To Stop:
sudo systemctl disable fail2ban
sudo systemctl stop fail2ban
To see how a specific jail is faring:
fail2ban-client status wordpress-login
and you’ll see something like:
Status for the jail: wordpress-login
|- Filter
| |- Currently failed: 156
| |- Total failed: 101134
| `- File list: /var/log/nginx/my.access.log ...
`- Actions
|- Currently banned: 0
|- Total banned: 1145
`- Banned IP list:
- Also check out the default
sshdjail, all you have to do is enable it.
