iptables und NAT-Regeln hinter Docker-Networking wirklich verstehen
AI generated
FROM
RUN
Docker · Networking · Linux
iptables und NAT hinter Docker-Networking
Was beim docker run -p wirklich im Kernel passiert

Jedes Mal, wenn ein Container mit einer Port-Weiterleitung gestartet wird, verändert Docker im Hintergrund das iptables-Regelwerk des Hosts. Diese automatische Manipulation ist praktisch, sorgt aber regelmäßig für schwer nachvollziehbare Konflikte, sobald eigene Firewall-Regeln oder andere Tools wie firewalld ins Spiel kommen.

17 Min. Lesezeit NAT & FORWARD-Chain DOCKER-Chain Debugging mit iptables -L

1. Warum Docker überhaupt iptables anfasst

Docker-Container laufen standardmäßig in einem eigenen, isolierten Netzwerk-Namespace mit privaten IP-Adressen aus einem Bridge-Netzwerk wie 172.17.0.0/16. Damit ein Container von außen über einen Port des Hosts erreichbar wird oder selbst ins Internet kommunizieren kann, muss der Netzwerkverkehr zwischen dieser privaten Adresse und der öffentlichen Host-Schnittstelle übersetzt werden. Genau diese Übersetzung übernimmt der Linux-Kernel über das Netfilter-Framework, gesteuert durch iptables-Regeln.

Docker verwaltet dieses Regelwerk nicht manuell durch den Nutzer, sondern schreibt beim Start des Daemons und bei jedem docker run mit Port-Mapping automatisch eigene Regeln in mehrere iptables-Chains. Diese Automatisierung ist der Grund, warum Container-Networking in Docker so unkompliziert wirkt, sie ist aber auch die Ursache vieler Konflikte, sobald Administratoren versuchen, parallel eigene Firewall-Regeln zu pflegen.

2. Die eigenen Chains, die Docker anlegt

Beim Start legt der Docker-Daemon mehrere eigene Chains an, unter anderem DOCKER, DOCKER-ISOLATION-STAGE-1, DOCKER-ISOLATION-STAGE-2 und DOCKER-USER. Die Chain DOCKER enthält die NAT- und Forwarding-Regeln für einzelne veröffentlichte Ports, während die Isolation-Stages verhindern, dass unterschiedliche Docker-Netzwerke ungewollt miteinander kommunizieren können. Diese Chains werden per Jump-Regel in die Standard-Chains FORWARD und DOCKER der NAT-Tabelle eingehängt.

Besonders relevant für eigene Anpassungen ist die Chain DOCKER-USER, die Docker explizit für Regeln von Administratoren vorsieht, ohne dass sie bei einem Neustart des Daemons überschrieben wird. Eigene Firewall-Regeln, die den Docker-generierten Traffic beeinflussen sollen, gehören fast immer in diese Chain, nicht in die Standard-INPUT- oder FORWARD-Chain, da Docker seine eigenen Regeln dort regelmäßig neu schreibt.


# Alle Docker-relevanten Chains anzeigen
iptables -L -n --line-numbers | grep -A5 DOCKER

# Eigene Regel sicher in DOCKER-USER einfuegen,
# damit sie einen Neustart des Docker-Daemons uebersteht
iptables -I DOCKER-USER -s 203.0.113.0/24 -j ACCEPT
iptables -I DOCKER-USER -j DROP

3. Wie ein Port-Mapping zur NAT-Regel wird

Wird ein Container mit -p 8080:80 gestartet, erzeugt Docker in der NAT-Tabelle eine Regel in der Chain DOCKER, die eingehenden Traffic auf Port 8080 des Hosts per Destination-NAT auf Port 80 der internen Container-IP umschreibt. Zusätzlich wird in der FORWARD-Chain eine Regel angelegt, die diesen umgeleiteten Traffic explizit erlaubt, da eine reine NAT-Regel den Paketfluss durch die Firewall alleine noch nicht freigibt.

Diese doppelte Regelstruktur ist ein häufiger Stolperstein: Wer nur die NAT-Tabelle betrachtet, sieht die Übersetzung, aber nicht, ob der Traffic tatsächlich durchgelassen wird. Wer nur die Filter-Tabelle betrachtet, sieht das Forwarding, aber nicht, wohin die Pakete tatsächlich umgeschrieben werden. Ein vollständiges Verständnis erfordert immer den Blick auf beide Tabellen gemeinsam.


