Restrict Access to WordPress with Nginx and GeoIP

Written by

in

, ,

The goal of this post is to harden your WordPress dashboard by preventing logins from countries where you know you will never be connecting. Since brute-force login attempts may still originate from an allowed country, it would be wise to combine this with other tools like fail2ban or one of the numerous plug-ins that add login rate-limiting restrictions to WordPress.

This example targets Nginx on CentOS 7 using PHP 7 from the Remi repo. Settings may vary depending on your exact setup, so watch out for differences from your config, and back up your /etc/nginx first!

First make sure you keep an up-to-date GeoIP database by running a script like the example below via a nightly cron job.

#!/bin/bash

/bin/curl https://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz -o /tmp/GeoIP.dat.gz

/bin/gunzip -c /tmp/GeoIP.dat.gz > /etc/nginx/GeoIP.dat

/bin/rm -f /tmp/GeoIP.dat.gz

Make sure the GeoIP module is installed:

yum install nginx-mod-http-geoip

Make sure the module is loaded in /etc/nginx/nginx.conf:

load_module modules/ngx_http_geoip_module.so;

Inside of http { } in nginx.conf, add this, modifying country and default as desired:

geoip_country /etc/nginx/GeoIP.dat;
map $geoip_country_code $allowed_country {
   default no;
   US yes;
}

And finally add the necessary location statement in your virtual host’s server { }. In this example I’m using PHP 7.1 from the Remi repo, so your configuration may vary.

location ~ ^/(wp-admin|wp-login.php) {
 try_files $uri $uri/ /index.php?$args;
 # try_files $uri =404;
 fastcgi_pass unix:/var/run/php-fpm/php71-fpm.sock;
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 include fastcgi_params;
 index index.html index.htm index.php;
 if ($allowed_country = no) {
 return 444;
 }
}