Le Coq Numérique Le Coq Numérique Souveraineté numérique française
Guides Techniques

Docker contourne ufw : comprendre le piège et protéger votre serveur

Par Michel Vigoureux · · Docker, ufw, pare-feu

Quand Docker publie un port, il passe par-dessus ufw. Pourquoi ça arrive, comment vérifier si vous êtes exposé, et les 3 façons de vous protéger sur un VPS.

Vous avez installé ufw, fermé tous les ports sauf SSH et le web, vérifié avec ufw status. Tout semble verrouillé. Puis vous lancez une base de données dans Docker avec ports: - "5432:5432"… et elle est joignable depuis le monde entier, malgré ufw.

Ce n'est pas un bug. C'est le fonctionnement normal de Docker, documenté officiellement. Et c'est l'un des pièges les plus courants en auto-hébergement.

D'abord, c'est quoi un pare-feu ?

Un pare-feu est un filtre placé sur le chemin du trafic réseau. Pour chaque paquet qui arrive, il consulte une liste de règles : « port 443, j'accepte », « port 5432, je rejette ».

Sous Linux, ces règles vivent dans le noyau du système (le moteur s'appelle netfilter, piloté par les outils iptables ou nftables). Les écrire à la main est fastidieux, alors on utilise des outils plus simples :

  • ufw (Uncomplicated Firewall) : ufw allow 443 et c'est réglé.
  • Docker, de son côté, écrit aussi ses propres règles dans le noyau, pour faire circuler le trafic vers ses conteneurs.

Deux outils écrivent au même endroit. Le problème vient de là.

Pourquoi Docker passe par-dessus ufw

Quand vous publiez un port d'un conteneur (-p 5432:5432 ou une ligne ports: dans Compose), Docker crée une règle de redirection : « tout ce qui arrive sur le port 5432 du serveur, envoie-le au conteneur ».

Or ce trafic redirigé ne passe pas par la même porte que le trafic destiné au serveur lui-même. Il emprunte un circuit (la chaîne FORWARD) que Docker gère lui-même, avant que les règles d'ufw aient leur mot à dire. Résultat :

Internet ──► port 5432 ──► règles Docker ──► conteneur   ✅ passe
                              (ufw n'est jamais consulté)

ufw affiche toujours « 5432 : refusé ». Mais le trafic, lui, passe.

Schéma en deux parties. Sans pare-feu Hetzner : le trafic venu d'Internet contourne ufw grâce aux règles de Docker et atteint un conteneur dont le port 5432 est publié, ouvert au monde entier. Avec pare-feu Hetzner : le trafic est bloqué en amont, avant d'atteindre le serveur.
Le piège ufw · la solution : un pare-feu en amont, et ne publier que Caddy

Vérifier si vous êtes concerné

Sur le serveur, listez les ports publiés par Docker :

docker ps --format 'table {{.Names}}\t{{.Ports}}'

Tout ce qui apparaît sous la forme 0.0.0.0:XXXX-> ou [::]:XXXX-> est ouvert à Internet, quoi que dise ufw.

Pour en avoir le cœur net, testez depuis une autre machine (votre ordinateur, pas le serveur) :

nmap -Pn -p 5432 IP_DU_SERVEUR

open : le port est joignable. filtered : il est bien bloqué.

Les 3 façons de vous protéger

1. Le pare-feu de l'hébergeur (la plus robuste)

Hetzner, OVH, Scaleway et la plupart des hébergeurs proposent un pare-feu cloud, placé devant votre serveur, dans leur infrastructure. Il filtre le trafic avant même qu'il n'atteigne la machine.

Docker tourne sur votre serveur : il ne peut pas toucher à ce pare-feu. N'autorisez que ce dont vous avez besoin (22, 80, 443), et un port publié par erreur reste injoignable.

C'est la solution retenue dans le guide Vaultwarden : pare-feu Hetzner en amont, ufw en seconde ceinture.

2. Ne publier aucun port inutile (la plus simple)

Dans la plupart des cas, un conteneur n'a pas besoin d'être joignable depuis Internet. Une base de données n'a besoin d'être vue que par votre application. Une application web n'a besoin d'être vue que par votre reverse proxy.

Docker Compose met automatiquement tous les services d'un même fichier sur un réseau interne, où ils se joignent par leur nom (vaultwarden, db, etc.), sans aucune ligne ports:. Seul le reverse proxy publie 80 et 443.

👉 Voir Reverse proxy et HTTPS automatique avec Caddy.

3. Publier uniquement en local

Si vous avez besoin d'accéder à un port depuis le serveur lui-même (ou par un tunnel SSH), publiez-le sur 127.0.0.1 seulement :

    ports:
      - "127.0.0.1:5432:5432"

Le port n'est alors joignable que depuis le serveur. Depuis votre ordinateur, vous pouvez y accéder par un tunnel SSH :

ssh -L 5432:127.0.0.1:5432 utilisateur@IP_DU_SERVEUR

Et les solutions « ufw-docker » ?

Il existe des scripts (comme ufw-docker) qui réécrivent les règles pour qu'ufw reprenne la main sur les conteneurs. Ils fonctionnent, mais ajoutent une couche de complexité qu'il faut comprendre et maintenir. Pour un serveur personnel, les trois solutions ci-dessus, combinées, sont plus simples et plus sûres.

À retenir

  • Un port publié par Docker est ouvert à Internet, même si ufw dit le contraire.
  • Le pare-feu de l'hébergeur est la seule protection que Docker ne peut pas contourner.
  • Ne publiez que le reverse proxy. Le reste communique sur le réseau interne de Docker.
  • Vérifiez depuis l'extérieur avec nmap, jamais seulement avec ufw status.

Pour aller plus loin

Mots-clés :

Docker ufw pare-feu sécurité VPS

Les noms de logiciels et marques éventuellement cités dans cet article (Nextcloud, Matomo, Plausible, Umami, Vaultwarden, Bitwarden, Passbolt, Infisical, Activepieces, ERPNext, Dolibarr, etc.) appartiennent à leurs titulaires respectifs et ne sont mentionnés qu'à titre nominatif ou de comparaison. Le Coq Numérique n'est ni affilié, ni partenaire, ni sponsorisé par ces éditeurs, installe et infogère uniquement des versions non modifiées de ces logiciels libres, et n'inclut pas leurs modules « Enterprise »/commerciaux dans ses offres. Voir nos mentions légales.

Passez à l'action

Protégez vos données et mettez-vous en conformité RGPD. Audit offert sous 24 h.

Demander mon audit offert