Bloqueo web por país origen con MaxMind, en Apache y Debian 9

Introducción

En esta entrada vamos a aprender como denegar accesos a nuestra página Web en un servidor Apache, filtrando por el país origen desde donde se está realizando la conexión.

Podemos encontrarnos situaciones en las que solemos recibir ataques de login por fuerza bruta, de MySQL Injection, por ejemplo, o que simplemente tienes una aplicación que solo vas a servir a direcciones IP nacionales. En todos estos casos filtrar por país origen nos puede ser de gran utilidad.

Vamos al lío!!!


Componentes

El escenario en donde aplicaremos este procedimiento consta de los siguientes componentes:

  • Servidor web Apache2 instalado en Debian 9.
  • Módulo libapache2-mod-geoip.
  • Base de datos GeoIP.dat.
  • Bloqueo en el archivo de configuración del dominio o en archivo .htaccess.

La base de datos se obtiene al instalar el módulo de Apache, pero en mi caso está bastante desfasada. Veremos como obtenerla a partir de las bases de datos gratuitas de MaxMind.

Se supone que ya tenemos un servidor Web, por lo que esta entrada solo se centra en el bloqueo del acceso y no en el despliegue del servidor.


Instalación

Para realizar la instalación seguiremos los siguientes pasos:

Librería mod_geoip

Primero instalamos la librería necesaria para realizar el bloqueo:

apt-get install libapache2-mod-geoip

No haría falta habilitar el módulo, aunque podemos comprobarlo con el siguiente comando y nos dirá si ya lo está o no:

a2enmod geoip

Configuración de Apache

Edita el siguiente archivo con tu editor favorito:

nano /etc/apache2/mods-available/geoip.conf

Descomentamos las siguientes líneas, en donde indicamos que se active la geolocalización y se consulte el archivo con la información de los paises:

<IfModule mod_geoip.c>
  GeoIPEnable On
  GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
</IfModule>

Como comenté en la sección anterior, esta base de datos GeoIP.dat está algo desfasada, ya que en mi instalación data del 12 de Mayo del 2017.

Reiniciamos el servidor Web:

/etc/init.d/apache2 restart

Confirmar la instalación

Ahora confirmamos que la instalación funciona. Imaginemos que tenemos nuestro dominio https://www.tiraquelibras.com instalado en un VirtualHost y cuyo DocumentRoot o directorio en donde se encuentra la Web es /var/www/html/www.tiraquelibras.com/.

Creamos el archivo geoip.php en el directorio del dominio. Usa tu editor favorito para ello:

nano /var/www/html/www.tiraquelibras.com/geoip.php

El archivo contiene el siguiente código, que ya se lo cutre que es pero nos vale para saber si funciona y obtener la IP origen y el código del país:

<html>
  <head>
    <title>mod_geoip</title>
  </head>
  <body>
    <?php
      echo "IP del origen: ".$_SERVER['REMOTE_ADDR']."<br>";
      echo "Código del continente: ".$_SERVER["GEOIP_CONTINENT_CODE"]."<br>";
      echo "Código del país: ".$_SERVER["GEOIP_COUNTRY_CODE"]."<br>";
      echo "Nombre del país: ".$_SERVER["GEOIP_COUNTRY_NAME"]."<br>";
    ?>
  </body>
</html>

El resultado sería el siguiente al acceder a la URL https://www.tiraquelibras.com/geoip.php:

Podemos ver como se indica la IP orgien, el código del país, en este caso ES, el cual usaremos para indicar a quién bloquearemos en el acceso a nuestra Web.


Bloqueo

Podemos aplicar el bloqueo del país origen en dos puntos distintos:

  • Dentro del archivo de configuración del dominio o del VirtualHost si lo tuviéramos configurado, en la configuración del servidor Web.
  • En el archivo .htaccess, ubicado en el directorio de la Web a proteger.

Ambas tendrán el mismo efecto.

En configuración del VirtualHost

Si aplicamos el bloqueo dentro del archivo de configuración del dominio o del VirtualHost debemos indicarlo en la sección en donde se especifica el directorio que aloja la página Web a proteger, tal y como se muestra a continuación. Por ejemplo, en nuestro caso sería dentro del archivo de Apache /etc/apache2/sites-available/www.tiraquelibras.com-le-ssl.conf, pero tu debes indicar el que corresponda a tu dominio.

En función de si queremos permitir o bloquear por país origen:

Permitir país origen y denegar el resto

<VirtualHost *:...

    <Directory /var/www/html/www.tiraquelibras.com>
        # Only allow specific countries
        GeoIPEnable On
        SetEnvIf GEOIP_COUNTRY_CODE ES AllowCountry
        Deny from all
        Allow from env=AllowCountry

    </Directory>

