Tabla de contenidos
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 bases de datos gratuitas disponibles
Transformar archivo .CSV a .DAT