Docker fout un beau bordel avec les règles iptables
/nftables
, et voici pourquoi ça fait vraiment chier :
🚨 Ce que Docker fait par défaut :
-
Il modifie directement
iptables
/nftables
sans te demander ton avis. -
Il crée ses propres chaînes (
DOCKER
,DOCKER-USER
, etc.) un peu partout. -
Il suppose que tu veux que tout conteneur ait accès à tout.
-
Il te colle des règles
MASQUERADE
(NAT source) qui passent au-dessus de ta logique. -
Et surtout : il fonctionne mal avec des firewalls personnalisés ou stricts — ce qui est précisément ton cas.
💣 Ce que ça cause :
-
Conflits avec tes règles manuelles (
FORWARD DROP
, etc.) -
Des comportements “magiques” impossibles à tracer (ça marche pour
curl
, mais pas pourSMTP
, etc.) -
Des trous de sécurité si tu oublies de tout verrouiller ensuite
✅ Solutions concrètes
1. Désactiver la gestion automatique du firewall par Docker
Ajoute ceci à /etc/docker/daemon.json
:
{
"iptables": false,
"ip6tables": false
}
Puis :
sudo systemctl restart docker
🛑 Attention : Docker ne créera plus aucune règle. Tu dois tout gérer toi-même — ce qui est parfait pour toi.
2. Créer tes propres règles nftables pour gérer Docker proprement
Par exemple :
table inet filter {
chain default_fwd {
type filter hook forward priority filter; policy drop;
iifname "docker0" oifname != "docker0" accept
iifname "br-8203e51da77b" oifname != "br-8203e51da77b" accept
oifname "docker0" ct state related,established accept
oifname "br-8203e51da77b" ct state related,established accept
}
}
Tu peux être aussi précis que tu veux : destination, port, protocole, interface, groupe de conteneurs, etc.
3. Ou carrément isoler les conteneurs et passer par un reverse proxy/NAT filtré
Tu les colles sur un bridge privé, puis tu exposes uniquement ce que tu veux avec des règles de NAT explicites et propres. Fini le fouillis.
Plan détaillé et complet de ton pare-feu nftables
de production, avec :
-
🔒 Politique par défaut DROP
-
🌐 Accès web nginx (ports 80/443)
-
🐳 Accès total à Internet pour les containers Docker (
docker0
,br-*
) -
🛡️ Filtrage global (
blackhole
sets) -
🧠 Fail2Ban avec
f2b-table
-
📄 Logs pertinents dans un fichier séparé avec
rsyslog
et rotation -
🔁 Masquerading NAT pour Docker
-
💾 Chargement via
/etc/nftables.conf
et démarrage automatique
🔧 1. Fichier nftables.conf
(à placer dans /etc/nftables.conf
)
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
set blackhole_v4 {
type ipv4_addr
flags interval
}
set blackhole_v6 {
type ipv6_addr
flags interval
}
chain global {
ip saddr @blackhole_v4 drop
ip daddr @blackhole_v4 drop
ip6 saddr @blackhole_v6 drop
ip6 daddr @blackhole_v6 drop
}
chain INPUT {
type filter hook input priority 0; policy drop;
iifname "lo" accept
ct state established,related accept
ct state invalid drop
jump global
# Web
tcp dport { 80, 443 } accept
# SSH
tcp dport 22 accept
# Fail2Ban
ip saddr @addr-set-sshd tcp dport 22 reject
ip saddr @addr-set-nextcloud tcp dport { 80, 443 } reject
# ICMP
ip protocol icmp accept
ip6 nexthdr ipv6-icmp accept
# log rejet
log prefix "[nftables] INPUT DROP: " flags all level warning
counter reject
}
chain OUTPUT {
type filter hook output priority 0; policy drop;
oifname "lo" accept
ct state established,related accept
ct state invalid drop
jump global
# par défaut : open bar
accept
}
chain FORWARD {
type filter hook forward priority 0; policy drop;
jump global
jump docker_fwd
# log rejet
log prefix "[nftables] FORWARD DROP: " flags all level warning
counter reject
}
chain docker_fwd {
# Containers vers Internet
iifname "docker0" oifname != "docker0" accept
iifname "br-+" oifname != "br-+" accept
# Réponses vers containers
ct state related,established accept
}
}
table inet f2b-table {
set addr-set-sshd {
type ipv4_addr
flags interval
}
set addr-set-nextcloud {
type ipv4_addr
flags interval
}
chain INPUT {
type filter hook input priority -1; policy accept;
tcp dport 22 ip saddr @addr-set-sshd reject
tcp dport { 80, 443 } ip saddr @addr-set-nextcloud reject
}
}
table ip nat {
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
# NAT Docker vers Internet (IP de l'hôte)
ip saddr 172.17.0.0/16 masquerade
ip saddr 172.18.0.0/16 masquerade
}
}
📝 2. Log vers fichier dédié avec rsyslog
Fichier : /etc/rsyslog.d/30-nftables.conf
:msg, contains, "[nftables]" /var/log/nftables.log
& stop
Puis :
sudo touch /var/log/nftables.log
sudo chmod 640 /var/log/nftables.log
sudo systemctl restart rsyslog
🔁 3. Rotation des logs
Fichier : /etc/logrotate.d/nftables
/var/log/nftables.log {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
create 640 syslog adm
postrotate
/bin/systemctl restart rsyslog > /dev/null 2>&1 || true
endscript
}
🚀 4. Activer nftables
au boot
sudo systemctl enable nftables
sudo systemctl restart nftables
✅ 5. Vérification
sudo nft list ruleset
sudo ip a | grep docker
Tu peux aussi tester depuis une VM Docker :
docker run --rm -it alpine sh
apk add curl
curl https://example.com
Et SMTP :
apk add busybox-extras
telnet smtp.koumbit.net 587
Une bonne manière d'attirer l'attention de vos lecteurs est de raconter une histoire.
Tout ce que vous considérez écrire peut être raconté comme une histoire.