Block hacker attacks on WordPress’ xmlrpc.php

It you’re getting a ton of POST requests to your WordPress xmlrpc.php file, here’s a quick way to block all the bad ips via iptables. In my case I’m using nginx and php-fpm, but something very similar would also work for apache.

First, recognize the signature. Your access logs will look something like this:

5.135.68.51 - - [13/May/2015:12:14:59 -0400] "POST /xmlrpc.php HTTP/1.0" 499 0 "-" "Mozilla/5.0 (compatible; Googlebot/2.1;  https://www.google.com/bot.html)"
185.61.138.72 - - [13/May/2015:12:14:59 -0400] "POST /xmlrpc.php HTTP/1.0" 499 0 "-" "Mozilla/5.0 (compatible; Googlebot/2.1;  https://www.google.com/bot.html)"
185.11.147.17 - - [13/May/2015:12:14:59 -0400] "POST /xmlrpc.php HTTP/1.0" 404 168 "-" "Mozilla/5.0 (compatible; Googlebot/2.1;  https://www.google.com/bot.html)"
185.11.147.17 - - [13/May/2015:12:14:59 -0400] "POST /xmlrpc.php HTTP/1.0" 499 0 "-" "Mozilla/5.0 (compatible; Googlebot/2.1;  https://www.google.com/bot.html)"
185.62.188.76 - - [13/May/2015:12:15:01 -0400] "POST /xmlrpc.php HTTP/1.0" 499 0 "-" "Mozilla/5.0 (compatible; Googlebot/2.1;  https://www.google.com/bot.html)"
185.62.188.76 - - [13/May/2015:12:15:01 -0400] "POST /xmlrpc.php HTTP/1.0" 499 0 "-" "Mozilla/5.0 (compatible; Googlebot/2.1;  https://www.google.com/bot.html)"
185.62.188.76 - - [13/May/2015:12:15:01 -0400] "POST /xmlrpc.php HTTP/1.0" 499 0 "-" "Mozilla/5.0 (compatible; Googlebot/2.1;  https://www.google.com/bot.html)"
185.61.138.72 - - [13/May/2015:12:15:01 -0400] "POST /xmlrpc.php HTTP/1.0" 404 168 "-" "Mozilla/5.0 (compatible; Googlebot/2.1;  https://www.google.com/bot.html)"
5.135.68.51 - - [13/May/2015:12:15:02 -0400] "POST /xmlrpc.php HTTP/1.0" 499 0 "-" "Mozilla/5.0 (compatible; Googlebot/2.1;  https://www.google.com/bot.html)"
5.135.68.51 - - [13/May/2015:12:15:02 -0400] "POST /xmlrpc.php HTTP/1.0" 404 168 "-" "Mozilla/5.0 (compatible; Googlebot/2.1;  https://www.google.com/bot.html)"

Googlebot will NOT be POSTing your xmlrpc.php like that. Next the trick is to figure out which IP addresses are harassing you. Run this in your terminal:

$> grep xmlrpc /var/log/nginx/access.log | cut -d' ' -f1 | sort | uniq -c | sort -rn | head
  29200 185.11.147.17
  17182 185.62.188.76
  10657 185.61.138.72
   8183 5.135.68.51
   1914 192.227.175.122
   1738 195.154.185.116
   1198 43.252.228.132
    501 205.234.152.218
    155 86.105.212.68
    103 141.138.157.95

Most likely all of these are hackers since it would be unlikely even Jetpack or some other WordPress service would hit your xmlrpc.php that frequently. But you can decide where the cut off should be by adding -n# the the head request above. In my case I chose head -n8 like so:

$> grep xmlrpc /var/log/nginx/access.log | cut -d' ' -f1 | sort | uniq -c | sort -rn | head -n8
  29200 185.11.147.17
  17182 185.62.188.76
  10657 185.61.138.72
   8183 5.135.68.51
   1914 192.227.175.122
   1738 195.154.185.116
   1198 43.252.228.132
    501 205.234.152.218

Sooo …. now you just need to wrap that in a loop that will create the iptable rules to block traffic from the ips:

$> for ip in $(grep xmlrpc /var/log/nginx/access.log | cut -d' ' -f1 | sort | uniq -c | sort -rn | head -n8 | awk '{print $2}'); do iptables -A INPUT -s $ip -j DROP; done

No more hackers.

How to Be a Good WordPress Developer?

Pippin has some thoughts. I concur with most of them, especially the one about challenging yourself. The best self-taught developers are those who become obsessed with solving problems. They can’t stop themselves. They might get discouraged and walk away from the computer in disgust. But a few minutes later they’ll think “but I haven’t try this” and be right back at it.

Good developers surround themselves with people who know more than they do. They have no real desire to show how smart they are but would rather learn something smart from others. If you can let your pride go and be ok being the dumbest person in a room full of the smartest people ( as opposed to being the smartest in the room ) you’ll be better than you’d ever imagined otherwise. Plus people will like working with you which helps .

If your looking for a more “skill” based assessment of what it takes to be a developer, this is a pretty good article. Specifically, I like the notion of “problem decomposition,” which is a fancy way to say troubleshooting.

A key aspect of solving a problem ( and thus being a good developer ) is not getting handcuffed by what you don’t know. Obviously, if you knew you wouldn’t have a problem. But just because you don’t know what is causing a specific issue doesn’t mean you know nothing. I often start troubleshooting by clarifying and confirming what I do know.

For instance,  if WordPress gives me an “Error establishing a database connection” screen: What do I know? Do I know my username and password are correct? Can I confirm that by connecting to mysql via the command line or PhpMyAdmin? Do I know that mysql is running on the server?  Again does phpmyadmin work? Does my hosting dashboard have a mysql “status” icon”? Or does <code>service mysql status</code> return something? So on and so forth.

Confirming what you know sometimes exposes that what you think you know may not actually be true. And if it is true, it helps you focus your theories of the problem on areas that really are unknown. Like anything else, the more you decompose problems the better you’ll be at it.

SVN Tips That Saved My Ass Once

Ever need to deploy a version controlled site that overwrites existing files? This is common when taking a site from un-versioned to versioned.

First checkout the files using the force option.

svn checkout --force https://vanwinkle.somesvnserver.com/trunk/ ./

This will force the checkout process to complete, but your old files will not really be overwritten. Instead they will be considered modified version of the corresponding file in the repo. So to complete the process you need to do:

svn revert -R ./

This tells subversion to “revert” the files in the existing directory to the versioned state. The -R tells it to do this recursively and the ./ tells it to start in the current directory.