Configure Nginx Geolocation Filter to Block Traffic by Country or City

The following guide explains how to leverage the capabilities of the Nginx Geo Http Module to block access to your webserver based on Country or City.

Setting up Geoip2 Nginx Module

Install libmaxminddb libraries:

1
2
3
sudo add-apt-repository -y ppa:maxmind/ppa
sudo apt update
sudo apt install -y libmaxminddb0 libmaxminddb-dev mmdb-bin

Download and unpack the geoip2 module:

1
2
wget https://github.com/leev/ngx_http_geoip2_module/archive/3.3.tar.gz
tar -xvzf 3.3.tar.gz

Check your current nginx version:

1
2
nginx -v
> nginx version: nginx/1.16.1

Grab your version and replace it on the following commands:

1
2
3
4
version="1.16.1"
wget https://nginx.org/download/nginx-$version.tar.gz
tar -xvzf nginx-$version.tar.gz
cd nginx-$version

Build Geoip2 as a dymanic module:

1
2
3
./configure --with-compat --add-dynamic-module=./objs/ngx_http_geoip2_module.so
make
make modules

Copy the generated file to the nginx modules path (in Ubuntu /usr/share/nginx/modules/):

1
sudo cp /objs/ngx_http_geoip2_module.so /usr/share/nginx/modules/

Getting geoip2 databases

  1. Go to https://dev.maxmind.com and create a free account
  2. On your Account Summary section, find the Download Databases button.
  3. Download GeoLite Country and GeoLite City
  4. Create a folder where to extract the database files:
    1
    sudo mkdir -p /usr/share/GeoIP2
  5. Extract the compressed files on the created path. Make sure the .mmdb files are at the root of that folder.

Configuring Nginx to use GeoIp2 module

Add the following line to the nginx.conf file:

1
load_module /usr/share/nginx/modules/ngx_http_geoip2_module.so;

Add the following configuration into the nginx.conf file within the http section:

1
2
3
4
5
6
7
8
9
10
11
geoip2 /usr/share/GeoIP2/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_metadata_country_build metadata build_epoch;
$geoip2_data_country_code default=US source=$remote_addr country iso_code;
$geoip2_data_country_name country names en;
}
geoip2 /usr/share/GeoIP2/GeoLite2-City.mmdb {
auto_reload 60m;
$geoip2_metadata_city_build metadata build_epoch;
$geoip2_data_city_name default=London city names en;
}

In order to block traffic by Country, add the following configuration next:

1
2
3
4
5
map $geoip2_data_country_code $allowed_country {
default yes;
CN no;
IN no;
}

In order to activate the blocking filter, add the following lines to any server or location block:

1
2
3
if ($allowed_country = no) {
return 404;
}