# NAT-Regel fuer das Port-Mapping anzeigen
iptables -t nat -L DOCKER -n

# Beispielausgabe:
# DNAT  tcp  --  0.0.0.0/0  0.0.0.0/0  tcp dpt:8080
#       to:172.17.0.2:80

# Zugehoerige FORWARD-Regel
iptables -L FORWARD -n | grep 172.17.0.2

4. Warum eigene iptables-Regeln kollidieren können

Ein klassisches Problem entsteht, wenn ein Administrator eine restriktive INPUT- oder FORWARD-Policy setzt und dabei annimmt, dass diese auch Docker-Container betrifft. Da Docker seine eigenen Jump-Regeln an den Anfang der FORWARD-Chain setzt, greift eine spätere DROP-Regel oft gar nicht mehr, weil der Traffic bereits vorher über die DOCKER-Chain akzeptiert wurde. Umgekehrt kann eine zu früh gesetzte DROP-Regel den gesamten Docker-Traffic blockieren, obwohl die Docker-eigenen Regeln technisch korrekt konfiguriert sind.

Ein weiteres verbreitetes Problem tritt auf, wenn Firewall-Management-Tools wie firewalld oder ufw parallel zu Docker eingesetzt werden. Diese Tools schreiben das iptables-Regelwerk aus ihrer eigenen Konfiguration heraus neu und können dabei Docker-Regeln versehentlich entfernen oder in eine andere Reihenfolge bringen. Nach jedem Neustart eines solchen Tools sollte deshalb geprüft werden, ob die Docker-Container weiterhin wie erwartet erreichbar sind.

5. Systematisches Debugging mit iptables -L und -t nat -L

Der erste Schritt bei Netzwerkproblemen mit Docker-Containern ist immer, sich einen vollständigen Überblick über beide relevanten Tabellen zu verschaffen: die Filter-Tabelle für Forwarding-Entscheidungen und die NAT-Tabelle für Adressübersetzungen. Der Befehl iptables -L -n -v zeigt zusätzlich Paketzähler an, mit denen sich erkennen lässt, ob eine bestimmte Regel überhaupt jemals getroffen wurde, was bei der Fehlersuche oft entscheidender ist als die reine Regel-Reihenfolge.

Bei Problemen mit einem konkreten Port-Mapping lohnt es sich, gezielt nach der Container-IP zu filtern, statt die komplette Ausgabe manuell zu durchsuchen. So lässt sich schnell feststellen, ob eine NAT-Regel überhaupt existiert und ob die zugehörige FORWARD-Regel den Traffic tatsächlich zulässt, statt beide Aspekte getrennt und ohne Bezug zueinander zu prüfen.


# Vollstaendige Uebersicht mit Paketzaehlern
iptables -L -n -v
iptables -t nat -L -n -v

# Gezielt nach einer Container-IP filtern
iptables -t nat -L -n | grep 172.17.0.2
iptables -L FORWARD -n -v | grep 172.17.0.2

# Live mitschneiden, welche Regel getroffen wird
watch -n1 'iptables -L DOCKER -n -v'

6. IP-Forwarding und die Docker-Bridge im Zusammenspiel

Damit iptables überhaupt Pakete zwischen Netzwerken weiterleiten kann, muss der Kernel-Parameter net.ipv4.ip_forward aktiviert sein. Docker setzt diesen Wert beim Start des Daemons in aller Regel automatisch, aber in gehärteten Umgebungen oder bei manuell verwalteten Sysctl-Konfigurationen kann er versehentlich wieder deaktiviert werden, etwa durch ein zentrales Konfigurationsmanagement, das den Wert bei jedem Reboot zurücksetzt.

Ist ip_forward deaktiviert, funktionieren selbst korrekt konfigurierte NAT- und FORWARD-Regeln nicht, da der Kernel Pakete grundsätzlich nicht zwischen Interfaces weiterleitet. Dieses Symptom wird oft fälschlich als Docker-Netzwerkfehler interpretiert, obwohl die Ursache eine einzelne deaktivierte Kernel-Einstellung ist, die sich mit einem einzigen Befehl prüfen und korrigieren lässt.


