Skip to content

Instantly share code, notes, and snippets.

@SoftCreatR
Last active May 30, 2021 15:01
Show Gist options
  • Save SoftCreatR/9d9723a5833dc2d1c4fe5635bbcc083d to your computer and use it in GitHub Desktop.
Save SoftCreatR/9d9723a5833dc2d1c4fe5635bbcc083d to your computer and use it in GitHub Desktop.
IP Address Information in pure nginx, using GeoIP2, JSON Var Module and some mapping magic.
#####
# IPInfo Host configuration
#
# Source: https://gist.github.com/SoftCreatR
#
# Requires:
# - ngx_http_json_var_module (https://github.com/SoftCreatR/nginx-json-var-module)
# - geoip2.conf (see below)
#####
include conf.d/geoip2.conf;
map $remote_addr $remote_addr_type
{
default "v4";
~: "v6";
}
json_var $ipinfo_json
{
ip $remote_addr;
type $remote_addr_type;
city_name $geoip_city_name;
zip_code $geoip_postal_code;
region_code $geoip_region_code;
region_name $geoip_region_name;
country_code $geoip_city_country_code;
country_name $geoip_country_name;
is_in_european_union $geoip_country_is_in_european_union;
continent_code $geoip_country_continent_code;
continent_name $geoip_country_continent_name;
lat $geoip_latitude;
lon $geoip_longitude;
timezone $geoip_timezone;
asn "AS$geoip_asn";
isp $geoip_aso;
}
map $request_uri $ipinfo_output_data_by_request
{
default $ipinfo_json;
~/ip $remote_addr;
~/city $geoip_city_name;
~/(zip|postal) $geoip_postal_code;
~/region $geoip_region_name;
~/country $geoip_country_name;
~/continent $geoip_country_continent_name;
~/lat $geoip_latitude;
~/lon $geoip_longitude;
~/loc "$geoip_latitude,$geoip_longitude";
~/timezone $geoip_timezone;
~/asn "AS$geoip_asn";
~/isp $geoip_aso;
~/org "AS$geoip_asn $geoip_aso";
}
server
{
listen *:80;
listen *:443 ssl http2;
# Define your hostname(s) here
server_name myip4.softcreatr.com
myip.softcreatr.com;
##
# Load additional config here, if needed.
##
location /
{
access_log off;
default_type "application/json";
add_header Access-Control-Allow-Origin "*";
return 200 "$ipinfo_output_data_by_request";
}
location ~ ^/(ip|city|zip|postal|region|country|continent|lat|lon|loc|timezone|asn|isp|org)$
{
access_log off;
default_type "text/plain";
add_header Access-Control-Allow-Origin "*";
return 200 "$ipinfo_output_data_by_request";
}
}
server
{
listen [::]:80;
listen [::]:443 ssl http2;
# Define your hostname(s) here
server_name myip6.softcreatr.com
myip.softcreatr.com;
##
# Load additional config here, if needed.
##
location /
{
access_log off;
default_type "application/json";
add_header Access-Control-Allow-Origin "*";
return 200 "$ipinfo_output_data_by_request";
}
location ~ ^/(ip|city|zip|postal|region|country|continent|lat|lon|loc|timezone|asn|isp|org)$
{
access_log off;
default_type "text/plain";
add_header Access-Control-Allow-Origin "*";
return 200 "$ipinfo_output_data_by_request";
}
}
#####
# GeoIP2 configuration
#
# Source: https://gist.github.com/SoftCreatR
#
# Requires:
# - ngx_http_geoip2_module (https://github.com/leev/ngx_http_geoip2_module)
# - libmaxminddb (https://github.com/maxmind/libmaxminddb)
# - GeoLite 2 databases (City, Country, ASN - https://dev.maxmind.com/geoip/geoip2/geolite2/)
#####
# GeoIP: Country
geoip2 /opt/geoip/GeoLite2-Country.mmdb
{
# continent
$geoip_country_continent_code continent code;
$geoip_country_continent_name_de continent names de;
$geoip_country_continent_name_en continent names en;
$geoip_country_continent_name_es continent names es;
$geoip_country_continent_name_fr continent names fr;
$geoip_country_continent_name_ja continent names ja;
$geoip_country_continent_name_pt_br continent names pt-BR;
$geoip_country_continent_name_ru continent names ru;
$geoip_country_continent_name_zh_cn continent names zh-CN;
# country
$geoip_country_is_in_european_union country is_in_european_union;
$geoip_country_code default=XX country iso_code;
$geoip_country_name_de country names de;
$geoip_country_name_en country names en;
$geoip_country_name_es country names es;
$geoip_country_name_fr country names fr;
$geoip_country_name_ja country names ja;
$geoip_country_name_pt_br country names pt-BR;
$geoip_country_name_ru country names ru;
$geoip_country_name_zh_cn country names zh-CN;
}
# GeoIP: City
geoip2 /opt/geoip/GeoLite2-City.mmdb
{
# city
$geoip_city_name_de city names de;
$geoip_city_name_en city names en;
$geoip_city_name_es city names es;
$geoip_city_name_fr city names fr;
$geoip_city_name_ja city names ja;
$geoip_city_name_pt_br city names pt-BR;
$geoip_city_name_ru city names ru;
$geoip_city_name_zh_cn city names zh-CN;
# continent
$geoip_city_continent_code continent code;
$geoip_city_continent_name_de continent names de;
$geoip_city_continent_name_en continent names en;
$geoip_city_continent_name_es continent names es;
$geoip_city_continent_name_fr continent names fr;
$geoip_city_continent_name_ja continent names ja;
$geoip_city_continent_name_pt_br continent names pt-BR;
$geoip_city_continent_name_ru continent names ru;
$geoip_city_continent_name_zh_cn continent names zh-CN;
# country
$geoip_city_country_code default=XX country iso_code;
$geoip_city_country_name_de country names de;
$geoip_city_country_name_en country names en;
$geoip_city_country_name_es country names es;
$geoip_city_country_name_fr country names fr;
$geoip_city_country_name_ja country names ja;
$geoip_city_country_name_pt_br country names pt-BR;
$geoip_city_country_name_ru country names ru;
$geoip_city_country_name_zh_cn country names zh-CN;
# location
$geoip_accuracy_radius location accuracy_radius;
$geoip_latitude location latitude;
$geoip_longitude location longitude;
$geoip_timezone location time_zone;
# postal
$geoip_postal_code postal code;
# subdivisions
$geoip_region_code subdivisions 0 iso_code;
$geoip_region_name_de subdivisions 0 names de;
$geoip_region_name_en subdivisions 0 names en;
$geoip_region_name_es subdivisions 0 names es;
$geoip_region_name_fr subdivisions 0 names fr;
$geoip_region_name_ru subdivisions 0 names ru;
}
# GeoIP: ASN
geoip2 /opt/geoip/GeoLite2-ASN.mmdb
{
$geoip_asn autonomous_system_number;
$geoip_aso autonomous_system_organization;
}
# Variables
map $http_accept_language $geoip_city_name
{
default $geoip_city_name_en;
~de $geoip_city_name_de;
~es $geoip_city_name_es;
~fr $geoip_city_name_fr;
~ja $geoip_city_name_ja;
~pt-br $geoip_city_name_pt_br;
~ru $geoip_city_name_ru;
~zh-cn $geoip_city_name_zh_cn;
}
map $http_accept_language $geoip_region_name
{
default $geoip_region_name_en;
~de $geoip_region_name_de;
~es $geoip_region_name_es;
~fr $geoip_region_name_fr;
~ru $geoip_region_name_ru;
}
map $http_accept_language $geoip_country_name
{
default $geoip_country_name_en;
~de $geoip_country_name_de;
~es $geoip_country_name_es;
~fr $geoip_country_name_fr;
~ja $geoip_country_name_ja;
~pt-br $geoip_country_name_pt_br;
~ru $geoip_country_name_ru;
~zh-cn $geoip_country_name_zh_cn;
}
map $http_accept_language $geoip_country_continent_name
{
default $geoip_country_continent_name_en;
~de $geoip_country_continent_name_de;
~es $geoip_country_continent_name_es;
~fr $geoip_country_continent_name_fr;
~ja $geoip_country_continent_name_ja;
~pt-br $geoip_country_continent_name_pt_br;
~ru $geoip_country_continent_name_ru;
~zh-cn $geoip_country_continent_name_zh_cn;
}
@SoftCreatR
Copy link
Author

Instead of using the JSON var module, you could simply create a variable by hand, containing valid JSON to return (which is more flexible than the module but not required in our case).

@SoftCreatR
Copy link
Author

SoftCreatR commented May 30, 2021

This may come in handy, if you want to add a route that matches IPv6 addresses:

location ~ "^/((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:)))(%.+)?$"
{
    # yadda
}

Example: https://myip.softcreatr.com/2605:8600:223:c497:6999:8ebc:1b9a:f216

For IPv4:

location ~ "^/((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]).){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"
{
    # yadda
}

Example: https://myip.softcreatr.com/79.181.52.28

And combined:

location ~ "^/((((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:)))(%.+)?$)|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]).){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]))"
{
    # yadda
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment