Fail2ban filter for WordPress

With the annoying brute force wordpress hack going round, one way to protect your site(s) would be to use fail2ban, with a configuration something like (which I’ve shamelessly lifted from ).

The below seems to be working, and given it’s relative simplicity it’s obvious how you’d go about changing to protect other POST based scripts from brute force attacks.

As with all fail2ban rules, it’s not going to work if the attacker changes IP often (but from scanning the logs so far, it doesn’t seem to be the case that they are).

Obvious caveats :

  1. Users who can’t remember their password(s) will get blocked.
  2. It’s not going to protect you from a distributed attack (multiple IPs) very well
  3. You may want to perform other counter-measures (like putting Apache http authentication in for URLs matching /wp-login.php)


In /etc/fail2ban/jail.conf :

enabled = true
port = http,https
filter = apache-wp-login
logpath = /var/www/vhosts/*/statistics/logs/access_log
maxretry = 5
findtime = 120

And In /etc/fail2ban/filter.d/apache-wp-login.conf :

failregex = <HOST> - - .* "POST /wp-login.php HTTP/.*" 200

ignoreregex =

Where a “hacking” access.log entry looks a bit like : - - [02/Feb/2014:12:50:01 +0000] "POST /wp-login.php HTTP/1.0" 200 4344 "-" "-"





12 responses to “Fail2ban filter for WordPress”

  1. […] para wordpress | Fail2Ban para Nginx | […]

  2. Jake V. Avatar

    This works great. I spent the last few days troubleshooting why fail2ban had quit working and ended up reinstalling it.

    In the process I expanded the functionality of the program.

    This jail alone caught over 1430 attempts at brute forcing our WP login page.

    Thanks for the write up.

  3. hurt138 Avatar

    Already got about 12 bans since putting this on yesterday.

    Works great!

    Thank you.

  4. Gavin Avatar

    I’ve been experimenting with Fail2Ban for blocking failed WP logins, and this method has a couple of drawbacks.

    1. the failregex succeeds for all POST’s to wp-login.php, so this will catch successful logins, as well as failed ones.

    2. the logpath should be set to also watch access_ssl_log , so that failed logins over https will also get caught

    Solutions (for Apache):
    Modify the filter failregex to something like this:
    failregex = .*] “POST /wp-login.php HTTP/.*” 200

    Apache will return a 200 response code for a failed login via POST, and a 302 for a successful one. So the above filter should only catch failed logins. Test carefully though.

    My server has Plesk 12, so the correct logpath would be:
    logpath = /var/www/vhosts/system/*/logs/access*_log

    This will watch access_log as well as access_ssl_log

    Earlier versions of Plesk may have the logs in a different location, so always check first.

    Hope that helps.

  5. David Goodwin Avatar

    Hi Gavin – thanks — I’ve updated the regexp above.

  6. […] seems quite useful – and certainly gives better control over abusive requests than using fail2ban (in that, only specific URLs/request types can be targeted and blocked with the throttle module, […]

  7. Paul Avatar

    It’s not recommended to modify fail2ban own conf-file.
    Cause You’ll loose your rules after an upgrade of it.
    Instead, use jail.local config file

  8. David Goodwin Avatar

    Yeah – But I think jail.local is distro specific (CentOS).
    Debian has a jail.d directory for example.

  9. Viktor Szépe Avatar

    Hello David!
    After years of involvement in WP security plugins I started analyzing real HTTP traffic.

    This is a WAF for WordPress with 60+ security checks also triggering Fail2ban:

  10. Holger Freier Avatar

    this code works

    failregex = .*POST.*(wp-login\.php|xmlrpc\.php).* 200

  11. […] – Bloquear ataques de fuerza bruta en Nginx y WordPress con fail2ban Fail2ban for NGinx Fail2ban for WordPress […]

Leave a Reply

Your email address will not be published. Required fields are marked *