Blocking Country and Continent with nginx GeoIP on Ubuntu 18.04

Globalization has made cyberattacks much easier 🙁 unfortunately. As a result, you may not want certain countries to visit your site if you mainly get malicious traffic from specific countries that overload your server and slow it down. In this tutorial we will be configuring nginx to use the latest GeoIP database and blocking a custom list of countries, continents or both from accessing your site using MaxMind GeoIP databases.

nginx GeoIP Database Installation Ubuntu 18.04

This tutorial assumes you already have nginx-extras installed on your system and have root access.

Install the necessary GeoIP database, GeoIP library and nginx GeoIP module

sudo apt-get install geoip-database-extra libgeoip1 libnginx-mod-http-geoip -y

After installing these packages we can update the MaxMind GeoIP databases to be the latest GeoIP2 data packaged in the GeoIP database format – thanks to Miyuru who keeps them updated. This is especially convenient because currently if you want to use the official GeoIP2 databases you would need to recompile nginx which can be quite the hassle.

cd /usr/share/GeoIP
mv GeoIP.dat GeoIP.dat.bak
wget https://dl.miyuru.lk/geoip/maxmind/country/maxmind.dat.gz
gunzip maxmind.dat.gz
mv maxmind.dat GeoIP.dat
mv GeoIPCity.dat GeoIPCity.dat.bak
wget https://dl.miyuru.lk/geoip/maxmind/city/maxmind.dat.gz
gunzip maxmind.dat.gz
mv maxmind.dat GeoIPCity.dat

To tell nginx where the GeoIP databases are located you need to add these lines into /etc/nginx/nginx.conf in your http { block

geoip_country /usr/share/GeoIP/GeoIP.dat;
geoip_city /usr/share/GeoIP/GeoIPCity.dat;

I put it at the top here

#WP-Bullet.com nginx configuration
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        multi_accept on;
}

http {
    # GeoIP databases
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    geoip_city /usr/share/GeoIP/GeoIPCity.dat;
    ...

Now we can block some countries and continents 😀

Blocking Countries by GeoIP Detection in nginx

The first thing we are going to do is make a list of the countries to block, you can put this in your http { block.

The full list of MaxMind GeoIP country codes in 2 letter format can be found here

# map the list of denied countries
map $geoip_country_code $allowed_country {
   default yes;
   # Pakistan
   PK no;
   # Ukraine
   UA no;
   # Russia
   RU no;
   # China
   CN no;
   }

Now we can block the country with this if statement

# block the country
if ($allowed_country = no) {
    return 444;
}

If you want to add a custom HTTP header to show the country you can do so with this snippet in the nginx server block.

add_header X-Country $geoip_country_code;

Now let's block some continents!

Blocking Continents by GeoIP Detection in nginx

The logic for blocking continents is very similar, for this however we need to use the GeoIP city database.

You can find a list of the countries and the continents to which they belong here.

Full list of MaxMind GeoIP Continents in 2 letter code:

AF
AN
AS
EU
NA
OC
SA

Here is the MaxMind GeoIP continent list with 2 letter country code mapped to the full continent name

AF - Africa
AN - Antarctica
AS - Asia
EU - Europe
NA - North America
OC - Oceania
SA - South America

We can use the same nginx map command logic for blocking continents!

# map the continents to block
map $geoip_city_continent_code $allowed_continent {
   default yes;
   # Antarctica
   AN no;
   # Asia
   AS no;
   }

In your server block you can add this if statement to block the continents via GeoIP for your custom continent block list.

# block the continents
if ($allowed_continent = no) {
    return 444;
}

If you want to add a custom nginx header showing the continent you can add this snippet in your server block

add_header X-Continent $geoip_city_continent_code;

As usual after you finish making any of these modifications you should test your nginx configuration

nginx -t

If the syntax is OK then reload nginx

service nginx reload

This is only the beginning of the possibilities with GeoIP detection with nginx using the GeoIP databases from MaxMind!
You can try playing with redirecting based on GeoIP as well and caching based on Geolocation.

Sources

Blocking Visitors from a Country nginx
nginx GeoIP module Documentation

13 thoughts on “Blocking Country and Continent with nginx GeoIP on Ubuntu 18.04”

    • Good idea! You can set a cronjob to do this quite easily every month or so. I’m not sure how often this database does get updated though. You will probably need to make sure nginx reloads after you update the database as well.

  1. Hello
    I wanted to block certain cities, since it passes the country block.

    so I put that in the nginx.conf file:

    map $geoip_city_code $allowed_city {
    default yes;
    # Singapore
    SG no;
    }

    when I type nginx -t

    I got this message:
    nginx: [emerg] unknown “geoip_city_code” variable
    nginx: configuration file /etc/nginx/nginx.conf test failed

    Do you have any ideas? 🙂

    Currently, I have this in the nginx.conf file
    # GeoIP databases
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    geoip_city /usr/share/GeoIP/GeoIPCity.dat;
    # map the list of denied countries
    map $geoip_country_code $allowed_country {
    default yes;
    # Pakistan
    PK no;
    # Ukraine
    UA no;
    # Russia
    RU no;
    # China
    CN no;
    }
    map $geoip_city_code $allowed_city {
    default yes;
    # Singapore
    SG no;
    }

  2. I’ve had this working on my previous server, now trying to set it up on a new server which should be more or less alike the old server. However, I’m getting:
    nginx: [emerg] unknown directive “geoip_country” in /etc/nginx/nginx.conf:37
    nginx: configuration file /etc/nginx/nginx.conf test failed

    any idea what’s causing this?

Comments are closed.