Bloquer l’accès depuis l’extérieur aux conteneurs Docker (Linux)

Mafzst
Mafzst
Feb 25, 2017 · 3 min read
Dontworry

Docker est très pratique pour lancer des services hétéroclites sur un serveur sans trop de problèmes de conflits entre eux (Nginx et Apache par exemple). Mais, par défaut, Docker expose ces services sur un port de la machine hôte, donc accessible depuis l’extérieur.

Si comme moi vous voulez plus de contrôle sur quels port sont accessibles ou simplement que vous voulez utiliser un reverse proxy devant (pour utiliser un domaine par exemple), il est possible de fermer l’accès direct aux services Docker par défaut à coups de quelques règles iptables. Voyons comment faire.

Les IPTables

Pour rappel avant de commencer, les IPTables sont un méchanisme dans Linux qui permet d’appliquer des filtres sur le traffic réseau entrant, sortant ou transféré entre deux interfaces, c’est un pare-feu.

Si les IPTables ne sont pas très claires pour vous je vous conseille la lecture ce cet article avant de commencer.

Par défaut Docker mets en place des règles permettant d’accéder aux services sur l’interface docker0 par transfert de paquets depuis n’importe quelle autre interface. On va donc aller ce placer en amont de ces règles pour filtrer le trafic, ça permet de ne pas modifier le config de docker et de conserver les règles pour atteindre les services depuis la machine hôte.

Bloquer tout le traffic

Pour commencer on va créer une nouvelle table PRE_DOCKER pour contenir nos règles.

iptables -N PRE_DOCKER

On définit ensuite l’action par défaut de cette table : pour cela on insert une règle dans notre nouvelle table sans conditions et avec l’actionDROP

iptables -I PRE_DOCKER -j DROP

On ajoute ensuite des exceptions pour le traffic “normal” de Docker :

  • Le traffic entre les conteneurs
  • Le traffic de Docker vers l’extérieur
  • Les connexions déjà établies ou liées à une autre

Ce qui donne

iptables -I PRE_DOCKER -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I PRE_DOCKER -i docker0 ! -o docker0 -j ACCEPT
iptables -I PRE_DOCKER -m state --state RELATED -j ACCEPT
iptables -I PRE_DOCKER -i docker0 -o docker0 -j ACCEPT

Il ne reste plus maintenant qu’à insérer notre table dans une chaîne. Dans notre cas il s’agit de la chaîne FORWARD car le traffic de l’extérieur vers Docker arrive sur une interface et est transféré vers l’interface de Docker docker0

iptables -I FORWARD -o docker0 -j PRE_DOCKER

Autoriser quelques services

Si on veut autoriser quelques service à être accessible depuis l’extérieur, il faut rajouter des règles dans notre table de filtrage.

La méthode que je propose permet d’accéder à tous les services qui écoutent sur le même port. Si vous démarrez deux conteneurs Nginx, les deux écoutent sur le port 80 et sont redirigés sur deux ports différents de la machine hôte par Docker. Avec cette méthode les deux seront autorisés avec une seul règle. Il ne pourront pas être dissociés.

C’est un comportement qui me va. Si vous n’êtes pas dans ce cas là je vous invite à creuser les iptables.

Du coup on autorise le port d’écoute du conteneur par le port de destination de la machine cible !

Par exemple pour un conteneur écoutant sur le port 80 (tcp)

iptables -I PRE_DOCKER -p tcp --dport 80 -j ACCEPT

J’en ai fini avec cette petite astuce. J’ai écris un petit script bash pour gagner du temps qui exécute la partie blocage. Il dispo ici.

A+

Mafzst

Je partage avec vous mon quotidien de développeur passionné. Nouvelles technos, projets, tutos, casse-têtes,…

Mafzst

Written by

Mafzst

Développeur, amoureux des données, photographe

Mafzst

Mafzst

Je partage avec vous mon quotidien de développeur passionné. Nouvelles technos, projets, tutos, casse-têtes,…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade