C’est quoi bunkerized-nginx ?
C’est un outil qui va vous éviter de devoir suivre les bonnes pratiques de sécurité à chaque fois que vous avez besoin d’un serveur web ou d’un reverse proxy en frontal de vos services web. Bunkerized-nginx se présente sous la forme d’une image Docker et va s’occuper des paramètres et configurations pour vous. Le but final est d’atteindre une sécurité « par défaut » sans (trop) d’action de votre part.
Sommaire
Liste non exhaustive des fonctionnalités :
- support du HTTPS et Let's Encrypt automatique ;
- bonnes pratiques de sécurité web : entêtes HTTP, éviter les fuites d’info, durcissement de TLS… ;
- ModSecurity intégré avec les règles OWASP Core Rule Set ;
- bannissement des comportements « suspects » avec fail2ban ;
- détection de robots avec des « challenges » (cookie, JavaScript, CAPTCHA…) ;
- blocage des nœuds de sortie TOR, des « mauvais » User-Agent, des pays de votre choix… ;
- blocage des IPs connues comme malveillantes via des listes noires externes (DNSBL, CrowdSec…) ;
- prévention des attaques par bruteforce en limitant les requêtes ;
- détection des fichiers « mauvais » avec ClamAV à l’upload;
- facile à configurer avec des variables d’environnement ou une interface web ;
- configuration automatique possible via des « labels » ;
- support de Docker Swarm.
L’outil permet de duper facilement les outils automatisés comme vous pouvez le voir ici.
Il y a une démo en ligne ici : demo bunkerized-nginx. N’hésitez pas à faire des tests de sécurité dessus.
Comment ça fonctionne ?
En lien avec PHP
docker network create mynet
docker run --network mynet \
-p 80:8080 \
-v /path/to/web/files:/www:ro \
-e REMOTE_PHP=myphp \
-e REMOTE_PHP_PATH=/app \
bunkerity/bunkerized-nginx
docker run --network mynet \
--name myphp \
-v /path/to/web/files:/app \
php:fpm
Les fichiers web sont stockés dans le dossier /www à l’intérieur du conteneur. Veuillez noter que bunkerized-nginx ne tourne pas en root (pour des raisons évidentes de sécurité) mais avec un utilisateur non privilégié ayant comme UID 101 et comme GID 101. Il faut donc mettre les droits sur /path/to/web/files en conséquence.
La variable d’environnement REMOTE_PHP
permet de définir l’adresse d’une instance PHP-FPM qui va exécuter les fichiers PHP. Tandis que la variable REMOTE_PHP_PATH
permet de définir le chemin utilisé par l’instance PHP-FPM pour chercher les fichiers.
HTTPS avec Let's Encrypt automatique
docker run -p 80:8080 \
-p 443:8443 \
-v /path/to/web/files:/www:ro \
-v /where/to/save/certificates:/etc/letsencrypt \
-e SERVER_NAME=www.yourdomain.com \
-e AUTO_LETS_ENCRYPT=yes \
-e REDIRECT_HTTP_TO_HTTPS=yes \
bunkerity/bunkerized-nginx
Les certificats sont stockés dans le répertoire /etc/letsencrypt à l’intérieur du conteneur. Il est conseillé de les stocker en local pour pouvoir les réutiliser en cas de redémarrage du conteneur. Veuillez noter que bunkerized-nginx ne tourne pas en root (pour des raisons évidentes de sécurité) mais avec un utilisateur non privilégié ayant comme UID 101 et comme GID 101. Il faut donc mettre les droits sur /where/to/save/certificates en conséquence.
Si vous ne voulez pas que bunkerized-nginx écoute en HTTP, vous pouvez rajouter la variable d’environnement LISTEN_HTTP=no
(seulement du HTTPS par exemple). Par contre, Let's Encrypt a besoin du port 80 pour résoudre les challenges, il faut donc garder la redirection.
Ici nous avons 3 variables d’environnement :
- SERVER_NAME
: il s’agit du FQDN de votre service (qui doit pointer vers l’adresse IP de votre serveur pour que Let's Encrypt fonctionne)
- AUTO_LETS_ENCRYPT
: active la création et le renouvellement automatique de certificats via Let's Encrypt
- REDIRECT_HTTP_TO_HTTPS
: active la redirection HTTP vers HTTPS
En tant que reverse proxy
docker run -p 80:8080 \
-e USE_REVERSE_PROXY=yes \
-e REVERSE_PROXY_URL=/ \
-e REVERSE_PROXY_HOST=http://myserver:8080 \
bunkerity/bunkerized-nginx
Il s’agit d’un cas assez simple où il n’y a qu’une seule application derrière le reverse proxy. Si vous en avez plus d’une, vous pouvez utiliser plusieurs fois les variables d’environnement REVERSE_PROXY_URL/REVERSE_PROXY_HOST en rajoutant un nombre à la fin comme ceci :
docker run -p 80:8080 \
-e USE_REVERSE_PROXY=yes \
-e REVERSE_PROXY_URL_1=/app1/ \
-e REVERSE_PROXY_HOST_1=http://myapp1:3000/ \
-e REVERSE_PROXY_URL_2=/app2/ \
-e REVERSE_PROXY_HOST_2=http://myapp2:3000/ \
bunkerity/bunkerized-nginx
Multisite
Par défaut, bunkerized-nginx va seulement créer une seule configuration « serveur » (un seul bloc « server » sera créé dans la configuration nginx). En mettant la variable d’environnement MULTISITE
avec la valeur yes
, une configuration « serveur » sera créée pour chaque hôte présent dans la variable d’environnement SERVER_NAME
. De plus, vous pouvez définir des configurations différentes pour chaque service en préfixant les variables par le FQDN comme ceci :
docker run -p 80:8080 \
-p 443:8443 \
-v /where/to/save/certificates:/etc/letsencrypt \
-e SERVER_NAME=app1.domain.com app2.domain.com \
-e MULTISITE=yes \
-e AUTO_LETS_ENCRYPT=yes \
-e REDIRECT_HTTP_TO_HTTPS=yes \
-e USE_REVERSE_PROXY=yes \
-e app1.domain.com_REVERSE_PROXY_URL=/ \
-e app1.domain.com_REVERSE_PROXY_HOST=http://myapp1:8000 \
-e app2.domain.com_REVERSE_PROXY_URL=/ \
-e app2.domain.com_REVERSE_PROXY_HOST=http://myapp2:8000 \
bunkerity/bunkerized-nginx
USE_REVERSE_PROXY
est donc appliquée « globalement » pour chaque serveur. Par contre les variables d’environnement app1.domain.com_*
et app2.domain.com_*
sont seulement appliquées pour app1.domain.com et app2.domain.com respectivement.
Quand bunkerized-nginx doit lire des fichiers et que MULTISITE
a pour valeur yes
, le répertoire /www contiendra un sous-dossier par service et chaque sous-dossier aura pour nom le FQDN correspondant dans la variable SERVER_NAME
. Prenons cet exemple :
docker run -p 80:8080 \
-p 443:8443 \
-v /where/to/save/certificates:/etc/letsencrypt \
-v /where/are/web/files:/www:ro \
-e SERVER_NAME=app1.domain.com app2.domain.com \
-e MULTISITE=yes \
-e AUTO_LETS_ENCRYPT=yes \
-e REDIRECT_HTTP_TO_HTTPS=yes \
-e app1.domain.com_REMOTE_PHP=php1 \
-e app1.domain.com_REMOTE_PHP_PATH=/app \
-e app2.domain.com_REMOTE_PHP=php2 \
-e app2.domain.com_REMOTE_PHP_PATH=/app \
bunkerity/bunkerized-nginx
Dans ce cas, le répertoire /where/are/web/files devra avoir une structure comme celle-ci :
/where/are/web/files
├── app1.domain.com
│ └── index.php
│ └── ...
└── app2.domain.com
└── index.php
└── ...
Aller plus loin
Bunkerized-nginx permet de faire bien plus que ce soit la configuration automatique avec des labels, l’intégration dans un environnement Docker Swarm ou même l’utilisation d’une interface web pour configurer les services. Tout est expliqué dans le README du projet GitHub.
Veuillez noter qu’énormément d’éléments de sécurité sont activés avec des valeurs par défaut. Mais vous pouvez tout configurer comme bon vous semble. Pour plus d’informations vous pouvez consulter la liste des variables d’environnement.
Il y a aussi des exemples concrets accompagnés de fichiers docker-compose.yml prêts à l’emploi dans le dossier examples sur GitHub.
Aller plus loin
- Projet GitHub (277 clics)
- Demo en ligne (90 clics)
- Documentation (51 clics)
- Exemples (63 clics)
# Docker
Posté par J Avd . Évalué à 10.
Franchement je commence à en avoir marre de voir systématiquement les solutions être présentées sous forme de docker…
"Gentoo" is an ancient african word, meaning "Read the F*ckin' Manual". "Gentoo" also means "I am what I am because you all are freaky n3rdz"
[^] # Re: Docker
Posté par stopspam . Évalué à 4.
sentiment partagé
[^] # Re: Docker
Posté par meseira (site web personnel) . Évalué à 5.
Franchement, je partage ton sentiment…
[^] # Re: Docker
Posté par Letho . Évalué à 4.
Idem. Et pourtant j'aime beaucoup Docker (et surtout Podman). Je préfère garder une distinction entre la partie « infra » (une bonne vieille CentOS des familles, Nginx en reverse-proxy, etc), que je vais pouvoir configurer facilement, et les applications déployées pour les clients qui elles le sont sous forme de containers.
[^] # Re: Docker
Posté par Psychofox (Mastodon) . Évalué à 10.
Le code est sur github, avec les dockerfiles. Tu peux donc l'implémenter sur un système non conteneurisé. Et ça ne fait que fournir des choses que tu peux déjà installer à la popogne normalement.
Je ne vois pas bien où est le problème.
Ce serait gênant si c'était une app obscure et proprio qui était fournie sous forme d'image sans la moindre idée sur sa construction
[^] # Re: Docker
Posté par meseira (site web personnel) . Évalué à 10.
Le problème est qu'un Dockerfile ne remplace pas la doc. Une explication claire des dépendances et d'une façon d'installer le programme, c'est aussi important que le code pour un projet libre.
[^] # Re: Docker
Posté par xulops (site web personnel) . Évalué à 4.
Les deux peuvent avoir leur utilité. La fameuse phrase où il vaut mieux apprendre à quelqu'un la pêche que de lui donner un poisson, c'est vrai quand il n'y a pas urgence. Un gars qui n'a pas mangé depuis 3 jours, il vaut mieux lui filer un poisson tout de suite, et lui apprendre à pêcher plus tard.
Moi c'est "un outil qui va vous éviter de devoir suivre les bonnes pratiques de sécurité à chaque fois que vous avez besoin d’un serveur web" qui m'inquiète un peu. Me dire que je ne dois pas suivre les bonnes pratiques, heu … ou alors c'est la phrase qui est mal tournée ? Du coup je me demande en quoi c'est plus sécurisé qu'un apache (que je connais mieux que nginx) normalement configuré.
[^] # Re: Docker
Posté par bunkerity . Évalué à 2.
Oui c'est vrai que la phrase n'est pas très bien tournée. Voici d'autres reformulations pour éclaircir : "un outil qui va vous éviter de devoir appliquer à la main les bonnes pratiques de sécurité" ou bien "un outil qui va vous faciliter l'application des bonnes pratiques de sécurité". Concernant les aspects sécurité, je vous invite à regarder la liste des variables d'environnement cela vous donnera une idée des fonctionnalités de sécurité qui sont intégrées.
[^] # Re: Docker
Posté par barmic 🦦 . Évalué à 9.
C'est une image d'Épinal. La plus part des projets ont une doc d'installation qui est une série de commandes. Le dockerfile est largement plus compréhensible que la plus part des fichiers de gestionnaire de configuration que j'ai pu voir. C'est un bon point de départ pour une documentation exécutable.
Mais il y a d'autres raisons :
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Docker
Posté par Psychofox (Mastodon) . Évalué à 8. Dernière modification le 30 avril 2021 à 11:50.
Si j'ai bien compris ce qu'est bunkerized-nginx, ce projet sert justement à t'aider à tout configurer sans avoir à te fader l'installation et la configuration de tout le bouzin car c'est un packaging de briques existantes.
Si tu veux configurer ton nginx, ton lets encrypt, fail2ban, clamav et tout le reste que fait bunkerized-nginx, tu le peux déjà, les docs existent déjà pour chacune des ces briques.
Si tu aimes faire les choses à la main et en dehors de docker, les docs existent déjà, si tu veux de l'automatisation sans containers, une multitude de playbooks/recipes/modules existent déjà pour ansible/chef/puppet/salt/whatever pour ces divers composants.
Ça ne sert donc à rien de critiquer le choix de docker car ce n'est qu'une proposition parmi une multitude.
[^] # Re: Docker
Posté par Philippe M (site web personnel) . Évalué à 8.
Et pourtant cela simplifie tellement les tests "pour voir ce que c'est" sans passer des jours à préparer une machine, installer toutes les dépendances pas forcément dispo sur ta distri, se prendre la tête avec le détail non documenté… pour enfin arriver à démarrer le service et ce rendre compte en 30mn qu'en faite non c'est pas ce que tu cherche.
Après pour la mise en prod c'est un choix d'infra propre à chaque SI.
Born to Kill EndUser !
[^] # Re: Docker
Posté par bunkerity . Évalué à 10.
Nous prévoyons de supporter des installations sans Docker directement sur un Linux (cf. TODO list). Mais effectivement nous avons fait le choix de Docker pour commencer. En tout cas merci pour vos retours !
[^] # Re: Docker
Posté par Cyril Chaboisseau (Mastodon) . Évalué à 2.
En théorie je suis d'accord, et j'ai moi-même mis longtemps à trouver une utilité à Docker.
Mais en pratique et dans le cas présent (serveur web), dans l'hypothèse où le serveur se ferait hacké (par exemple via une commande PHP shell_exec, system ou passthru), c'est la porte ouverte à tout un tas de tentatives d'élévation de privilèges qui peuvent amener l'attaquant à trouver des failles pouvant amener à passer root ou un autre compte administrateur.
L'intérêt de lancer le serveur web dans un bac à sable (Docker ou n'importe quel autre outil de compartimentation des processus), c'est que dans l'éventualité où il y aurait une faille dans le système ou bien des mots de passe lisibles dans l'un des fichiers accessibles sur la machine sur laquelle il tourne, et bien ces fichiers ou cette failles ne seraient pas exploitable.
[^] # Re: Docker
Posté par Atem18 (site web personnel) . Évalué à 1.
Pour le coup, ils ne font que exécuter des scripts bash long comme le bras dans le container, ce qui est clairement dégueulasse et contraire à la philosophie Docker.
Donc pour le coup, je pense que tu peux les exécuter sur un autre linux et ça marchera plus ou moins.
# Le ToR tue ?
Posté par Pol' uX (site web personnel) . Évalué à 10.
C'est dommage de banaliser la censure arbitraire des rares outils qui en protègent (de la censure).
Adhérer à l'April, ça vous tente ?
[^] # Re: Le ToR tue ?
Posté par bunkerity . Évalué à 5.
Effectivement, cela dépend des usages. Si besoin, vous pouvez désactiver le blocage des nœuds de sortie TOR via la variable d'environnement BLOCK_TOR_EXIT_NODE positionnée à no (plus d'info ici). D'ailleurs nous avons même un exemple d'utilisation de bunkerized-nginx avec un "hidden service" en .onion ici.
[^] # Re: Le ToR tue ?
Posté par Pol' uX (site web personnel) . Évalué à 10.
Franchement vous devriez le désactiver par défaut et documenter son activation pour les rares cas où c'est pertinent.
Adhérer à l'April, ça vous tente ?
# Une version Apache ?
Posté par deuf . Évalué à 2. Dernière modification le 30 avril 2021 à 15:03.
est ce qu'il y aura une version apache ?
il y a des fonctionnalités que je ne retrouve pas dans nginx (la version opensource).
Je pense au module openid qui n'est présent que dans la version payante.
[^] # Re: Une version Apache ?
Posté par bunkerity . Évalué à 1. Dernière modification le 02 mai 2021 à 17:43.
Pour le moment ce n'est pas prévu. Mais nous gardons l'idée en tête, merci du retour.
# ajout site
Posté par Sorr0w . Évalué à 2.
Superbe article. Je me pose une question qui va peut-être paraître bête. Comment fait on lorsque l'on va rajouter un site où autre. Il faut relancer son container ?
[^] # Re: ajout site
Posté par bunkerity . Évalué à 2.
Dans l'exemple de l'article, oui il relancer le conteneur avec les nouvelles variables d'environnement. Sinon bunkerized-nginx supporte aussi la configuration automatique avec des "labels" qui permet justement d'éviter de le relancer à chaque fois (plus d'info ici).
[^] # Re: ajout site
Posté par Sorr0w . Évalué à 1.
Merci pour cette réponse. Je ne suis pas à l'aise avec docker et c'est dommage car je n'arrive pas à faire fonctionner tout ça en automatique.
J'ai fais quelques recherches mais sans succès. Vous savez où l'on peux trouver un tuto de quelqu'un qui fait l'installation automatique et qui rajoute des sites au fur et à mesure avec un reverse proxy, du PHP etc ? Pour voir comment prendre en main ce container.
# bunkerized Node JS +Express
Posté par Coincoin39 . Évalué à 1.
Bonjour,
Existe t'il la même chose pour les serveurs nodeJS+express ?
Coincoin39
[^] # Re: bunkerized Node JS +Express
Posté par bunkerity . Évalué à 2.
Vous pouvez très bien utiliser bunkerized-nginx en frontal de vos applications NodeJS+Express en tant que reverse proxy (exemples : basique et multisite).
[^] # Re: bunkerized Node JS +Express
Posté par Coincoin39 . Évalué à 0.
merci, je vais regarder cela !
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.