I posted some previous ideas on this that were okay, but they turned out to be less-than-idea solutions. They work, but one of the blogs I watch over is a bit busy, and having Fail2Ban watching the Apache access.log was putting excessive load on the CPU.
So here’s a nicer approach, but it needs a bit more fiddling:
As /etc/fail2ban/filters.d/apache-phpmyadmin.conf
[Definition] failregex = [[]client[]] (File does not exist|script ').*(phpMyAdmin|phpmyadmin|dbadmin|mysql|myadmin|w00t|muieblackcat|mysqladmin).* ignoreregex =
As /etc/fail2ban/filters.d/apache-wp-login.conf
[Definition] failregex = [[]client[]] WP login failed.* ignoreregex =
As /etc/fail2ban/filters.d/apache-wp-timthumb.conf
[Definition] failregex = [[]client[]] (File does not exist|script ').*(timthumb\.php).* ignoreregex =
The relevant sections of /etc/fail2ban/jail.local should be something like these. This allows a few failed logins, but only one attempt to hit a phpMyAdmin directory or the TimThumb exploit. But maxretry and findtime can be whatever you want.
[apache-wp-login] enabled = true port = http,https filter = apache-wp-login logpath = /var/log/apache*/*error.log maxretry = 3 findtime = 120 [apache-phpmyadmin] action = %(action_mwl)s enabled = true port = http,https filter = apache-phpmyadmin logpath = /var/log/apache*/*error.log maxretry = 1 findtime = 60 [apache-wp-timthumb] action = %(action_mwl)s enabled = true port = http,https filter = apache-wp-timthumb logpath = /var/log/apache*/*error.log maxretry = 1 findtime = 60
So now all of the jails are watching error.log, which hopefully gets significantly less traffic than access.log. But we need to make sure WordPress logs the information we need.
If pretty permalinks is turned on, WP handles 404s and does not output to a log. Add a 404.php to the active theme that looks like this, or if there is already one, just add the error_log line:
And add this to the functions.php in your theme too, to handle the login attempts:
// Log login errors to Apache error log add_action('wp_login_failed', 'log_wp_login_fail'); // hook failed login function log_wp_login_fail($username) { error_log("WP login failed for username: $username"); }
Restart Fail2Ban server to pickup the changes, start some logging, and do some testing.
sudo service fail2ban restart tail -n 100 -f /var/log/fail2ban.log
REFERENCES
http://blog.somsip.com/2012/02/using-fail2ban-to-protect-wordpress/
http://blog.somsip.com/2012/01/protecting-wordpress-from-script-fishing-attacks-with-fail2ban-more/
http://blog.somsip.com/2011/12/protecting-wordpress-from-script-fishing-attacks-with-fail2ban/