...
</VirtualHost>

Puedes indicar más de un país creando una línea independiente por cada uno de ellos.

Denegar país origen y permitir el resto

También podríamos indicar el país a bloquear en lugar del permitido, por ejemplo para bloquear únicamente China. En este caso no es necesario indicar que se permita al resto con la opción Allow from …, ya que de lo contrario no se aplicaría el bloqueo:

<VirtualHost *:...

    <Directory /var/www/html/www.tiraquelibras.com>
        # Only allow specific countries
        GeoIPEnable On
        SetEnvIf GEOIP_COUNTRY_CODE CH DenyCountry
        Deny from env=DenyCountry
    </Directory>

...
</VirtualHost>

Puedes indicar más de un país creando una línea independiente por cada uno de ellos.

Reiniciar servidor web

Ante cualquier cambio en la configuración recuerda reiniciar el servidor Web:

/etc/init.d/apache2 reload

Confirmar el bloqueo

En este caso permitiríamos únicamente las IPs con origen España ES rechazando el resto, como se indicó en el ejemplo anterior.

Si navegamos desde una IP ubicada en otro país no deberíamos de poder navegar. Para realizar esta prueba puedes consultar la siguiente publicación para hacer uso de un Proxy anónimo de la red Tor usando una Raspberry y Docker.

En este caso haremos uso de una IP ubicada en China, y por tanto no se permitirá el acceso a nuestra URL protegida:

IP               -  176.10.99.200
ContCode         -  EU
Continent        -  Europe
CounCode         -  CH
Country          -  Switzerland

Powered by https://www.tiraquelibras.com/blog

Sin embargo, desde una IP española sí estará permitido el acceso:

IP               -  85.152.18.44
ContCode         -  EU
Continent        -  Europe
CounCode         -  ES
Country          -  Spain

Powered by https://www.tiraquelibras.com/blog

En archivo .htaccess

Configuración de .htaccess

Dentro de la configuración de nuestro dominio configuramos el uso del archivo .htaccess en el directorio en donde se encuentre la página Web o DocumentRoot, en nuestro caso /etc/apache2/sites-available/www.tiraquelibras.com-le-ssl.conf:

...
<Directory /var/www/html/www.tiraquelibras.com>
        # Enable .htaccess
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
</Directory>
...

Y creamos el archivo .htaccess en nuestro directorio Web, en nuestro caso /var/www/html/www.tiraquelibras.com/.htaccess, con el siguiente contenido en función de si queremos permitir o bloquear por país origen:

Permitir país origen y denegar el resto

GeoIPEnable On
# Put countries to allow here
SetEnvIf GEOIP_COUNTRY_CODE ES AllowCountry

Deny from all
Allow from env=AllowCountry

Puedes indicar más de un país creando una línea independiente por cada uno de ellos.

Denegar país origen y permitir el resto

GeoIPEnable On
# Put countries to allow here
SetEnvIf GEOIP_COUNTRY_CODE US DenyCountry

Deny from env=DenyCountry

Puedes indicar más de un país creando una línea independiente por cada uno de ellos.

Reiniciar servidor web

Ante cualquier cambio en la configuración recuerda reiniciar el servidor Web:

/etc/init.d/apache2 reload

Confirmar el bloqueo

Para confirmar el bloqueo podemos realizar los mismos pasos que en el apartado anterior.


Actualizar la base de datos

Para actualizar la base de datos que consulta Apache para relaizar la geolocalización podemos hacer uso de las bases de datos gratuitas de MaxMind en formato .CSV, y posteriormente con un contenedor de Docker transformaremos este archivo a formato .DAT.

Pasos necesarios

Para poder descargarte las bases de datos de MaxMind y actualizar la base de datos que el servidor Web consultará, debes seguir los siguientes pasos:

  • Debes crearte una cuenta en su página web MaxMind.
  • Una vez accedas al portal debes ir a la sección Services -> My Licence Key y crear una nueva Key que llamaremos Apache2. Recuerda copiarla y guardarla ya que solo se muestra una vez y no se puede recuperar:
  • Una vez creada la Key procedemos a la descarga de la base de datos en formato .ZIP desde la sección de MaxMind.
  • Con Docker obtenemos el archivo GeoIP.dat a partir del .CSV descargado según esta herramienta publicada en este enlace de GitHub. Nosotros llamaremos al archivo final GeoIP-MaxMind.dat. A continuación explicaremos como obtener la imagen y arrancar el Container.
  • Movemos o indicamos al servidor Web dónde se encuentra el nuevo archivo.

Archivo final con Docker

Una vez tengamos descargado el archivo debemos transformarlo al formato que consulta el servidor Web, y para ello hay una herramienta que lo hará por nosotros de manera muy sencilla.

