Protecting Apache webservers from WordPress admin login dictionary attacks with fail2ban

A better solution has been posted here but I’ll leave this post up too.

A very popular webserver I administer has been getting more attention from the script kiddies, and the Apache access log has been filling up with repeated hits to “POST wp-login.php” as scripts cycle through dictionary attacks. So it was time to invest some time in better security. And fail2ban seemed to be the way to go.

Installation is simple on Ubuntu as it’s supplied as a package:

sudo apt-get update
sudo apt-get install fail2ban

By default under version 0.8.2, only sshd protection is auto enabled. I’ve also enabled the apache-noscript filter included in the package, and so far have just added an additional filter to block the repeated attempts on WordPress admin login. This needs to allow a valid admin login, possibly one or two genuine password mistypes, and the self-referential redirect after login.


# Fail2Ban configuration file
# Author: Tim Connors
# $Revision: 668 $


# Option:  failregex
# Notes.:  Regexp to catch Apache dictionary attacks on Wrodpress wp-login
# Values:  TEXT
failregex = <HOST>.*] "POST /wp-login.php

# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
ignoreregex =

And added to /etc/fail2ban jail.local (don’t forget to copy jail.conf to jail.local after installation)


enabled = true
port    = http,https
filter  = apache-wp-login
logpath = /var/log/apache*/*access.log
maxretry = 5
findtime = 120

This seems to work okay, but maybe the timings need a bit of tweaking after testing.

  1. Thanks – that worked a treat…. :)

  2. Fail2ban filter for Wordpress | David Goodwin - pingback on April 17, 2013 at 2:58 pm
  3. We found through testing that the script listed above counted every login attempt whether or not they were successful. When several users would log into a WordPress site from a single location they would all get locked out. After testing the issue we noticed that Apache was returning a 200 code on unsuccessful login attempts and a 302 code on successful attempts. We changed the script to this:

    failregex = .*] “POST /wp-login.php HTTP/.*” 200

    This change caused fail2ban to ignore the successful logins and count the unsuccessful ones. We will continue watching it but for now it looks correct! Thanks for setting this up!

Leave a Comment

NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackbacks and Pingbacks: