RETOUR D’EXPÉRIENCE /

Garder un backend privé tout en autorisant un egress ciblé

Introduction

Dans certaines stacks Compose, des services critiques (bases de données, clés) doivent rester entièrement isolés du réseau d’entrée, tandis que d’autres composants applicatifs ont un besoin légitime d’accéder à Internet. Le sujet décrit la décision permettant de concilier ces deux exigences sans exposer le backend.

Symptôme

Le réseau backend était configuré pour être entièrement interne afin de protéger les données. Simultanément, un composant applicatif (ici : machine learning) devait télécharger des modèles depuis Internet, ce qui échouait faute d’egress réseau.

Contexte technique

Les stacks étudiées séparent classiquement : un réseau d’entrée (proxy), un réseau backend interne pour les services sensibles, et la possibilité d’ouvrir des chemins sortants contrôlés pour certains services. Dans le cas étudié, le réseau backend était configuré internal: true pour isoler la base et les composants critiques.

Diagnostic

La configuration initiale utilisait un seul réseau backend pour les services sensibles et les services applicatifs. Un seul réseau ne pouvait pas garantir simultanément l’isolation stricte du backend et l’egress applicatif nécessaire : le ML n’avait pas de connectivité sortante et les bases restaient protégées.

Cause racine

La cause racine est l’architecture réseau trop simple : un réseau unique ne permet pas d’appliquer le principe de moindre privilège réseau à la fois pour l’isolation des données et pour des besoins d’egress limités.

Solution retenue

Conserver le backend interne et créer un réseau Docker d’egress distinct. Seul le service qui a besoin d’accéder à Internet (le composant ML) est joint aux deux réseaux : backend (interne) et egress (vers l’extérieur). Les services de données restent uniquement sur backend.

app_server
  ├── proxy
  └── backend

db
  └── backend

valkey
  └── backend

ml
  ├── backend
  └── egress → Internet

Ce schéma simplifié illustre la séparation : le service ML partage l’accès au réseau backend pour communiquer localement avec la base si nécessaire, mais possède aussi un chemin distinct vers Internet via egress.

Conséquences observées

  • Les services de stockage et les composants sensibles restent isolés sur le réseau interne.
  • Le composant ML peut télécharger modèles et dépendances depuis Internet lorsque nécessaire.
  • La solution applique le principe de moindre privilège réseau en limitant l’egress au seul service concerné.
  • Nécessite de maintenir un réseau Docker supplémentaire.
  • Le service ML dépend d’Internet pour les téléchargements initiaux ou lors de changements de modèle.

Exemple générique de représentation (pédagogique)

Le fragment suivant est une représentation générique du pattern réseau utilisée à des fins pédagogiques, et ne doit pas être présenté comme une copie exacte d’un fichier de production.

services:
  machine-learning:
    networks:
      - backend
      - egress

networks:
  backend:
    internal: true
  egress: {}

Validation

La validation recommandée consiste à tester explicitement une matrice de flux autorisés et refusés entre entrants, backend et egress. Cette matrice doit couvrir au minimum : accès proxy→service public, service ML→Internet, et absence d’accès direct du réseau d’entrée aux services de base.

Enseignements

  • Concevoir les réseaux à partir d’une matrice de flux autorisés plutôt qu’à partir de besoins individuels.
  • Ne jamais résoudre un besoin d’egress en publiant un port de base de données sur le réseau d’entrée.

Séparer les chemins sortie des chemins internes permet d’appliquer le principe de moindre privilège sans compromettre l’isolation des données.

Pattern réutilisable

  1. Cartographier les flux réseau requis entre entrants, services applicatifs et services de données.
  2. Identifier les services nécessitant un egress vers Internet.
  3. Créer un réseau d’egress distinct et documenter son usage et ses contrôles.
  4. Joindre uniquement les services identifiés à ce réseau d’egress, laisser les bases uniquement sur le réseau interne.
  5. Valider la configuration via une matrice de tests de connectivité explicite.

Conclusion

Dans des environnements Compose, la création d’un réseau d’egress séparé pour les services qui en ont besoin est une solution simple et efficace pour concilier isolation stricte du backend et besoins applicatifs de connectivité sortante, tout en restant fidèle au principe de moindre privilège.