Skip to content

kraloveckey/nginx-geoip2

ย 
ย 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

57 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

nginx-geoip2

nginx-geoip2 creates variables with values from the MaxMind GeoIP2 databases based on the client IP (default) or from a specific variable (supports both IPv4 and IPv6).

The module supports both nginx HTTP and stream contexts.

Note

See also: whoip โ€“ a self-hosted service for exposing IP information using MaxMind, GeoIP2 & Nginx that returns JSON/Plain data by IP. It demonstrates a complete real-world setup of this module.


Installing

First install libmaxminddb as described in its README.md.

Download nginx source

wget http://nginx.org/download/nginx-VERSION.tar.gz
tar zxvf nginx-VERSION.tar.gz
cd nginx-VERSION

Build as a dynamic module (nginx 1.9.11+)

./configure --with-compat --add-dynamic-module=/path/to/nginx-geoip2
make modules

This produces objs/ngx_http_geoip2_module.so. Copy it to your nginx module path, then add to nginx.conf:

load_module modules/ngx_http_geoip2_module.so;

Build as a static module

./configure --add-module=/path/to/nginx-geoip2
make
make install

With stream support

./configure --add-dynamic-module=/path/to/nginx-geoip2 --with-stream
# or static:
./configure --add-module=/path/to/nginx-geoip2 --with-stream

Download MaxMind GeoLite2 Database (optional)

The free GeoLite2 databases are available from MaxMind's website (requires signing up).


Example Usage

http {
    ...
    geoip2 /etc/maxmind-country.mmdb {
        auto_reload 5m;
        $geoip2_metadata_country_build metadata build_epoch;
        $geoip2_data_country_code default=US source=$variable_with_ip country iso_code;
        $geoip2_data_country_name country names en;
    }

    geoip2 /etc/maxmind-city.mmdb {
        $geoip2_data_city_name default=London city names en;
    }
    ...

    fastcgi_param COUNTRY_CODE $geoip2_data_country_code;
    fastcgi_param COUNTRY_NAME $geoip2_data_country_name;
    fastcgi_param CITY_NAME    $geoip2_data_city_name;
    ...
}

stream {
    ...
    geoip2 /etc/maxmind-country.mmdb {
        $geoip2_data_country_code default=US source=$remote_addr country iso_code;
    }
    ...
}

Reference

Metadata

Retrieve metadata about the GeoIP database.

$variable_name metadata <field>

Available fields:

  • build_epoch โ€“ build timestamp of the MaxMind database.
  • last_check โ€“ last time the database was checked for changes (requires auto_reload).
  • last_change โ€“ last time the database was reloaded (requires auto_reload).

auto_reload (default: disabled)

Nginx will check the modification time of the database at the specified interval and reload it if the file has changed.

auto_reload <interval>

Important โ€“ safe database update procedure: The database is mmap()'d into the nginx worker process. Never overwrite the file in place (e.g. with cp). Always write to a temporary file first, then atomically rename it:

cp GeoIP2-City.mmdb.new /data/geoip/GeoIP2-City.mmdb.tmp
mv /data/geoip/GeoIP2-City.mmdb.tmp /data/geoip/GeoIP2-City.mmdb

Using mv changes only the directory entry (inode pointer). The worker keeps its open file descriptor to the old inode until auto_reload closes it โ€“ the old mmap remains valid throughout. Overwriting the inode contents while it is memory-mapped causes SIGBUS (signal 7) and a worker crash.

GeoIP variable

$variable_name [default=<value>] [source=$variable_with_ip] path ...
  • If default is not specified, the variable will be empty when not found.
  • If source is not specified, $remote_addr is used for the lookup.

To find the data path you want, use mmdblookup:

$ mmdblookup --file /usr/share/GeoIP/GeoIP2-Country.mmdb --ip 8.8.8.8

  {
    "country":
      {
        "geoname_id":
          6252001 <uint32>
        "iso_code":
          "US" <utf8_string>
        "names":
          {
            "de":
              "USA" <utf8_string>
            "en":
              "United States" <utf8_string>
          }
      }
  }

$ mmdblookup --file /usr/share/GeoIP/GeoIP2-Country.mmdb --ip 8.8.8.8 country names en

  "United States" <utf8_string>

This translates to:

$country_name default="United States" source=$remote_addr country names en;

string_uriencode (default: off)

string_uriencode on;

When enabled, UTF-8 string values from the GeoIP database are percent-encoded before being placed into nginx variables. This prevents issues with non-ASCII characters (for example, Japanese city names like ลŒbu) being passed as raw UTF-8 bytes in HTTP headers, which can cause failures in strict upstream frameworks or libraries.

MaxMind began introducing more non-ASCII content in 2023 (see MaxMind release notes).

Proxy directives

These work the same as the original ngx_http_geoip_module. Note: if source=$variable is provided on a variable, these settings are ignored for that variable.

geoip2_proxy <cidr>;

Defines trusted addresses. When a request comes from a trusted address, the IP from the X-Forwarded-For header is used instead.

geoip2_proxy_recursive on | off;

When off, the last address in X-Forwarded-For is used. When on, the last non-trusted address in X-Forwarded-For is used.


Testing

See test/README.md for instructions on building and running a Docker container to test the module locally.

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • C 95.2%
  • Dockerfile 2.4%
  • Makefile 1.3%
  • Shell 1.1%