I have a client who was having chronic server downtime on GoDaddy. A customer support rep pointed me to the Resource Usage page on cPanel which showed the CPU was maxed out. When I investigated the Apache logs, I discovered that several of the sites on the server were under DDoS (distributed denial of service) attack targeting the xmlrpc.php and wp-login.php files. This is how I mitigated those attacks without using Cloudflare and without getting a bigger server.
How You Know You’re Under Attack
A DDoS attack can massively slow down the load time of your site or make the site completely inaccessible, with the browser spinner going forever until it eventually times out.
If you go into your web hosting control panel, there’s usually a place where you can see CPU usage. On GoDaddy Business Web Hosting, there’s a page on cPanel called “Resource usage”. If you click that, you’ll see your site’s CPU usage. Spikes in usage are a hint that you are under attack, especially if there is no other reason your site should be getting high traffic at the moment.
To really prove that you’re under attack, though, you’ll need to check out your server Apache access logs. In GoDaddy, this in cPanel in the Metrics section. Click “Raw Access” to get to your logs and then click on the website in your server with the largest log file (you can sort by clicking the Disk Usage header).
In the log file above, you can see something is probing wp-login.php and xmlrpc.php almost every second in various subdirectories of the site. If you see something like this, you know you’re under attack.
The knee-jerk solution to combating DDoS attacks is to use Cloudflare. That works, but it involves pointing your DNS at Cloudflare, and then pointing Cloudflare at your server. In my case, the DNS was controlled by the clients, so it would be a pain to get them to change it.
Another solution is to simply get more computing power on your server. But, this costs money, and in my mind is a form of defeat, since the attack isn’t really blocked.
XML-RPC is a service that is used for inter-site communications with your site that is mostly unused these days except during Jetpack setup. If you’re unsure of what it does, you should do some research to make sure that disabling it is OK with your site.
There are tons of articles online on how to disable WordPress’ XML-RPC file, but many of these methods do NOT mitigate DDoS attacks on that file!
There are several plugins that can disable XML-RPC, or you can add some code yourself in your functions.php to do it. While these do prevent access to your site via XML-RPC, they do not prevent WordPress resources (i.e., CPU) to be used when xmlrpc.php is visited. Thus, these do NOT mitigate DDoS attacks to xmlrpc.php!
There is also a popular snippet of code floating around that blocks XML-RPC from your .htacess file:
<Files xmlrpc.php> order deny,allow deny from all </Files>
When I tried this, and visited xmlrpc.php in my browser, I got redirected to my site’s “Not Found” page. While that is fine for blocking access, it still requires your server to go through all of the motions of loading WordPress and rendering up your “Not Found” page. I wanted to avoid all of that!
My Solution for Apache
I wanted to find a way to truly block attacks on xmlrpc.php and wp-login.php without using PHP or WordPress resources, thus sparing precious CPU bandwidth.
Blocking xmlrpc.php is one thing, but wp-login.php is actually needed to log into WordPress, so that can’t just be blocked!
In my case, the attacker was targeting wp-login.php in subdirectories such as “/old”, “/wp”, “/test”, “/blog”, and so on (you can see them in the log above). So, I could try to target wp-login.php in just those directories!
After lots of research and experimentation, I came up with this .htaccess code to do the blocking for xmlrpc.php and wp-login.php in specific directories:
# DDOS ATTACK MITIGATION BY BRIAN 2020-06-20 RedirectMatch 403 ^/old/wp-login.php RedirectMatch 403 ^/cms/wp-login.php RedirectMatch 403 ^/wp/wp-login.php RedirectMatch 403 ^/test/wp-login.php RedirectMatch 403 ^/blog/wp-login.php RedirectMatch 403 ^/backup/wp-login.php RedirectMatch 403 ^/wp1/wp-login.php RedirectMatch 403 ^/2019/wp-login.php RedirectMatch 403 ^/2020/wp-login.php RedirectMatch 403 ^/2021/wp-login.php RedirectMatch 403 ^/2022/wp-login.php RedirectMatch 403 ^/2023/wp-login.php RedirectMatch 403 xmlrpc.php ErrorDocument 403 forbidden
If you place this after the other code in your .htaccess file, it will return a 403 forbidden error for any attempt to access xmlrpc.php altogether, and wp-login.php in those particular directories only.
The last line is important to prevent displaying your site’s “Not Found” page in WordPress. With this code, WordPress is never loaded and the browser just displays “forbidden”.
You can confirm it’s working by trying to access xmlrpc.php or wp-login.php (in the specified directories) in your browser.
Note, this code is tailored to stop wp-login.php attacks in subdirectories. If you have attacks on this file in the root, it might be best to block all IP addresses to that file except your own, i.e., whitelisting.
Finally, this code works on Apache servers. You’ll need different code for NGINX.
After I implemented the .htaccess code above, my CPU usage went down to normal:
And, checking my log files, I saw that the attacks were now returning 403 instead of 200!
Another Example: Autodiscover Attack
I had another case where Outlook and someone’s mobile phone were trying to hit the /autodiscover/autodiscover.xml file on the server:
I blocked the whole directory with this:
# STOP AUTODISCOVER "ATTACK" 7/17/2020 BY BRIAN RedirectMatch 403 ^/autodiscover/.*
Blocking IP Addresses
Sometimes you’ll see attacks coming from a single or a small set of IP addresses. It’s easy to just block these IP addresses entirely.
First, check with your hosting provider. They usually have a place to do it. In GoDaddy, go to cPanel -> Security -> IP Blocker and simply enter the IP addresses.
If you want to block IP’s from your .htaccess file, you can do it with this line:
Deny from 18.104.22.168
Let me know if these worked for you. Do you have other solutions to block DDoS attacks on WordPress? Let me know in the comments below! – Brian