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:
Los bloqueos se realizan con el módulo GeoIP, para comprobar si lo tenemos:
1 |
nginx -V |
Una vez hayáis comprobado que tenéis el módulo --with-http_geoip_module=dynamic, podemos continuar.
En caso contrario, lo podéis instalar con este paquete:
1 |
sudo apt install nginx-extras |
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. Nos aseguramos de tenerlas instaladas:
1 |
sudo apt install geoip-database libgeoip1 |
Las añadimos a Nginx en el archivo /etc/nginx/nginx.conf en el bloque http{}:
1 2 3 4 |
http { #GeoIP geoip_country /usr/share/GeoIP/GeoIP.dat; [...] |
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:
1 2 3 4 5 6 7 8 |
http { [...] map $geoip_country_code $paises_permitidos { default no; ES yes; # Si queréis añadir más países, los podéis añadir aquí } [...] |
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.
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.
El bloqueo se realiza en el bloque server{}:
1 2 3 4 5 6 |
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:
1 |
service nginx restart |
A partir de aquí, ya tendríamos bloqueada la página para todos los países excepto España.
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:
1 2 3 4 5 6 7 8 |
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{}:
1 2 3 4 5 6 7 8 9 10 |
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.
No olvidéis aplicar los cambios después de las configuraciones:
1 |
service nginx restart |
Este es el resultado final del bloque http{}:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
http { #GeoIP geoip_country /usr/share/GeoIP/GeoIP.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 } [...] |
Y este el del bloque server{} de nuestro dominio:
1 2 3 4 5 6 7 8 9 |
server { if ($redes_permitidas = yes) { set $paises_permitidos yes; } if ($paises_permitidos = no) { return 444; } [...] |
Si alguien hace una petición desde un país que tenemos bloqueado, la respuesta será una como esta:
Para cualquier duda podéis preguntar por los comentarios o por el grupo de Telegram de LiGNUx @liGNUx.
¡Hasta la próxima!