Cómo instalar y utilizar el módulo GeoIP2 en nginx

  • #nginx
  • #nodejs
  • #php

Si quieres geolocalizar a los visitantes de tu sitio web atento a este artículo, te enseñamos como lograrlo utilizando GeoIP2 y nginx.

MaxMind es conocida en el mundo del desarrollo web por ser la empresa que ofrece el módulo GeoIP y bases de datos tanto gratuitas como de pago, para geolocalizar las visitas que llegan a nuestro sitio web.

GeoIP para localizar a tus usuarios

Hace un tiempo lanzó un nuevo módulo, GeoIP2, con algunas mejoras interesantes y un nuevo formato .mmdb.

El funcionamiento es bastante similar a la antigua versión (ahora Legacy), y las mejoras no son tan sustanciales para el usuario común como para necesitar una actualización, pero os vamos a ayudar a integrar este nuevo módulo en Nginx utilizando un reciente aporte de la comunidad: ngx_http_geoip2_module.

Instalando el módulo de nginx

A parte de las instrucciones para el resto de distribuciones y aprovechando que nos encanta Gentoo, os ofrecemos un ebuild e instrucciones para ésta.

Todas las distribuciones

Lo primero que necesitamos es compilar la librería creada por MaxMind para leer este nuevo formato de bases de datos.

Podemos encontrarla en https://github.com/maxmind/libmaxminddb y se instala de la siguiente manera:

./configure
make
make check
sudo make install
sudo ldconfig

Esta librería también puede instalarse mediante git clone, brew install o aptitude install. Consulta la documentación en el enlace anterior para más información.

El siguiente paso es descargar el módulo de nginx desde https://github.com/leev/ngx_http_geoip2_module y compilamos nuevamente nginx con los siguientes comandos:

./configure --add-module=/path/to/ngx_http_geoip2_module
make
make install

Gentoo

En Gentoo hemos creado un ebuild para instalar todo esto de manera más rápida, fácil, y sobre todo, mediante emerge.

El ebuild lo podéis encontrar en https://github.com/whiledev/whiledev-overlay y es muy fácil instalarlo desde Layman. Si no tenéis instalado Layman, se hace mediante emerge -av layman.

Después sincronizamos Layman y añadimos el repositorio:

layman -S
layman -a whiledev

Editamos el fichero /etc/portage/make.conf y añadimos geoip2 a nuestra lista de módulos requeridos por nginx: NGINX_MODULES_HTTP="... geoip2 ...".

Tras esto, seguramente necesitemos añadir el keyword ~amd64 a nuestra lista de keywords aceptadas:

echo "dev-libs/libmaxminddb ~amd64" >> /etc/portage/package.accept_keywords
echo "www-servers/nginx ~amd64" >> /etc/portage/package.accept_keywords

Y por último, el esperado emerge -av nginx.

Instalando y configurando las bases de datos

Para utilizar el módulo necesitamos descargar las bases de datos gratuitas (o de pago) y guardarlas en algún lugar, por ejemplo /usr/share/GeoIP. Si no existe el directorio lo creamos y ejecutamos los siguientes comandos:

wget -O - http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz | gunzip -fc > /usr/share/GeoIP/GeoLite2-City.mmdb
wget -O - http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz | gunzip -fc > /usr/share/GeoIP/GeoLite2-Country.mmdb

El siguiente paso es conectar nginx con las bases de datos a través del módulo ngx_http_geoip2_module y la librería libmaxminddb. Sin entrar en mayor detalle, añadimos lo siguiente a nuestro fichero de configuración de nginx (generalmente /etc/nginx/nginx.conf):