# Pruefen, ob IP-Forwarding aktiv ist
sysctl net.ipv4.ip_forward

# Aktivieren, falls deaktiviert (temporaer)
sysctl -w net.ipv4.ip_forward=1

# Dauerhaft in der Konfiguration verankern
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/99-docker.conf

7. Der Übergang zu nftables und was sich dabei ändert

Moderne Linux-Distributionen setzen zunehmend auf nftables als Nachfolger von iptables, wobei der klassische iptables-Befehl über eine Kompatibilitätsschicht (iptables-nft) weiterhin funktioniert. Docker unterstützt seit Version 27 auch einen nativen nftables-Modus, der die gleichen NAT- und Forwarding-Konzepte umsetzt, aber eigene Tabellen statt der klassischen Chains verwendet.

Wer auf ein System mit nftables-Backend wechselt oder Docker im nftables-Modus betreibt, muss beim Debugging entsprechend auf nft list ruleset statt iptables -L zurückgreifen. Die grundlegende Logik aus NAT-Übersetzung und expliziter Forwarding-Freigabe bleibt dabei identisch, lediglich die Werkzeuge zur Inspektion unterscheiden sich.


# Pruefen, welches Backend aktiv ist
iptables --version

# Regelwerk unter nftables anzeigen
nft list ruleset | grep -A20 docker

8. Praxisbeispiel: Ein Container ist von außen nicht erreichbar

Ein typisches Support-Szenario: Ein Container wurde mit -p 443:443 gestartet, ist lokal auf dem Host per curl erreichbar, aber von außen nicht. Der systematische Debugging-Ablauf beginnt mit der Prüfung, ob die NAT-Regel überhaupt existiert, gefolgt von der Prüfung der FORWARD-Chain, dann von ip_forward, und erst zuletzt von möglichen externen Faktoren wie Cloud-Security-Groups oder einer vorgelagerten Firewall.

In den meisten Fällen liegt die Ursache entweder an einer nachträglich installierten Firewall-Software, die das Docker-Regelwerk überschrieben hat, oder an einer restriktiven DROP-Policy in DOCKER-USER, die versehentlich auch legitimen Traffic blockiert. Beide Ursachen lassen sich mit den zuvor gezeigten Befehlen in wenigen Minuten eingrenzen, ohne die Container-Konfiguration selbst verändern zu müssen.

9. Checkliste für die Praxis

Für den täglichen Betrieb lohnt sich eine feste Reihenfolge an Prüfschritten, statt bei jedem Netzwerkproblem von vorne zu improvisieren. Diese Reihenfolge deckt die häufigsten Ursachen ab, von der grundlegenden Kernel-Einstellung über die Docker-eigenen Chains bis hin zu Konflikten mit externer Firewall-Software, und lässt sich in wenigen Minuten vollständig durchlaufen.

Die folgende Tabelle fasst die wichtigsten Prüfpunkte, die zugehörigen Befehle und typische Ursachen zusammen, damit das Debugging beim nächsten Netzwerkproblem nicht wieder bei null beginnen muss.

Prüfpunkt Befehl Typische Ursache bei Fehler Priorität
IP-Forwarding aktiv? sysctl net.ipv4.ip_forward Konfigurationsmanagement setzt Wert zurück Hoch
NAT-Regel vorhanden? iptables -t nat -L DOCKER -n Container ohne Port-Mapping gestartet Hoch
FORWARD-Regel vorhanden? iptables -L FORWARD -n -v Externes Firewall-Tool hat Regeln überschrieben Hoch
DOCKER-USER Chain geprüft? iptables -L DOCKER-USER -n Eigene DROP-Regel blockiert Traffic Mittel
Backend iptables oder nftables? iptables --version Falsches Debugging-Werkzeug verwendet Niedrig

Mironsoft

Container-Infrastruktur, CI-Pipelines und Deployment-Automatisierung

Docker-Setups, die im Team und in Produktion tragfähig bleiben?

Wir prüfen bestehende Dockerfiles und Compose-Stacks auf Sicherheitslücken, aufgeblähte Images und fragile Build-Pipelines und bauen daraus eine Container-Infrastruktur, die schnell baut, sicher läuft und im Team nachvollziehbar bleibt.

Dockerfile-Review

