ADMIN

2021

02

2021-02-01T12:00:00

Sichere Virtualisierung

PRAXIS

056

Security-Tipp

Netzwerkmanagement

Docker und IPTables

Geregelte Container-Kommunikation

von Matthias Wübbeling

Veröffentlicht in Ausgabe 02/2021 - PRAXIS

Docker ermöglicht die Konfiguration virtueller Netzwerke und verwendet unter Linux seinerseits ausgiebig IPTables zur Konfiguration der Netzwerkkommunikation zwischen den Containern, dem Hostsystem und entfernten Computern. Zur Absicherung laufender Container genügt es jedoch nicht, nur die INPUT-Chain des Hosts für die Filterung des eingehenden Datenverkehrs zu betrachten. Der Security-Tipp in diesem Monat zeigt Möglichkeiten auf, die IPTables-Konfiguration in Einklang mit Docker zu bringen.

Als Firewall-Administrator kennen Sie vielleicht das Gefühl, wenn Sie Ihren Regelsatz um eine Filterregel erweitert haben und im Nachgang feststellen, dass diese gar nicht den angedachten Zweck erfüllt. IPTables als Paketfilter ist auf Linux-Systemen heute noch immer das Mittel der Wahl. Automatisch hinzugefügte Regeln – etwa solche, wie sie der Docker-Daemon erstellt – führen dabei aber immer wieder zu Nebeneffekten auf manuell oder halbautomatisiert angelegte Regelsätze. Das größere Sicherheitsproblem entsteht jedoch, wenn eine Regel eingehende Pakete filtern soll, diese aber beim Eingang von Paketen für Docker-Container gar nicht berücksichtigt wird.
Tabellen und Ketten
Die grundsätzliche Organisation von Filterregeln in IPTables ist schnell erklärt. Zunächst gibt es die drei bekanntesten Tabellen: "filter", "mangle" und "nat". Dabei werden in der Filtertabelle maßgeblich solche Regeln angelegt, die sprichwörtlich einen Paketfilter ausmachen. Die Mangle-Tabelle erlaubt Ihnen insbesondere die Manipulation der Felder des IP-Headers, aber auch die Markierung der Pakete im Kernel, um diese beim Durchlauf durch die IPTables-Ketten in anderen Regeln wiederzuerkennen.
Innerhalb der Nat-Tabelle können Sie Regeln definieren, um bei der Paketweiterleitung eine Adressübersetzung der Pakete zu bewirken. Das kennen Sie etwa von Ihrem Heimrouter, wo Sie aus Ihrem privaten Netzbereich mittels NAT in der Lage sind, Pakete in das Internet zu senden und empfangene Pakete wieder den entsprechenden Computer in Ihrem privaten Netzwerk zuzuordnen. Die Tabellen "raw" und "security" kommen deutlich seltener zum Einsatz und bieten etwa die Funktionalität, um das Tracken von Verbindungen zu verhindern, oder zum Markieren von Paketen in SELinux-Kontexten.
Als Firewall-Administrator kennen Sie vielleicht das Gefühl, wenn Sie Ihren Regelsatz um eine Filterregel erweitert haben und im Nachgang feststellen, dass diese gar nicht den angedachten Zweck erfüllt. IPTables als Paketfilter ist auf Linux-Systemen heute noch immer das Mittel der Wahl. Automatisch hinzugefügte Regeln – etwa solche, wie sie der Docker-Daemon erstellt – führen dabei aber immer wieder zu Nebeneffekten auf manuell oder halbautomatisiert angelegte Regelsätze. Das größere Sicherheitsproblem entsteht jedoch, wenn eine Regel eingehende Pakete filtern soll, diese aber beim Eingang von Paketen für Docker-Container gar nicht berücksichtigt wird.
Tabellen und Ketten
Die grundsätzliche Organisation von Filterregeln in IPTables ist schnell erklärt. Zunächst gibt es die drei bekanntesten Tabellen: "filter", "mangle" und "nat". Dabei werden in der Filtertabelle maßgeblich solche Regeln angelegt, die sprichwörtlich einen Paketfilter ausmachen. Die Mangle-Tabelle erlaubt Ihnen insbesondere die Manipulation der Felder des IP-Headers, aber auch die Markierung der Pakete im Kernel, um diese beim Durchlauf durch die IPTables-Ketten in anderen Regeln wiederzuerkennen.
Innerhalb der Nat-Tabelle können Sie Regeln definieren, um bei der Paketweiterleitung eine Adressübersetzung der Pakete zu bewirken. Das kennen Sie etwa von Ihrem Heimrouter, wo Sie aus Ihrem privaten Netzbereich mittels NAT in der Lage sind, Pakete in das Internet zu senden und empfangene Pakete wieder den entsprechenden Computer in Ihrem privaten Netzwerk zuzuordnen. Die Tabellen "raw" und "security" kommen deutlich seltener zum Einsatz und bieten etwa die Funktionalität, um das Tracken von Verbindungen zu verhindern, oder zum Markieren von Paketen in SELinux-Kontexten.
In jeder der fünf Tabellen gibt es unterschiedliche Regelketten (Chains), die der Reihe nach von oben nach unten durchlaufen, bis eine Regel auf das überprüfte Paket anzuwenden ist. Dabei gibt es fest eingebaute Ketten, aber auch die Möglichkeit für Benutzer, weitere Ketten zu definieren. Diese zusätzlichen Ketten dienen dabei hauptsächlich der Strukturierung und Ordnung von Regeln und erleichtern etwa das automatisierte Erstellen und Ändern von Regeln.
Regeln für Docker
Der Docker-Daemon, der zwingende Voraussetzung für die Nutzung der Docker-Containervirtualisierung ist, erstellt beim Start bereits eigene Chains und Regeln. Ohne einen laufenden Container handelt es sich dabei aber nur um die Unterstruktur zur Ordnung der später automatisch angelegten Regeln. Wie im Bild zu sehen, werden dafür in der Filtertabelle die folgenden vier Chains angelegt: "DOCKER", "DOCKER-USER", "DOCKER-ISOLATION-STAGE1" und "DOCKER-ISOLATION-STAGE2". Diese sollten Sie, mit Ausnahme der Chain "DOCKER-USER", möglichst nicht verändern.
Docker verwendet ein virtualisiertes Netzwerk mit eigenem Interface, im Normalfall mit dem Namen "docker0". Dafür kommen in der Forward-Chain Regeln für die Weiterleitung der Pakete an diesem Interface an die laufenden Container zum Einsatz. Docker nutzt für das Interface und die Container private IP-Adressen aus dem Bereich 172.16.0.0/20. Um aus den Containern heraus den Netzwerkzugang des Hostsystems zu ermöglichen, werden in der NAT-Tabelle entsprechende Regeln mit Source- und Destination-NAT für jeden Container erzeugt. Mit diesen Regeln funktioniert die Kommunikation der Container in alle Richtungen und auch untereinander. Wenn Sie ein separates Netzwerk für Ihre Container erzeugen, erstellt Docker ein eigenes Bridge-Interface für jedes dieser Netzwerke und erweitert die Filterregeln dann automatisch um entsprechende Regeln für die Bridge-Interfaces.
Die Chain DOCKER-USER ermöglicht das Hinterlegen eigener Regeln.
Fallstricke
Änderungen an den Regeln und Chains in den IPTables-Tabellen können mitunter dazu führen, dass Ihre Container nicht mehr erreichbar sind. Daher ist IPTables immer eine der ersten Anlaufstellen bei Netzwerkproblemen von Containern. Je nachdem, wie Sie Ihre eigenen Regeln verwalten, verwenden Sie vielleicht vor der Erstellung die Option "-F", um die Tabellen oder einzelne Chains darin zu leeren. Im Anschluss an einen Flush sind Ihre Docker-Container erwartungsgemäß von der Außenwelt und voneinander abgeschottet. Bevor Sie versuchen, die automatisch erstellten Regeln in ihren Tools auszulesen und nach einem Flush wieder einzuspielen, hilft Ihnen ein Neustart des Docker-Daemons bei der zuverlässigen Wiederherstellung.
Um allgemein den Zugriff auf Dienste Ihres Computers zu verhindern, erstellen Sie üblicherweise Regeln in der Input-Chain der Filtertabelle. Bestenfalls setzen Sie die Policy dieser Chain auf DROP und geben je nach Bedarf einzelne Ports oder Protokolle frei. Sie werden schnell feststellen, dass Ihre Container-Dienste trotz dieser Maßnahme nach wie vor auch von außen erreichbar sind. Der Versuch, IPTables-Regeln innerhalb der Container zu setzen, scheitert in der Regel an fehlenden Rechten. Sie könnten über zusätzliche Capabilities Ihren Docker-Container im privilegierten Modus starten, das ist aus unterschiedlichen Gründen aber zumindest nicht bei jedem Container gewollt.
Möchten Sie den Zugriff auf die Dienste eines Containers von außen einschränken, müssen Sie also zusätzliche Regeln in der Forward-Chain erstellen. Während Docker die Input- und die Output-Chain unangetastet lässt, verwendet es die Forward-Chain aber sehr rege und rücksichtslos. Da Docker sich selbst immer wieder auf den ersten Rängen der Chains platziert, diese Regeln finden also als Erstes Anwendung, rutschen ihre manuellen Regeln zuweilen immer weiter nach hinten und werden so in einigen Fällen gar nicht mehr beachtet.
Docker sieht für Ihre eigenen Regeln nämlich die oben bereits erwähnte Chain "DOCKER-USER" vor. Betrachten Sie noch einmal die eingetragenen Regeln aus dem Schaubild. Dort können Sie sehen, dass diese Chain vor den anderen Regeln in der Forward-Chain abgeprüft wird. Das ist Ihre Chance, dort Ihre Filterregeln zu hinterlegen.
Im Folgenden gehen wir davon aus, dass Sie einen Container mit einem eigenen virtuellen Netzwerk betreiben, also mit einer zufällig benannten Bridge. Möchten Sie nun beispielsweise den Zugriff auf Port 443 eines Containers in diesem Netzwerk verhindern, müssen Sie zunächst herausfinden, welche Bridge dem virtuellen Netzwerk zugeordnet ist. Das gelingt Ihnen mit dem Kommando docker network list. Suchen Sie den Namen des erstellten Netzwerks, steht in dem Eintrag an erster Stelle die Netzwerk-ID. Standardmäßig benennt Docker die Bridges mit "br-<NetzwerkID>". Eine Übersicht aller Bridges erhalten Sie mit dem Kommando brctl show.
Um den von Docker zugewiesenen Adressbereich der Bridge zu erfahren, verwenden Sie ifconfig und übergeben den Namen der Bridge als Argument, zum Beispiel so:
ifconfig br-2881be13f7f9
Nun können Sie den Zugriff auf dieses Netzwerk von außen weiter einschränken. Mit dem folgenden Kommando verhindern Sie den Zugriff auf die MySQL-Datenbank innerhalb des Netzwerks:
iptables -I DOCKER-USER -o br-2881be13f7f9 -p tcp --dport 3306 -j DROP
Natürlich können Sie auch für die virtuellen Netzwerke anhand der individuellen IP-Adressen Ihrer Container den Zugriff auf einzelne Dienste erlauben oder verhindern, solange Sie Ihren Containern feste IP-Adressen zuordnen.
Sollten Sie für Ihr Hostsystem, unabhängig von Docker, weitere Regeln zur Weiterleitung von Paketen benötigen, verwenden Sie bestenfalls auch die DOCKER-USER-Chain. Es ist zwar unwahrscheinlich, dass Docker Ihnen Pakete ausfiltert, die nicht an Container adressiert sind, aber Ihre eigenen Regeln in der DOCKER-USER-Chain werden immer vor allen anderen ausgeführt und gelten eben nicht nur für Ziele in Docker-Containern. Sie verhindern also, dass Sie durch Unachtsamkeit selbst die Weiterleitungsregeln verhindern.
Fazit
Die Netzwerkkonfigurationen von Docker-Umgebungen fallen mitunter recht komplex aus. Dort als Admin manuell Einstellungen zu setzen, ist alles andere als empfehlenswert. Da die meisten Container auch netzwerktechnisch isoliert sind, greifen die klassischen Input- und Output-Regeln auf dem Host nicht. Der Security-Tipp in diesem Monat hat Ihnen gezeigt, wie Sie Ihre Docker-Container zuverlässig schützen und dabei Ihre eigenen Forward-Regeln zuverlässig platzieren können.
(dr)