
Sécurité réseau (network policies, pare-feu)
Maîtrisez la sécurité réseau pour vos conteneurs Docker : segmentation, network policies, intégration pare-feu hôte et exposition sécurisée des ports.
Introduction : l'isolation réseau ne suffit pas toujours
Nous avons vu que Docker fournit une isolation réseau native pour les conteneurs, notamment via les namespaces réseau et les réseaux `bridge` ou `overlay`. Cependant, cette isolation par défaut n'est souvent pas suffisante pour garantir une sécurité robuste, en particulier dans des environnements complexes ou de production. Les conteneurs sur un même réseau `bridge` par défaut peuvent communiquer librement, et sans configuration supplémentaire, le contrôle du trafic entrant et sortant peut être limité.
La sécurité réseau dans l'écosystème Docker consiste à appliquer des contrôles plus fins sur la communication entre les conteneurs, entre les conteneurs et l'hôte, et entre les conteneurs et le monde extérieur. Il s'agit d'adopter une approche de "défense en profondeur" pour le réseau, en complétant l'isolation de base par des règles de pare-feu, des politiques de réseau et une configuration prudente.
Cette section aborde les stratégies et outils clés pour renforcer la sécurité réseau de vos déploiements Docker, allant de la segmentation de base à l'utilisation de politiques réseau avancées et à l'intégration avec le pare-feu de l'hôte.
Segmentation réseau : une première ligne de défense
Le principe de base de la sécurité réseau est la segmentation : diviser votre environnement en zones isolées et ne permettre que les communications strictement nécessaires entre elles. Dans Docker, cela se traduit principalement par l'utilisation de réseaux définis par l'utilisateur (user-defined networks).
Comme mentionné précédemment, évitez d'utiliser le réseau `bridge` par défaut pour vos applications multi-conteneurs. Créez plutôt des réseaux personnalisés (généralement de type `bridge` pour un seul hôte, ou `overlay` pour Swarm) pour regrouper les conteneurs qui ont besoin de communiquer. Par exemple, créez un réseau `backend-net` pour votre API et votre base de données, et un réseau `frontend-net` pour votre serveur web. Si le frontend n'a besoin de parler qu'à l'API, connectez le conteneur API aux deux réseaux, mais le frontend uniquement à `frontend-net` et la base de données uniquement à `backend-net`.
Par défaut, les conteneurs sur des réseaux définis par l'utilisateur distincts ne peuvent pas communiquer entre eux, sauf si un conteneur est explicitement connecté aux deux réseaux. C'est déjà une amélioration significative par rapport au pont par défaut. Cette segmentation limite la "surface d'attaque latérale" : si un conteneur frontend est compromis, l'attaquant n'aura pas un accès réseau direct à la base de données.
Utiliser Docker Compose facilite grandement la création et la gestion de ces réseaux personnalisés pour vos applications.
Micro-segmentation avec les Network Policies (Kubernetes)
La segmentation par réseaux Docker est une bonne première étape, mais elle reste relativement grossière. Que faire si vous voulez contrôler plus finement le trafic *à l'intérieur* d'un même réseau ? Par exemple, autoriser le service A à parler au service B sur le port 80, mais interdire toute autre communication depuis A ?
C'est là qu'intervient le concept de Network Policies (politiques réseau). Ce sont des règles de pare-feu définies au niveau de l'orchestrateur qui spécifient quelles communications réseau (entrant/sortant, par protocole/port, basé sur les labels des sources/destinations) sont autorisées entre les conteneurs (ou Pods dans Kubernetes). Elles permettent une micro-segmentation beaucoup plus fine.
Kubernetes possède une implémentation native et puissante des Network Policies. Vous pouvez définir des règles très précises, par exemple : "Le Pod avec le label `app=frontend` peut uniquement envoyer du trafic vers les Pods avec le label `app=backend` sur le port TCP 8080". Tout autre trafic sortant du frontend ou entrant vers le backend serait bloqué par défaut si une politique restrictive est appliquée.# Exemple simplifié de NetworkPolicy Kubernetes
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080Docker Swarm et Docker seul n'ont pas de mécanisme natif équivalent aux Network Policies de Kubernetes. La segmentation repose principalement sur les réseaux Docker. Pour un contrôle plus fin dans ces environnements, il faut généralement recourir à des solutions tierces (comme des CNI plus avancés s'ils sont utilisables, des service meshes, ou des configurations pare-feu complexes sur l'hôte), ce qui est moins direct.Adopter une approche "zero-trust" où tout trafic est interdit par défaut et seules les communications explicitement autorisées via Network Policies sont permises est une bonne pratique dans les environnements Kubernetes.
Intégration avec le pare-feu de l'hôte (`iptables`, `firewalld`)
Docker interagit avec le système de pare-feu de la machine hôte (généralement `iptables` ou `nftables` via des interfaces comme `firewalld` sur Linux) pour implémenter certaines de ses fonctionnalités réseau, notamment le mappage de ports (`-p`) et la communication via les réseaux `bridge`.
Par défaut, lorsque vous publiez un port avec `-p hostPort:containerPort`, Docker ajoute des règles (dans la chaîne `DOCKER` d'iptables) pour autoriser le trafic entrant sur `hostPort` depuis n'importe quelle source (`0.0.0.0`) et le rediriger vers le conteneur. Cela peut outrepasser les règles que vous auriez pu définir manuellement dans les chaînes standard comme `INPUT`.
Pour appliquer vos propres règles de filtrage au trafic destiné aux conteneurs via les ports publiés, Docker fournit une chaîne spécifique : `DOCKER-USER` dans `iptables`. Les règles ajoutées à cette chaîne sont évaluées avant les règles de la chaîne `DOCKER`. C'est l'endroit recommandé pour ajouter des règles personnalisées, par exemple, pour restreindre l'accès à un port publié à certaines adresses IP sources uniquement.
# Exemple iptables: Autoriser l'accès au port 8080 (mappé par Docker)
# uniquement depuis l'IP 1.2.3.4
sudo iptables -I DOCKER-USER -i ext_if -p tcp --dport 8080 ! -s 1.2.3.4 -j REJECT
sudo iptables -I DOCKER-USER -i ext_if -p tcp --dport 8080 -s 1.2.3.4 -j ACCEPT
# (remplacer ext_if par votre interface externe)
# Alternative: tout bloquer sauf les IPs autorisées
sudo iptables -I DOCKER-USER -i ext_if -p tcp --dport 8080 -j REJECT # Mettre à la fin
sudo iptables -I DOCKER-USER -i ext_if -p tcp --dport 8080 -s 1.2.3.4 -j ACCEPT
sudo iptables -I DOCKER-USER -i ext_if -p tcp --dport 8080 -s 5.6.7.8 -j ACCEPTIl est également possible de configurer le pare-feu de l'hôte pour contrôler le trafic sortant des conteneurs, bien que cela puisse être plus complexe car les adresses IP sources des conteneurs sur les réseaux bridge par défaut sont généralement masquées (NAT).
Comprendre comment Docker interagit avec le pare-feu de l'hôte et savoir utiliser la chaîne `DOCKER-USER` est essentiel pour appliquer des contrôles de sécurité réseau au niveau de l'hôte qui complètent ceux de Docker.
Exposition sécurisée des ports : le principe de moindre exposition
Nous avons déjà abordé l'exposition des ports avec `-p` et `-P`, mais il est crucial de le revoir sous l'angle de la sécurité. Chaque port que vous exposez depuis un conteneur vers l'hôte augmente la surface d'attaque de votre application visible depuis le réseau.
Appliquez le principe de moindre exposition : n'exposez que les ports absolument nécessaires pour que les utilisateurs ou les services externes légitimes puissent accéder à votre application. N'exposez jamais des ports de débogage, de gestion ou de bases de données directement sur l'internet ou même sur le réseau local si ce n'est pas indispensable.
Lorsque vous utilisez `-p`, soyez précis. Si un service ne doit être accessible que depuis la machine hôte elle-même (par exemple, une base de données utilisée par une application sur le même hôte, ou un service derrière un reverse proxy local), liez le port à l'interface de loopback `127.0.0.1` :
# Expose le port 5432 du conteneur uniquement sur localhost:5432
docker run -d -p 127.0.0.1:5432:5432 postgresSi le service doit être accessible depuis le réseau local mais pas depuis internet, liez-le à l'adresse IP spécifique de l'interface réseau interne de l'hôte (`-p
Evitez d'utiliser `-P` (`--publish-all`) en production, car il expose tous les ports déclarés dans l'image sur des ports aléatoires de l'hôte, ce qui peut entraîner une exposition involontaire de services non destinés à être publics.
Considérations avancées : chiffrement et surveillance
Pour les applications manipulant des données sensibles, la sécurité réseau doit aller plus loin.
Chiffrement en transit : La communication entre les conteneurs, même sur des réseaux Docker internes, peut nécessiter d'être chiffrée pour se protéger contre l'écoute indiscrète (sniffing), surtout dans des environnements multi-locataires ou si le trafic transite entre différents hôtes (réseaux overlay). La mise en place de TLS mutuel (mTLS) entre les services applicatifs est une bonne pratique. Des outils comme les service meshes (Istio, Linkerd dans Kubernetes) peuvent automatiser largement la gestion du mTLS.Surveillance et Détection d'Intrusion Réseau (NIDS) : Mettez en place des outils pour surveiller le trafic réseau à destination et en provenance de vos conteneurs. Analysez les flux pour détecter des patterns anormaux, des tentatives de scan de ports, des connexions vers des destinations suspectes, ou des volumes de trafic inhabituels qui pourraient indiquer une compromission ou une attaque.En intégrant la segmentation réseau, l'utilisation de politiques réseau (là où c'est possible), la configuration attentive du pare-feu hôte, une exposition minimale des ports et le chiffrement, vous construisez une posture de sécurité réseau solide pour votre environnement Docker, réduisant considérablement les risques liés aux accès non autorisés et aux attaques réseau.