Multi-Stage-Builds, Layer-Caching und Image-Größe systematisch optimieren.

Security-Audit

Container-Isolation, Secrets-Handling und Image-Scanning gegen echte Angriffsflächen absichern.

CI/CD-Integration

Build-Pipelines, Registries und Deployment-Strategien für reproduzierbare Releases aufbauen.

10. Zusammenfassung

iptables und Docker: Das Wichtigste auf einen Blick

Automatik

Docker schreibt bei jedem Port-Mapping eigene NAT- und FORWARD-Regeln in iptables.

DOCKER-USER

Die einzige Chain, die für eigene, dauerhafte Firewall-Regeln vorgesehen ist.

Kollisionen

Firewall-Tools wie firewalld können Docker-Regeln überschreiben oder umordnen.

Debugging

Immer NAT- und FORWARD-Tabelle gemeinsam prüfen, plus den Status von ip_forward.

11. FAQ: iptables und Docker: Das Wichtigste auf einen Blick

1Warum verändert Docker überhaupt das iptables-Regelwerk?
Container laufen in einem isolierten Netzwerk-Namespace mit privaten IP-Adressen. Damit sie über Host-Ports erreichbar sind oder ins Internet kommunizieren können, muss der Kernel Netzwerkadressen übersetzen, was Docker automatisch über iptables-NAT-Regeln umsetzt.
2In welche Chain sollte ich eigene Firewall-Regeln für Docker-Traffic schreiben?
In die Chain DOCKER-USER. Sie ist explizit für Administrator-Regeln vorgesehen und wird bei einem Neustart des Docker-Daemons nicht überschrieben, anders als die von Docker selbst verwalteten Chains.
3Warum ist mein Container trotz korrektem Port-Mapping von außen nicht erreichbar?
Häufige Ursachen sind ein deaktiviertes IP-Forwarding im Kernel, eine von einem Firewall-Tool überschriebene DOCKER-Chain oder eine zu restriktive DROP-Regel in DOCKER-USER, die den Traffic blockiert.
4Wie prüfe ich, ob IP-Forwarding aktiviert ist?
Mit dem Befehl sysctl net.ipv4.ip_forward. Der Rückgabewert 1 bedeutet aktiviert, 0 bedeutet deaktiviert und muss mit sysctl -w net.ipv4.ip_forward=1 korrigiert werden.
5Warum kollidieren firewalld oder ufw mit Docker?
Diese Tools schreiben das iptables-Regelwerk aus ihrer eigenen Konfiguration heraus neu und können dabei Docker-generierte Regeln versehentlich entfernen oder umordnen, was zu unerwartet blockiertem Container-Traffic führt.
6Was zeigt der Befehl iptables -t nat -L DOCKER -n an?
Er zeigt die von Docker automatisch erzeugten Destination-NAT-Regeln, die eingehenden Traffic auf veröffentlichten Host-Ports zur internen IP-Adresse und dem internen Port des jeweiligen Containers weiterleiten.
7Wozu dienen die Chains DOCKER-ISOLATION-STAGE-1 und STAGE-2?
Sie verhindern, dass Container aus unterschiedlichen Docker-Netzwerken ungewollt direkt miteinander kommunizieren können, und sorgen so für Netzwerkisolation zwischen separaten Bridge-Netzwerken.
8Funktioniert Docker auch mit nftables statt iptables?
Ja, seit Docker 27 gibt es einen nativen nftables-Modus. Die klassische iptables-Kompatibilitätsschicht funktioniert aber ebenfalls weiterhin auf den meisten Systemen ohne Anpassung.
9Wie finde ich heraus, ob eine bestimmte iptables-Regel überhaupt getroffen wird?
Mit iptables -L -n -v werden Paketzähler pro Regel angezeigt. Bleibt der Zähler bei null, wird die Regel nie erreicht, meist weil eine vorherige Regel den Traffic bereits abschließend behandelt hat.
10Muss ich das Docker-Regelwerk manuell pflegen?
Nein, im Normalbetrieb verwaltet Docker seine Chains vollautomatisch. Manuelles Eingreifen ist nur nötig, um eigene, zusätzliche Regeln über DOCKER-USER zu ergänzen oder bei der Fehlersuche nach Konflikten mit anderer Firewall-Software.