NGINX Documentation

Restricting Access by Geographical Location

Introduction

NGINX Plus can differentiate users based on their geographical location. For example, you can have different website content for different countries, or you can restrict content distribution to a particular country or city.

NGINX Plus uses third-party MaxMind databases to match the IP address of the user and its location. As soon as the geoposition is known, it is then possible to use geoip-based variables in the map or the split_clients module.

Note MaxMind GeoLite Legacy databases are currently discontinued, MaxMind GeoIP2 or GeoLite2 databases and NGINX Plus GeoIP2 module should be used instead.

Restricting by geographical location works both for HTTP and TCP/UDP protocols.

Prerequisites

Configuring GeoIP2 in NGINX Plus

  1. Install the GeoIP2 dynamic module for NGINX Plus:

    For Amazon Linux, CentOS, Oracle Linux, and RHEL:

    $ yum install nginx-plus-module-geoip2
    

    For Debian and Ubuntu:

    $ apt-get install nginx-plus-module-geoip2
    

    For SLES:

    $ zypper install nginx-plus-module-geoip2
    
  2. Enable the GeoIP2 dynamic module in the NGINX Plus configuration file with the load_module directive specified in the main configuration level:

    load_module modules/ngx_http_geoip2_module.so;
    load_module modules/ngx_stream_geoip2_module.so;
    
    http {
        # ...
    }
    
  3. Obtain and unzip GeoIP2 or GeoLite2 databases from the MaxMind download page:

    In this example, the GeoLite2 free downloadable databases are used:

    $ wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz
    $ wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz
    $ gunzip GeoLite2-Country.mmdb.gz
    $ gunzip GeoLite2-City.mmdb.gz
    
  4. Add the paths to the country and city databases to the NGINX configuration with the geoip2 directive for http, stream, or both:

    http {
        #...
        geoip2 GeoIP2/GeoLite2-Country.mmdb;
        geoip2 GeoIP2/GeoLite2-City.mmdb;
        #...
     }
       
    stream {
        #...
        geoip2 GeoIP2/GeoLite2-Country.mmdb;
        geoip2 GeoIP2/GeoLite2-City.mmdb;
        #...
    }
    
  5. Use the standard variables from the GeoIP2 module to pass data to the map or split_clients directive.

    For example, using the geoip2_data_country_code variable and the map module, you can create another variable whose value will be the closest server basing on a continent location:

    #...
    map $geoip2_data_country_code $nearest_server {
        default default {};
        EU      eu;
        NA      na;
        AS      as;
        AF      af;
    #...
    

    Then you can choose an upstream server basing on the value passed in the $nearest_server variable:

    #...
    server {
        listen 12346;
        proxy_pass $nearest_server;
    }
     upstream eu {
        server eu1.example.com:12345;
        server eu2.example.com:12345;
    }
    upstream na {
        server na1.example.com:12345;
        server na2.example.com:12345;
    }
    #...
    

    If the continent is Europe, then the value of the $nearest_server will be eu, and the connection will be passed to the eu upstream via the proxy_pass directive.

Complete Example

This example can be applied in both the http and stream contexts.

 # can be either "http {" or "stream {"
    #...
    geoip2 GeoIP2/GeoLite2-Country.mmdb;
    geoip2 GeoIP2/GeoLite2-City.mmdb;
    map $geoip2_data_country_code $nearest_server {
        default default {};
        EU      eu;
        NA      na;
        AS      as;
        AF      af;
    server {
        listen 12346;
        proxy_pass $nearest_server;
    }
     upstream eu {
        server eu1.example.com:12345;
        server eu2.example.com:12345;
    }
    upstream na {
        server na1.example.com:12345;
        server na2.example.com:12345;
    }
}

In this example, the IP address will be checked in the GeoLite2-Country.mmdb and GeoLite2-City.mmdb databases, the result will be written to the geoip2_data_country_code variable. NGINX Plus will match the value of the variable against values in the map directive and white the result in the custom variable, in our example $nearest_server. Basing on the value of the $nearest_server, the proxy_pass directive will choose a corresponding upstream server.