Pdemos descargar la herramienta publicada en la URL de GitHub de dos formas:

  • Descargando la herramienta con el comando wget https://github.com/sherpya/geolite2legacy/archive/master.zip y descomprimiendo el archivo descargado.
  • Clonando la herramienta con el comando git clone https://github.com/sherpya/geolite2legacy.git.

Una vez descargado podemos crear la imagen de Docker desde el archivo Dockerfile que viene incluido en el repositorio, usando el siguiente comando:

docker build -t geolite2legacy .

La imagen resultante quedará creada y lista para ser utilizada, con el nombre geolite2legacy indicado en el comando anterior.

docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
geolite2legacy      latest              761a7e8f1ba6        5 days ago          178MB

Si quisiéramos ejecutar el comando de forma manual para obtener el archivo final, ejecutaríamos el siguiente comando, utilizando el archivo .ZIP de MaxMind descargado y el nombre del archivo final, en nuestro caso GeoIP-MaxMind.dat:

docker run -it -v $(pwd):/src geolite2legacy:latest -i /src/GeoLite2-Country-CSV.zip -o /src/GeoIP-MaxMind.dat

Automatizar actualización de la base de datos

Todo esto lo podemos obtener en el siguiente script de BASH, que llamaremos updateMaxMindCSV.sh, pero recuerda indicar la Key de MaxMind, generada anteriormente, dentro del archivo:

#!/bin/bash

### Variables

# DB file path
db_path='dbs'

# DB file name
#country_file='GeoLite2-Country-Locations-en.csv'

# DB file downloaded compresed
country_file_gz='GeoLite2-Country.zip'

# Max Mind Legacy file
maxMind_dat='GeoIP-MaxMind.dat'

# Max Mind token
maxMind_token='INDICA_TU_TOKEN_AQUI'

# URLs to download all databases (City, Country, ASN)
country_url="https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country-CSV&license_key=$maxMind_token&suffix=zip"

# Apache2 GeoIP path
apache_path='/usr/share/GeoIP/'

### Getting all files

# Country
wget -c $country_url -O $country_file_gz
if [ $? != 0 ];then
        echo "Failed gettig $country_file_gz MaxMind database"
        exit 1
fi


### Getting MaxMind Legacy Database from .ZIP file donwloaded
docker run -v $(pwd):/src geolite2legacy:latest -i /src/$country_file_gz -o /src/$maxMind_dat


### Copy file to Apache2 GeoIP path
cp $maxMind_dat $apache_path


### Deleting all files downloaded
rm -rf ./$country_file_gz ./$maxMind_dat

exit 0

La única diferencia con el comando manual de Docker es que en el script debemos de quitar el modo interactivo (-it) para evitar errores con archivos no existentes, los cuales le pasamos al Container como argumentos.

Le damos permisos de ejecución al archivo:

chmod 744 updateMaxMindCSV.sh

Si lo ejecutamos tendremos la base de datos en formato .DAT descargada a la última versión, y copiado al directorio en donde se encuenta el archivo GeoIP.dat original de Apache.

./updateMaxMindCSV.sh

En el directorio por defecto tendríamos el nuevo archivo generado:

ls /usr/share/GeoIP/
GeoIP.dat  GeoIP-MaxMind.dat  GeoIP-test.dat  GeoIPv6.dat

Programación de la descarga en el Cron

Si lo dejamos configurado en el Cron para que se ejecute el script de actualización un día a la semana, por ejemplo el miércoles, lo tendríamos siempre actualizado con la última versión publicada. Por ejemplo, para descargar y generar el archivo final en la madrugada de todos los miércoles de la semana:

crontab -e
...
02 19 * * 3 cd /usr/local/scripts/apacheGeoIp; ./updateMaxMindCSV.sh

Cambiar configuración de Apache

Ahora cambiamos la configuración del servidor Web para que use esta base de datos, editando el archivo /etc/apache2/mods-available/geoip.conf:

<IfModule mod_geoip.c>
  GeoIPEnable On
  #GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
  GeoIPDBFile /usr/share/GeoIP/GeoIP-MaxMind.dat
</IfModule>

Reiniciamos Apache y estaría funcionando:

service apache2 restart

Conclusión

Bloquear las conexiones por país origen nos puede ayudar a mantener nuestar Web protegida ante accesos no deseados, o incluso evitar que nos dejen inaccesible siendo el objetivo de ataques.


Enlaces de interés

MaxMind oficial

MaxMind bases de datos gratuitas disponibles

MaxMind códigos de paises

Transformar archivo .CSV a .DAT

Apache instalación módulo

Apache configuración de bloqueo en VirtualHost

Apache configuración de bloqueo en archivo .htaccess