joshtronic

Posted in Servers / Serverless tagged WordPress

You Might Not Need Plugins: WordPress Login Security with Fail2Ban

Becoming an insufferable self-hosting zealot has its ups and downs. Dealing with all of the bad actors in the world is a complete downer. That is, until you deploy a solution and get that hit of dopamine as you watch your server's CPU usage take a nose dive back to normal levels.

First major issue I deal with was extremely rude AI crawlers. Then damn near immediately after I migrated my WordPress sites over, it was brute force attempts to wp-login.php.

If I had to guess, next will be some brand new AI company that can't seem to properly vibe reading in robots.txt and actually respecting it.

The saga continues...

You know there's a plugin for that, right?

Oh, there are definitely plugins to help solve these security issues. Plugins to move your login files around to help obfuscate things. Plugins to handle limiting login attempts, handle velocity, and the like.

So many plugins, so little time. And you know there's some upgrade path in most of those plugins. These plugins are designed for folks that don't have direct server access, or simply don't know that most problems have already been solved with free software.

Old reliable technology to the rescue

If you don't already have fail2ban installed, I highly recommend that you do. It's a great piece of software, scanning your log files for sketchy behavior, and subsequently bans the offending parties. Out of the box, you get added security for a myriad of services (assuming you have them installed), including SSH.

To add additional filtering for WordPress troublemakers, you'll need to create a new file in filter.d and jail.d. The former will contain some RegEx to identify things, and the latter will define where to look and how to handle things.

Filter and find 'em

In addition to wp-login.php I also include xmlrpc.php as it's used for those nasty WordPress pingback DDoS attacks.

/etc/filter.d/wordpress.conf

[Definition]
failregex = ^ .* "(GET|POST) /+wp-login.php
            ^ .* "(GET|POST) /+xmlrpc.php

And lock 'em out

You'll want to tweak your logpath based on your setup, and can adjust the values below that to fit your needs.

/etc/jail.d/wordpress.conf

[wordpress]
enabled = true
port = http,https
filter = wordpress
action = iptables-multiport[name=wordpress, port="http,https", protocol=tcp]
logpath = /var/log/nginx/*.access.log
maxretry = 12
findtime = 120
bantime = 120

Restart and check that it's working

Of course, you'll want to restart fail2ban. If you're using systemd, you can do so as such: systemctl restart fail2ban.

To check that your wordpress.conf file is loaded up, you can run fail2ban-client status which should list out any active jails you have.

If you happened to be in the middle of an attack, and your CPU was elevated because of it, within a few moments of enabling the new jail, you should see a fairly immediate improvement.