Docker
Iptables mit Docker
Suche…
Einführung
In diesem Thema wird beschrieben, wie Sie den Zugriff auf Ihre Docker-Container mithilfe von iptables von außerhalb der Welt einschränken.
Für ungeduldige Menschen können Sie die Beispiele überprüfen. Für die anderen lesen Sie bitte den Bemerkungsabschnitt, um zu erfahren, wie Sie neue Regeln erstellen.
Syntax
- iptables -I DOCKER [RULE ...] [ACCEPT | DROP] // Eine Regel oben in der DOCKER-Tabelle hinzufügen
- iptables -D DOCKER [RULE ...] [ACCEPT | DROP] // Eine Regel aus der DOCKER-Tabelle entfernen
- ipset restore </etc/ipfriends.conf // Um Ihre ipset ipfriends neu zu konfigurieren
Parameter
Parameter | Einzelheiten |
---|---|
ext_if | Ihre externe Schnittstelle auf dem Docker-Host. |
XXX.XXX.XXX.XXX | Eine bestimmte IP-Adresse, auf die Docker-Container zugreifen, sollte angegeben werden. |
YYY.YYY.YYY.YYY | Eine weitere IP, auf die Docker-Container zugreifen sollen, sollte angegeben werden. |
ipfriends | Der ipset-Name, der die IPs definiert, die zum Zugriff auf Ihre Docker-Container berechtigt sind. |
Bemerkungen
Das Problem
Das Konfigurieren von iptables-Regeln für Docker-Container ist etwas schwierig. Zuerst würden Sie denken, dass "klassische" Firewall-Regeln den Trick tun sollten.
Nehmen wir beispielsweise an, Sie haben einen nginx-proxy-Container + mehrere Service-Container konfiguriert, um einige persönliche Web-Services über HTTPS verfügbar zu machen. Dann sollte eine Regel wie diese nur für IP XXX.XXX.XXX.XXX Zugriff auf Ihre Webdienste gewähren.
$ iptables -A INPUT -i eth0 -p tcp -s XXX.XXX.XXX.XXX -j ACCEPT
$ iptables -P INPUT DROP
Es funktioniert nicht, Ihre Container sind für jeden zugänglich.
In der Tat sind Docker-Container keine Hostdienste. Sie sind auf ein virtuelles Netzwerk in Ihrem Host angewiesen, und der Host fungiert als Gateway für dieses Netzwerk. In Bezug auf Gateways wird gerouteter Verkehr nicht von der INPUT-Tabelle verarbeitet, sondern von der FORWARD-Tabelle, die die Veröffentlichung der Regel als unwirksam macht.
Aber es ist noch nicht alles. In der Tat erstellt der Docker-Daemon eine Vielzahl von iptables-Regeln, wenn er seine Magie in Bezug auf die Netzwerkkonnektivität von Containern beginnt. Insbesondere wird eine DOCKER-Tabelle erstellt, um Regeln für Container zu behandeln, indem der Verkehr von der FORWARD-Tabelle an diese neue Tabelle weitergeleitet wird.
$ iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-ISOLATION all -- anywhere anywhere
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (2 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.18.0.4 tcp dpt:https
ACCEPT tcp -- anywhere 172.18.0.4 tcp dpt:http
Chain DOCKER-ISOLATION (1 references)
target prot opt source destination
DROP all -- anywhere anywhere
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
Die Lösung
Wenn Sie die offizielle Dokumentation ( https://docs.docker.com/v1.5/articles/networking/) lesen , wird eine erste Lösung angegeben, um den Zugriff des Docker-Containers auf eine bestimmte IP-Adresse zu beschränken.
$ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP
Das Hinzufügen einer Regel oben in der DOCKER-Tabelle ist eine gute Idee. Die von Docker automatisch konfigurierten Regeln werden nicht beeinträchtigt. Dies ist einfach. Aber zwei Hauptmängel:
- Erstens, was ist, wenn Sie von zwei IP-Adressen aus auf eine zugreifen müssen? Hier kann nur eine Src-IP akzeptiert werden, eine andere wird verworfen, ohne dass dies verhindert werden kann.
- Zweitens, was ist, wenn Ihr Docker Zugang zum Internet benötigt? Praktisch keine Anfrage wird erfolgreich sein, da nur der Server 8.8.8.8 darauf reagieren könnte.
- Was ist schließlich, wenn Sie weitere Logiken hinzufügen möchten? Geben Sie beispielsweise jedem Benutzer Zugriff auf Ihren Webserver, der über das HTTP-Protokoll bereitgestellt wird, beschränken Sie jedoch alles andere auf eine bestimmte IP-Adresse.
Für die erste Beobachtung können wir ipset verwenden . Anstatt eine IP in der obigen Regel zuzulassen, lassen wir alle IPs aus dem vordefinierten ipset zu. Als Bonus kann das ipset aktualisiert werden, ohne dass die iptable-Regel neu definiert werden muss.
$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP
Für die zweite Beobachtung ist dies ein kanonisches Problem für Firewalls: Wenn Sie einen Server über eine Firewall kontaktieren dürfen, sollte die Firewall den Server dazu berechtigen, auf Ihre Anfrage zu antworten. Dies kann durch Autorisieren von Paketen geschehen, die sich auf eine bestehende Verbindung beziehen. Für die Docker-Logik gibt es:
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT
Die letzte Beobachtung konzentriert sich auf einen Punkt: iptables-Regeln sind wesentlich. Tatsächlich muss eine zusätzliche Logik zum ACCEPT-Aktivieren einiger Verbindungen (einschließlich der Verbindungen, die ESTABLISHED-Verbindungen betreffen) vor der DROP-Regel an die Spitze der DOCKER-Tabelle gestellt werden, die alle verbleibenden Verbindungen ablehnen, die nicht zum ipset passen.
Da wir die Option -I von iptable verwenden, die Regeln oben in der Tabelle einfügt, müssen die vorherigen iptables-Regeln in umgekehrter Reihenfolge eingefügt werden:
// Drop rule for non matching IPs
$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP
// Then Accept rules for established connections
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 3rd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 2nd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 1st custom accept rule
In Anbetracht dessen können Sie nun die Beispiele überprüfen, die diese Konfiguration veranschaulichen.
Beschränken Sie den Zugriff auf Docker-Container auf eine Reihe von IP-Adressen
Installieren Sie zuerst ipset, falls erforderlich. Bitte beziehen Sie sich auf Ihre Distribution, um zu erfahren, wie es geht. Als Beispiel ist hier der Befehl für Debian-ähnliche Distributionen.
$ apt-get update
$ apt-get install ipset
Erstellen Sie anschließend eine Konfigurationsdatei, um ein ipset zu definieren, das die IPs enthält, für die Sie Zugriff auf Ihre Docker-Container öffnen möchten.
$ vi /etc/ipfriends.conf
# Recreate the ipset if needed, and flush all entries
create -exist ipfriends hash:ip family inet hashsize 1024 maxelem 65536
flush
# Give access to specific ips
add ipfriends XXX.XXX.XXX.XXX
add ipfriends YYY.YYY.YYY.YYY
Laden Sie dieses ipset.
$ ipset restore < /etc/ipfriends.conf
Stellen Sie sicher, dass Ihr Docker-Dämon ausgeführt wird: Nach Eingabe des folgenden Befehls sollte kein Fehler angezeigt werden.
$ docker ps
Sie können nun Ihre iptables-Regeln einfügen. Sie müssen die Reihenfolge respektieren.
// All requests of src ips not matching the ones from ipset ipfriends will be dropped.
$ iptables -I DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
// Except for requests coming from a connection already established.
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT
Wenn Sie neue Regeln erstellen möchten, müssen Sie vor dem Einfügen der neuen Regeln alle benutzerdefinierten Regeln entfernen, die Sie hinzugefügt haben.
$ iptables -D DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
$ iptables -D DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT
Konfigurieren Sie den Einschränkungszugriff beim Starten des Docker-Daemons
In Arbeit
Einige benutzerdefinierte iptables-Regeln
In Arbeit