http {
  # ...
  geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    $geoip2_data_country_iso_code country iso_code;
    $geoip2_data_country_name country names en;
    $geoip2_data_continent_code continent code;
    $geoip2_data_continent_name continent names en;
  }
  geoip2 /usr/share/GeoIP/GeoLite2-City.mmdb {
    $geoip2_data_city_name city names en;
    $geoip2_data_subdivision_iso_code subdivisions 0 iso_code;
    $geoip2_data_subdivision_name subdivisions 0 names en;
    $geoip2_data_postal_code postal code;
    $geoip2_data_location_latitude location latitude;
    $geoip2_data_location_longitude location longitude;
    $geoip2_data_location_metro_code location metro_code;
  }
  # ...
}

Si queremos que los nombres aparezcan en español, basta con cambiar names en por names es.

Utilizando GeoIP2

Ya podemos utilizar nuestras variables de GeoIP2 a través de nuestro back-end preferido. Aquí un par de ejemplos.

PHP

En el caso de PHP, retocaremos nuestro bloque de configuración de nginx para que quede más o menos parecido a esto:

location ~ \.php$ {
  include /etc/nginx/fastcgi.conf;
  fastcgi_param GEOIP_COUNTRY_CODE $geoip2_data_country_iso_code;
  fastcgi_param GEOIP_COUNTRY_NAME $geoip2_data_country_name;
  fastcgi_param GEOIP_CONTINENT_CODE $geoip2_data_continent_code;
  fastcgi_param GEOIP_CONTINENT_NAME $geoip2_data_continent_name;
  fastcgi_param GEOIP_CITY $geoip2_data_city_name;
  fastcgi_param GEOIP_REGION $geoip2_data_subdivision_iso_code;
  fastcgi_param GEOIP_REGION_NAME $geoip2_data_subdivision_name;
  fastcgi_param GEOIP_POSTAL_CODE $geoip2_data_postal_code;
  fastcgi_param GEOIP_LATITUDE $geoip2_data_location_latitude;
  fastcgi_param GEOIP_LONGITUDE $geoip2_data_location_longitude;
  fastcgi_param GEOIP_AREA_CODE $geoip2_data_location_metro_code;
  limit_conn phplimit 5;
  fastcgi_intercept_errors on;
  fastcgi_pass unix:/var/run/php-fpm.socket;
}

Y todo listo, ya podemos utilizar la geolocalización a través de PHP mediante las variables $_SERVER['GEOIP_COUNTRY_NAME'], $_SERVER['GEOIP_CITY'], etc.

Node.js

En el caso de Node.js, pasaremos nuestras variables desde nginx a Node.js de la siguiente forma:

upstream nodejs_app {
  server 127.0.0.1:3000;
}
location / {
  try_files $uri @nodejs_app;
}
location @nodejs_app {
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_set_header X-NginX-Proxy true;
  proxy_set_header X-GEOIP_COUNTRY_CODE $geoip2_data_country_iso_code;
  proxy_set_header X-GEOIP_COUNTRY_NAME $geoip2_data_country_name;
  proxy_set_header X-GEOIP_CONTINENT_CODE $geoip2_data_continent_code;
  proxy_set_header X-GEOIP_CONTINENT_NAME $geoip2_data_continent_name;
  proxy_set_header X-GEOIP_CITY $geoip2_data_city_name;
  proxy_set_header X-GEOIP_REGION $geoip2_data_subdivision_iso_code;
  proxy_set_header X-GEOIP_REGION_NAME $geoip2_data_subdivision_name;
  proxy_set_header X-GEOIP_POSTAL_CODE $geoip2_data_postal_code;
  proxy_set_header X-GEOIP_LATITUDE $geoip2_data_location_latitude;
  proxy_set_header X-GEOIP_LONGITUDE $geoip2_data_location_longitude;
  proxy_set_header X-GEOIP_AREA_CODE $geoip2_data_location_metro_code;
  proxy_pass http://nodejs_app;
  proxy_redirect off;
}

Si utilizamos el framework Express, accedemos a los datos mediante req.get('X-GEOIP_COUNTRY_NAME');, req.get('X-GEOIP_CITY');, etc.

Compartir en