Viernes, Marzo 22, 2019

Nginx: Bloquear peticiones según ubicación geográfica con GeoIP

nginx-conf-geoip

Tengo un servidor Nginx en el que solo quiero tener acceso yo, pero siempre tengo muchas peticiones de otros países (China sobre todo), y es por esto que escribo este articulo, porque me parece interesante bloquear todas las peticiones de fuera de mi país y así reducir la posibilidad de cualquier problema.

Índice:

  1. Requisitos previos
  2. Configurar Nginx
    1. Añadir las bases de datos
    2. Definir países/ciudades a bloquear
    3. Bloquear peticiones
      1. Permitir acceso desde la red local
  3. Resultado

Requisitos previos

Los bloqueos se realizan con el módulo GeoIP, para comprobar si lo tenemos:

nginx -V

nginx-version-1

Una vez hayáis comprobado que tenéis el módulo with-http_geoip_module=dynamic, podemos continuar.

Configurar Nginx

Añadir las bases de datos

El módulo GeoIP (ngx_http_geoip_module) necesita unas bases de datos precompiladas de MaxMind que contiene los rangos de IPs por países y ciudades. Para utilizarlas, primero tenemos que descargar las BBDD (bases de datos) en la carpeta /etc/nginx/geoip:

mkdir /etc/nginx/geoip
cd /etc/nginx/geoip

wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz

gunzip GeoIP.dat.gz
gunzip GeoLiteCity.dat.gz

Y ahora las añadimos a Nginx en el archivo /etc/nginx/nginx.conf en el bloque http{}:

/etc/nginx/nginx.conf

http {
#GeoIP
geoip_country /etc/nginx/geoip/GeoIP.dat;
geoip_city /etc/nginx/geoip/GeoLiteCity.dat;
[...]

Definir países/ciudades a bloquear

Después de añadir las bases de datos, crearemos unas variables (con el módulo map) con los países bloqueados y permitidos en $paises_permitidos:

/etc/nginx/nginx.conf

http {
[...]
map $geoip_country_code $paises_permitidos {
default no;
ES yes;
# Si quereis añadir mas paises, los podeis añadir aqui
}
[...]

De esta manera, solo estaríamos permitiendo el acceso a las IPs españolas. Ya que con default no; bloqueamos a todos los países y con  ES yes; permitimos solamente a España.

  • $geoip_country_code → es una variable del módulo GeoIP, nos devuelve un código de país de dos letras, por ejemplo, “RU”, “US”
  • $paises_permitidos → es la variable que estamos creando con los países permitidos

Si quisierais bloquear por ciudades tendríais que utilizar  $geoip_city en vez de  $geoip_country_code y escribir en nombre de la ciudad permitida tal y como dice la documentación.

Bloquear peticiones

El bloqueo se realiza en el bloque server{}:

bloque server{} de tu dominio web

server {
[...]
if ($paises_permitidos = no) {
return 444;
}
[...]

Con este condicional devolvemos un estado HTTP 444 (estado HTTP especial de Nginx que cierra la conexión sin enviar ninguna cabecera HTTP) a los países de la variable $paises_permitidos que tengan el valor no.

Aplicamos los cambios:

service nginx restart

A partir de aquí, ya tendríamos bloqueada la página para todos los países excepto España.

Permitir acceso desde la red local

Igual habéis notado que al entrar a la página desde la red local también nos bloquea las peticiones, esto es porque los rangos de IPs de la red local no están en las bases de datos de MaxMind.

Para solucionarlo, primero tenemos que crear una variable con los rangos de nuestra red local usando el módulo geo:

/etc/nginx/nginx.conf

http {
[...]
geo $redes_permitidas {
default no;
127.0.0.0/8 yes; # Loopback
192.168.1.0/24 yes; # Nuestra red local
}
[...]

Y agregar $redes_permitidas con el valor  yes a $paises_permitidos con un condicional en el bloque server{}:

bloque server{} de tu dominio web

server {
[...]
     if ($redes_permitidas = yes) {
         set $paises_permitidos yes;
     }

     if ($paises_permitidos = no) {
         return 444;
     }
[...]

De este modo, estamos simulando que las redes que hemos definido en $redes_permitidas, están en la BBDD de MaxMind. Además reutilizamos el condicional if ($paises_permitidos = no) (que es quien realmente bloquea las peticiones) de nuestro bloque server{}.

Ahora, ya tenemos acceso desde la red local, y ya están bloqueadas las peticiones de fuera de nuestro país.

Resultado

No olvidéis aplicar los cambios después de las configuraciones:

service nginx restart

Este es el resultado final del bloque http{}:

/etc/nginx/nginx.conf

http {
                 #GeoIP
                  geoip_country /etc/nginx/geoip/GeoIP.dat;
                 geoip_city /etc/nginx/geoip/GeoLiteCity.dat;

                map $geoip_country_code $paises_permitidos {
                      default no;
                     ES yes;
               }

              geo $redes_permitidas {
                     default no;
                     127.0.0.0/8 yes; # Loopback
                     192.168.1.0/24 yes; # Red local
               }
[...]

nginx.conf-geoip

Y este el del bloque server{} de nuestro dominio:

bloque server{} de tu dominio web

server {
              if ($redes_permitidas = yes) {
                       set $paises_permitidos yes;
               }

              if ($paises_permitidos = no) {
                     return 444;
               }
[...]

server-block-conf-geoip

Si alguien hace una petición desde un país que tenemos bloqueado, la respuesta será una como esta:

test-nginx-geoip-1

Fuente: lignux

¿Quién está en línea?

Hay 240 invitados y ningún miembro en línea

Contador de Visitas

9623376
Hoy Hoy 500
Ayer Ayer 2202
Esta semana Esta semana 8679
Este mes Este mes 38721
Total de Visitas Total de Visitas 9623376

Día con más
visitantes

03-20-2019 : 2228

Gracias por su visita