Botnet attacks on WordPress have been a persistent problem over the last year. Botnets are made up of hacked sites and users, and typically the people hacked aren’t even aware that they are being used as a vector in an attack. Dealing with such attacks can be very frustrating as these users are very difficult to distinguish from legitimate visitors to your site.

There are 2 common approaches to mitigate these attacks.

Blacklisting – ban IPs

Whitelisting – restrict to IPs

Blacklisting

With blacklisting you start banning IP addresses after X false login attempts. This is usually done with a plugin like WordFence. WordFence also goes a step further by sharing a database of known botnet IPs and blocking them across all participating sites.

However, blacklisting such users brings its own set of problems of dealing with legitimate user complaints when they find out they have been banned.

The other problem is that Botnets are constantly evolving. Early attackers would try to brute force your site’s admin account. But now attackers have started parsing account names from your blog to guess plausible account names.

More sophisticated BotNets will pick the most common password and try it against 100s of known users, instead of using known passwords against a username. Thus getting around any maximum-attempt measures like CAPTCHAs and false attempt banning.

Even if you have managed to secure your wp-admin with hard to guess passwords, all these login attempts still hit MySQL. Thus causing memory usage to spike and in some cases even take your server offline.

Whitelisting

With whitelisting you only allow a select group of IPs access to wp-admin . This is usually done at the Apache/Nginx layer. The advantage this has over Blacklisting is the Botnets attempts are immediately blocked with a 403 Forbidden response.

This has one caveat, it is cumbersome if you access wp-admin from different IPs. You need to manage this list manually. And you aren’t always able to use a static IP!

You can get around this using a handy tool called sshuttle. The name is a bit of a tongue twister, I just call it ‘shuttle’.

Sshuttle works like a proxy to your WordPress server. Once you start sshuttle, Any webpage request from your browser gets routed via your WordPress server. This means your server sees your wp-admin request as originating from itself!

We can combine this by whitelisting wp-login.php access to the ip address of the server itself. With nginx a location block that denies everything but this IP does the trick.

location = /wp-login.php { allow XX.XX.XX.XX; // your site's IP deny all; }

Sshuttle can be installed with apt-get on Ubuntu or homebrew on Macs. Starting sshuttle from the command line enables the proxy.

sshuttle -r user@your-site.com:ssh_port 0/0

Then visit wp-admin on your site. Now only people who can sshuttle into your site can access the wp-admin.

An added bonus, by tunneling all your requests through SSH you can safely access wp-admin even over public wifi without worrying about FireSheep and it’s packet sniffing friends.