WordPress websites are very common and so are people trying to hack them.  The XML-RPC attack where a hacker is constantly doing POST requests to xmlrpc.php is a common problem.  Every time I see this happening to a client, their server load shoots up to 50 or even 100 which cause the whole website and all requests to return very slow.

You’ll see something like this in your logs:

185.188.204.9 - - [18/Dec/2017:22:03:06 -0800] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
185.188.204.10 - - [18/Dec/2017:22:03:08 -0800] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
...
...

The only way to get the load down is to block xlmrpc.php, this can be done on Apache by adding to your WordPress Apache .htaccess file

Apache 2.2

<Files xmlrpc.php>
order deny,allow
deny from all
</Files>

Apache 2.4

<Files xmlrpc.php>
Require all denied
</Files>

Or Nginx configuration:

location = /xmlrpc.php {
     deny all;
}

Reload your Nginx configuration.

Once your do that the attacker will be blocked and the load will quickly drop down on the server.

I recently had to add another item, the customer had a 404 plugin installed on their website so even though the attacks were being denied, the requests were still getting bounced to index.php and causing a high load on the server. So i also added ad deny ip entry to block the network in question.

<Files xmlrpc.php>
Require all denied
</Files>

<Files index.php>
Require all granted
Require not ip 185.188.204.0/255.255.255.0
</Files>

Hope that helps you too.

****UPDATE****

If you’re running php-fpm with an Apache ProxyPass or ProxyPassMatch command you’re going to need to do it a little differently.  ProxyPass and ProxyPassMatch commands have higher precedence than other directives therefor they are run first.  Try using this example, where I exclude the two files from Proxy and then FilesMatch works correctly to block access.

<FilesMatch "^(xmlrpc\.php|wp-trackback\.php)">
Order Deny,Allow
Deny from all
</FilesMatch>

ProxyPassMatch ^/(wp-trackback.php)$ !
ProxyPassMatch ^/(xmlrpc.php)$ !
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/path/to/document/root/$1

You’ll see the “!” at the end that means exclude that proxy match, they must appear prior to the proxy rule that passes to PHP-FPM.

Those rules return a 403 to those hackers overloading my client’s server with constant hits to xmlrpc.php page

Clients tell me, I’ve installed one of the WordPress disable XML RPC plugins that are available, why am I still having a problem?  It’s because the attacker is still forcing php to execute which in turn makes a db hit every single time, and that is increasing the server load and slowing down your website.  You’re website is now secure, but it’s slow.

My preference is to use this method where hackers are blocked at Apache or Nginx.  When blocking at the web server this also keeps the overall load on the server at a minimum since it never even attempts to execute PHP or makes database requests.