Tutorial: WordPress brute-force login protection with SSHGuard

SSHGuard 2.1 was just released, and in this release SSHGuard gained the ability to detect and block brute-force login attempts against WordPress. Here is how you get started with using SSHGuard to protect WordPress.

Some prerequisites before you begin on this quick tutorial:

  • You should already have installed and configured SSHGuard (Fedora Linux instructions; generic instructions). Check for SSHGuard version 2.1 or newer in your package repository, or install it from source if it’s not available in your main package repository.
  • Your web server must be storing its access logs in NCSA Common Log Format (CLF). Most web servers either do this by default (like Apache Web Server and Nginx), or can be configured to output to this format. Extended formats with extra data fields at the end are also supported.
  • Your server logs must contain the real remote IP address for it to be effective. Make sure you don’t accidentally log the IP address of your upstream caching proxy or a CDN in lieu of the actual remote address.
  • Please note that using log buffering, such as the BufferedLogs option in Apache, will delay logs and thus reduce SSHGuard’s responsiveness.

All you need to do after having configured SSHGuard is to feed it your server logs. Here you’ve a few different options.

Selective logging of WordPress attacks

Depending on the traffic load of your web server, you may not want to keep an all-inclusive access log as this may negatively affect performance of your web server and SSHGuard. Instead you can configure selective logging of any relevant requests in a separate log file.

The following configuration snippet demonstrate how you setup logging of request to wp-login.php only with the CustomLog directive in Apache HTTP Server:

SetEnvIf Request_URI "/wp-login\.php"$ wordpresslogins
CustomLog "/var/log/httpd/wordpress-logins.log" common env=wordpresslogins

The next configuration snippet shows the same for Nginx:

location "/wp-login\.php" {
  access_log "/var/log/httpd/wordpress-logins.log";

You can then feed the log file /var/log/httpd/wordpress-logins.log to SSHGuard using the FILES configuration option. At this point you’re finished. You’ll still want to read the section about XML-RPC below.

Remember to disable XML-RPC

SSHGuard doesn’t support blocking brute-force attacks against the XML-RPC service in WordPress. Such attacks can be massively amplified with hundred of login attempts per single server request without leaving any distinct signature in your server logs.

Unless you use the Jetpack plugin or one of WordPress’ mobile apps, you should disable the XML-RPC service altogether. The XML-RPC service leaves your website vulnerable to many types of attacks. It’s important to the wider WordPress ecosystem with apps and add-on services, but it’s not essential to WordPress itself. The best option is just to disable it altogether when possible.

You can disable XML-RPC by blocking all remote access to /xmlrpc.php in your web server configuration.