Docker sur Debian / Ubuntu ne respectant pas ufw firewall paramètres exposant ports
Docker contourne ufw firewall et expose les ports au monde extérieur, une fuite de sécurité très grave.
Encore un autre problème inattendu Docker . Dans un article précédent, j'ai décrit pourquoi et comment vous devez forcer Docker à utiliser un subnet, pour éviter des changements soudains et inattendus dans le réseau avec des conséquences comme le courrier ne fonctionne plus.
Cet article parle de Docker ne respectant pas les paramètres firewall , au moins lorsqu'on exécute Debian / Ubuntu et ufw (Uncomplicated Firewall). Docker ne vous le dit pas, et expose les ports, donc ce comportement est totalement inattendu.
Mon serveur ISPConfig exécute Debian Stretch. J'utilise ufw comme firewall, voici les réglages principaux.
ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip
To Action From
-- ------ ----
22/tcp ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
443/tcp ALLOW IN Anywhere
8080/tcp ALLOW IN Anywhere
25 ALLOW IN Anywhere
Comme vous pouvez le voir, toutes les connexions entrantes sont bloquées sauf quelques-unes autorisées.
Mes applications web Docker Python utilisent le serveur HTTP Gunicorn WSGI pour servir le Python Flask app. Nginx s'exécute sur l'hôte et est configuré comme proxy inverse pour ces applications. Ça marche à merveille. Dans le fichier docker-compose.yml, les ports sont chargés depuis le fichier.env :
services:
web:
...
env_file:
- ./.env
ports:
- "${SERVER_PORT_HOST}:${SERVER_PORT_CONTAINER}"
Pour une application, le fichier.env contient ces lignes :
SERVER_PORT_HOST=8001
SERVER_PORT_CONTAINER=8001
En effet, la ligne docker-compose utilisée est donc :
ports:
- "8001:8001"
Le problème : Docker Le port 8001 est exposé au réseau extérieur même si ufw est configuré pour bloquer les connexions entrantes.
Cela signifie que l'application/service Docker est également visible à <SERVER-IP>:8001. Ce n'est pas seulement très mauvais, c'est aussi totalement inattendu car ufw a été configuré pour bloquer toutes les connexions entrantes.
Les solutions
Il y a plusieurs solutions à cela, ici je choisis de lier le port à la machine hôte. Les lignes docker-compose.yml deviennent alors :
ports:
- "127.0.0.1:8001:8001"
Ça marche pour moi.
D'autres façons de résoudre ce problème sont d'empêcher Docker d'interférer avec firewall, d'ajouter des règles au fichier ufw /etc/ufw/après.rules, etc. Voir les liens ci-dessous.
Résumé
Certaines personnes considèrent ce comportement Docker comme un bug, et je ne peux que l'accepter. Ufw est un firewall, un programme très important pour contrôler la sécurité. Ufw est très largement utilisé et si un autre programme contourne son comportement, l'utilisateur doit être informé. Jusqu'à ce que cela soit corrigé, au minimum Docker devrait émettre un gros message d'avertissement au démarrage d'une application.
Liens / crédits
Be careful with Docker ports!
https://dev.to/kovah/be-careful-with-docker-ports-3pih
Docker service exposed publicly though made to expose ports to localhost only
https://stackoverflow.com/questions/50621936/docker-service-exposed-publicly-though-made-to-expose-ports-to-localhost-only
Docker services only available to the local host
https://stackoverflow.com/questions/54261105/docker-services-only-available-to-the-local-host
How to fix the Docker and UFW security flaw
https://www.techrepublic.com/article/how-to-fix-the-docker-and-ufw-security-flaw/
The dangers of UFW + Docker
https://blog.viktorpetersson.com/2014/11/03/the-dangers-of-ufw-docker.html
What is the best practice of docker + ufw under Ubuntu
https://stackoverflow.com/questions/30383845/what-is-the-best-practice-of-docker-ufw-under-ubuntu
En savoir plus...
Docker
Laissez un commentaire
Commentez anonymement ou connectez-vous pour commenter.
Commentaires (1)
Laissez une réponse
Répondez de manière anonyme ou connectez-vous pour répondre.
Ein wirklich schweres und immer noch aktuelles Sicherheitsproblem. Danke für die schnelle Lösung für Docker Compose.
Récent
- Masquer les clés primaires de la base de données UUID de votre application web
- Don't Repeat Yourself (DRY) avec Jinja2
- SQLAlchemy, PostgreSQL, nombre maximal de lignes par user
- Afficher les valeurs des filtres dynamiques SQLAlchemy
- Transfert de données sécurisé grâce au cryptage à Public Key et à pyNaCl
- rqlite : une alternative à haute disponibilité et dist distribuée SQLite
Les plus consultés
- Utilisation des Python's pyOpenSSL pour vérifier les certificats SSL téléchargés d'un hôte
- Utiliser UUIDs au lieu de Integer Autoincrement Primary Keys avec SQLAlchemy et MariaDb
- Connexion à un service sur un hôte Docker à partir d'un conteneur Docker
- Utiliser PyInstaller et Cython pour créer un exécutable Python
- SQLAlchemy : Utilisation de Cascade Deletes pour supprimer des objets connexes
- Flask RESTful API validation des paramètres de la requête avec les schémas Marshmallow