Restricting xmlrpc.php

Earlier today, I saw some spikes on the load graph for the new server (where this site is hosted).

Upon checking the logs I saw a lot of these:

134.122.53.221 - - [01/May/2020:12:21:54 +0000] "POST //xmlrpc.php HTTP/1.1" 200 264 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
134.122.53.221 - - [01/May/2020:12:21:55 +0000] "POST //xmlrpc.php HTTP/1.1" 200 264 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
198.98.183.150 - - [01/May/2020:13:44:24 +0000] "POST //xmlrpc.php HTTP/1.1" 200 265 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
198.98.183.150 - - [01/May/2020:13:44:25 +0000] "POST //xmlrpc.php HTTP/1.1" 200 265 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"

I’m not mentioning the source IP owner, technical readers can look it up if they are interested. However, the second IP comes from a IP range that is rather interesting.

Searching the Internet, I found out that many people consider the xmlrpc.php as a problem. For those who are not familiar with WordPress, this file is responsible for external communications. For example when using the mobile application to manage your site, and also when you use Jetpack.

There are plugins to disable XML-RPC such as this one, but I use the app from time to time, so I would like to keep xmlrpc.php working.

The official Jetpack website provides this list for whitelisting purposes.

I have been restricting access to my /wp-admin URL for ages, using Nginx. I think it is a good idea to do the same for xmlrpc.php.

location ~ ^/(xmlrpc\.php$) {
    include conf.d/includes/jetpack-ipvs-v4.conf;
    deny all;
 
    include fastcgi.conf;
    fastcgi_intercept_errors on;
    fastcgi_pass php;
}

The simple script to update this IP list into Nginx configuration, that is consumed by the configuration above:

#!/bin/bash
 
FILENAME=jetpack-ipvs-v4.conf
CONF_FILE=/etc/nginx/conf.d/includes/${FILENAME}
 
wget -q -O /tmp/ips-v4.txt https://jetpack.com/ips-v4.txt
 
if [ -s /tmp/ips-v4.txt ]; then
  cat /tmp/ips-v4.txt | awk {'print "allow "$1";"'} > /tmp/${FILENAME}
 
  [ -s ${CONF_FILE} ] || touch ${CONF_FILE}
 
  if [ "$(diff /tmp/${FILENAME} ${CONF_FILE})" != "" ]; then
    echo "Files different, replacing ${CONF_FILE} and reloading nginx"
    mv -fv /tmp/${FILENAME} ${CONF_FILE}
    systemctl reload nginx
  else
    echo "File /tmp/${FILENAME} match ${CONF_FILE}, not doing anything"
  fi
fi
 
rm -f /tmp/ips-v4.txt

It can be periodically executed by cron so that when the IP list changes, the configuration gets updated.

Now, if any IP other than Jetpack tries to access /xmlrpc.php it will receive Error 403 Forbidden.

Have fun!

Moving Domains to Cloudflare

While clicking around in Cloudflare today, I found this button.

It got me into thinking about what I paid last year for a .com domain and this is what I see when I looked at the order history.

I was surprised to see the difference. At the current exchange rate, Cloudflare will only cost me MYR34.89 (US$8.03 with ICANN fee) for a .com domain, which is a saving of MYR40.33 per domain, per year.

Looking at all domains transferable to Cloudflare, this is what it would cost me if I renew them right now:

If I transfer them to Cloudflare, it will cost me US$60.28 (MYR261.93) per year, which is a saving of US$66.75 (MYR290.07) equivalent to a year of mid-size shared hosting in Malaysia, or a full year of hosting cost with my current cloud provider.

Mind. Blown. 🤯

Cloudflare offers at-cost pricing for registration and renewal of many TLDs, but unfortunately .name is not one of them so I won’t be able to move romantika.name to them. For now.

Happy New Year 2020

Yes, yes I know it is already April. The year 2020 has proven challenging not only to some of us but all of us globally. I hope everyone is staying safe with their loved ones.

Server Updates

I recently had to move this blog to a new server because:

  • The old server was an OpenVZ instance and it is not straightforward to upgrade the outdated OS, Ubuntu 14.04 which has reached the end of standard support.
  • Since Ubuntu 14.04 has reached the end of support, it was impossible to upgrade PHP. It was running PHP 5.5.9.
  • Since WordPress 5.4 requires at least PHP 5.6, it was impossible to upgrade from WordPress 5.1.4
  • The old hosting company decided to increase the hosting price by €20, which is not a small amount for a slow OpenVZ instance.

So I decided to move on to another hosting provider, this time I will have control over my own kernel and will be charged pay-per-use.

It has a smaller spec but different virtualization technology. The new server is on Ubuntu 18.04.4 with PHP 7.4.5.

Improvements I made on the new server are:

  • Use certbot on all hosted domains so that communication between Cloudflare and my server is always valid HTTPS
  • The site is now 100% HTTPS via Cloudflare. It can be served directly via HTTPS too.
  • All scripts are now pushed using Ansible
  • Git based updates for projects such as the automated prayer times

Many things have changed as well, such as better responsive themes and more robust plugins.

Historically, this blog was started in 2005 on WordPress version 1.5 and has moved through 5 different hosting providers.

Personal Update

Since my last post, I have moved through 6 different jobs. Time flies.

I am also older now so I don’t really have much energy to rant, but expect more mixed ramblings from me from time to time 😉

In Malaysia, the country has been in the Movement Control Order (MCO) for more than a month now and it is certainly a significant change in lifestyle.

Let’s hope that COVID-19 goes away as soon as possible so that we can live “the new normal”.

Until the next post, stay safe people, wherever you are.