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:
- Requisitos previos
- Configurar Nginx
- Añadir las bases de datos
- Definir países/ciudades a bloquear
- Bloquear peticiones
- Permitir acceso desde la red local
- Resultado
Requisitos previos
Los bloqueos se realizan con el módulo GeoIP, para comprobar si lo tenemos:
nginx -V
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
}
[...]
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;
}
[...]
Si alguien hace una petición desde un país que tenemos bloqueado, la respuesta será una como esta:
Fuente: lignux