Ajouter la GeoIP à Nginx Proxy Manager 1/2
En complément de la mise en place de Nginx Proxy Manager pour gérer vos redirections de sous-domaines vers les services que vous hébergez, nous allons voir comment ajouter les informations GeoIP à NPM, nous permettant de bloquer les visiteurs venant de certains pays et/ou de loguer la provenance de ces visiteurs.
La GeoIP est une technique permettant de localiser un utilisateur en se basant sur son adresse IP. Pour cela, nous nous appuierons sur des bases de données que Maxmind met à disposition gratuitement : GeoLite2. Ces bases gratuites sont moins précises que leurs versions payantes, mais seront largement suffisantes pour notre utilisation.
NPM n'intégrant pas les modules nécessaires dans l'image officielle, il va nous falloir mettre les mains dans le cambouis pour compiler et intégrer ces modules.
Prérequis
Pour cet article, nous allons partir d'un fichier docker-compose.yml
standard pour NPM :
version: '3.9'
services:
nginx-proxym:
container_name: nginx-proxym
image: jc21/nginx-proxy-manager:2.9.20
restart: always
volumes:
- /dockers/nginx-proxym/data:/data
- /dockers/nginx-proxym/letsencrypt:/etc/letsencrypt
ports:
- 80:80
- 443:443
- 81:81
environment:
TZ: "Europe/PARIS"
DB_SQLITE_FILE: "/data/database.sqlite"
Pour les volumes, j'ai opté pour un chemin absolu afin d'être plus clair dans les chemins utilisés, à vous d'adapter en fonction de votre configuration.
Vous noterez que le fichier utilise une base SQLite au lieu de MariaDB, c'est juste pour simplifier, tout ce que nous allons faire est indépendant de la base de donnée utilisée.
Préparations pour la compilation des modules
Afin de stocker les modules que nous allons compiler et le fichier de configuration nginx qui nous permettra de les charger, nous allons créer un dossier "modules" que l'on va monter comme volume dans le conteneur.
Voici la partie volumes modifiée de notre fichier docker-compose.yml
:
...
volumes:
- /dockers/nginx-proxym/data:/data
- /dockers/nginx-proxym/letsencrypt:/etc/letsencrypt
- /dockers/nginx-proxym/modules:/etc/nginx/modules
...
Nous allons créer un script compile-geoip2.sh
que nous allons placer dans le dossier data de NPM. Il va nous permettre d'installer les packages et fichiers nécessaires puis de compiler les modules pour notre version de Nginx.
On rend le script exécutable :chmod +x /dockers/nginx-proxym/data/compile-geoip2.sh
.
Modification de l'image NPM avec docker-compose
Afin de pouvoir compiler et exécuter les modules Geoip2 pour la version de Nginx présente dans l'image officielle de NPM, nous avons besoin d'installer quelques paquets systèmes supplémentaires : libmaxminddb0
et libmaxminddb-dev
.
Pour intégrer des paquets à un conteneur, deux possibilités existent :
- Faire notre propre image à partir de l'officielle (build) et y intégrer tout ce qu'il nous faut.
- Ou modifier le script de lancement du conteneur afin qu'il fasse l'installation des paquets avant le lancement de NPM.
J'ai opté pour la 2ème option, certes cela rallonge un petit peu le démarrage du conteneur, mais on a l'avantage de rester sur l'image officielle, ce qui est plus pratique pour les mises à jour (via watchtower notamment ...).
Nous allons donc créer un autre script entrypoint.sh
que nous allons placer dans le dossier data de NPM. Il va nous permettre, à chaque lancement de NPM, d'installer ces paquets et de lancer la compilation des modules s'ils ne sont pas présents où si la version de Nginx a changée lors d'une mise à jour de l'image officielle.
On rend le script exécutable : chmod +x /dockers/nginx-proxym/data/entrypoint.sh
.
On modifie notre fichier docker-compose.yml
pour écraser la configuration de l'entrypoint de l'image NPM. Pour cela, on ajoute une instruction :
...
nginx-proxym:
container_name: nginx-proxym
image: jc21/nginx-proxy-manager:2.9.20
entrypoint: "/data/entrypoint.sh"
restart: always
...
On relance le conteneur pour prendre en compte les modifications du compose et lancer la première compilation des modules : docker-compose restart
Il est possible de suivre les actions effectuées au lancement en regardant le log du conteneur : docker logs nginx-proxym
Chargement des modules
Une fois le conteneur lancé et la compilation finie, on retrouve nos modules dans le dossier /dockers/nginx-proxym/modules
.
/dockers/nginx-proxym/modules# ls -l
total 208
-rw-r--r-- 1 root root 0 déc. 13 23:59 ngx_geoip2_openresty-1.19.3.1
-rwxr-xr-x 1 root root 116032 déc. 13 23:59 ngx_http_geoip2_module.so
-rwxr-xr-x 1 root root 89632 déc. 13 23:59 ngx_stream_geoip2_module.so
Pour charger les modules compilés dans NPM, il suffit de créer un fichier geoip2.conf
dans le dossier modules :
Puis on recharge la configuration de nginx : docker exec -it nginx-proxym nginx -s reload
Pour voir la version de nginx utilisée lors de la compilation des modules, il suffit de regarder le nom du 3ème fichier présent dans le dossier modules.
Téléchargement et mise à jour des bases GeoLite
Pour obtenir les bases Geoip2 gratuites de Maxmind, il faut d'abord s'inscrire sur leur site. Ça se passe là : https://www.maxmind.com/en/geolite2/signup.
Créez votre compte et une fois celui-ci validé, vous pouvez vous connecter afin de générer une clé de licence qui servira par la suite : https://www.maxmind.com/en/accounts/current/license-key.
Afin de mettre à jour régulièrement les bases geoip, Maxmind propose une image docker très simple à utiliser. Il suffit de lui monter comme volume le dossier où l'on veut nos bases et de renseigner avec des variables d'environnement les informations de notre clé de licence.
On créé un nouveau répertoire geoip2
pour stocker nos bases dans le dossier data de NPM : /dockers/nginx-proxym/data/geoip2
.
Et voici la partie service que l'on peut rajouter au fichier docker-compose de NPM :
Il est possible de ne télécharger qu'une base suivant ce que l'on compte en faire :
- GeoLite2-ASN : Informations sur l'ISP à qui appartient l'IP.
- GeoLite2-Country : Geolocalisation de l'IP au niveau pays.
- GeoLite2-City : Geolocalisation de l'IP au niveau ville. (Inclue le niveau pays)
Une fois le conteneur lancé, on retrouve nos fichiers de base de données dans le répertoire /dockers/nginx-proxym/data/geoip2
.
/dockers/nginx-proxym/data/geoip2# ls -l
total 86220
-rw-r--r-- 1 root root 7541424 déc. 10 00:57 GeoLite2-ASN.mmdb
-rw-r--r-- 1 root root 74871506 déc. 10 00:57 GeoLite2-City.mmdb
-rw-r--r-- 1 root root 5862627 déc. 10 00:57 GeoLite2-Country.mmdb
Voici notre fichier docker-compose.yml
final pour la stack NPM GeoIP :
version: '3.9'
services:
nginx-proxym:
container_name: nginx-proxym
image: jc21/nginx-proxy-manager:2.9.20
entrypoint: "/data/entrypoint.sh"
restart: always
volumes:
- /dockers/nginx-proxym/data:/data
- /dockers/nginx-proxym/letsencrypt:/etc/letsencrypt
- /dockers/nginx-proxym/modules:/etc/nginx/modules
ports:
- 80:80
- 443:443
- 81:81
environment:
TZ: "Europe/PARIS"
DB_SQLITE_FILE: "/data/database.sqlite"
geoip-upd:
container_name: geoip-upd
image: maxmindinc/geoipupdate:latest
restart: unless-stopped
volumes:
- /dockers/nginx-proxym/data/geoip2:/usr/share/GeoIP
environment:
TZ: "Europe/PARIS"
GEOIPUPDATE_ACCOUNT_ID: XXXXXX
GEOIPUPDATE_LICENSE_KEY: "XXXXXXXXXXXXXXXXX"
GEOIPUPDATE_EDITION_IDS: "GeoLite2-City GeoLite2-Country GeoLite2-ASN"
GEOIPUPDATE_FREQUENCY: 12
GEOIPUPDATE_PRESERVE_FILE_TIMES: 1
Conclusion
Dans ce premier article, nous avons vu comment compiler les modules geoip2 pour la version nginx présente dans Nginx Proxy Manager et les charger afin de pouvoir les utiliser par la suite. Nous avons aussi vu comment télécharger et mettre à jour les bases de données GeoIP_Lite de Maxmind.
Tout est prêt pour utiliser les informations de GeoIP dans Ngnix Proxy Manager à des fins de blocage et/ou log. La configuration de tout ceci est abordée dans l'article suivant :
Si vous avez des questions ou simplement souhaitez échanger avec nous, n'hésitez pas à laisser des commentaires ou à venir sur notre groupe Telegram.