One of our servers was recently hit by a distributed brute force login attack on WordPress' login page (wp-login.php). The distributed attack, coming from many different ip addresses, attempted gain access through brute force guessing of username & password combinations. The attack was simultaneously run on many of the websites on the same server that were running the WordPress content management system, which caused massive server overload to the point where the server was unresponsive.
It's difficult to stop these types of attacks because they keep coming from different IP addresses. Thus, a system admin can't just set up an ip tables firewall rule to block a single offending IP that keeps knocking at your door, as was done in a recent xml-rpc DoS attack on our servers. Blocking at the ip tables firewall is the least taxing on the server because the packets are dropped at the kernel level before any heavier applications are called.
With very strict "Brute Force" firewall settings of locking out ip addresses that create just one failed login attempt, WordFence was able to do a decent job of mitigating the attack. The attack was so distributed that there were literally hundreds of ip addresses blocked and each ip only tried logging in a couple times. Thus the previous "brute force" setting of allowing 10 failed login attempts per ip address was not sufficient for WordFence to kick in its protection mechanism. Because the distribution was so high, even with the single failure block-out, WordFence was only able to cut the load by about a third.
The strenuous part on the server is that WordFence is run in php, which on this server is run as a cgi process. Cgi processes tend to consume quite a bit of memory and processing power (more and more with each knock at the front door), so the the attack is still taxing the server, even though WordFence is dumping the login attempts as they come in.
Another line of defense may be to only allow access to the "wp-login.php" from specific ip addresses (or ip address range) through an Apache .htaccess file. Apache can then dump the requests before sending them to the php/cgi process where WordFence is run. Granted, this defense only works if you know the ip address(es) from which the website administrator(s) will be logging into WordPress.
Since most administrators are coming from connections with dynamically set ip addresses, a static .htaccess file protection mechanism probably isn't the most practical solution to implement. One could write a plugin or script that allows administrators to add their ip address to the .htaccess file by hitting a certain "secret" link.
For the time being we aren't going to go that far as with the stricter WordFence settings in place, WordFence was able to mitigate the attack. It appears as though the attacking bots/scripts did have some form of intelligence that they cut back their login attempts as many of the ip addresses started getting dumped to a page that indicated they were blocked from access to the login script.
The current down side is that the WordFence security settings are so high that if a legitimate user enters the wrong password, they will be locked out. In the case of this server, most of our clients are logging in through their browsers and have the browser saving the password, so they won't be entering the wrong username/password combination. But alas, as users will be logging in from other devices at times, they may get those devices locked out with a single mistype.
More commentary is in the video below:
This article was written swiftly and may not be comprehensive enough for a full understanding of all the items discussed. Please do request any clarifications or make any suggestions in the comments.