Mein Ziel ist es, den Zugriff auf Docker-Container auf nur wenige öffentliche IP-Adressen zu beschränken. Gibt es einen einfachen, wiederholbaren Prozess, um mein Ziel zu erreichen? Wenn ich nur die Grundlagen von iptables verstehe, während ich die Standardoptionen von Docker verwende, fällt es mir sehr schwer.
Ich möchte einen Container ausführen, ihn für das öffentliche Internet sichtbar machen, aber nur Verbindungen von ausgewählten Hosts zulassen. Ich würde erwarten, eine Standardeingaberichtlinie von ABLEHNEN festzulegen und dann nur Verbindungen von meinen Hosts zuzulassen. Aber die NAT-Regeln und -Ketten von Docker stören und meine Eingabevorschriften werden ignoriert.
Kann jemand ein Beispiel dafür geben, wie ich mein Ziel unter den folgenden Annahmen erreichen kann?
Öffentliche Host-IP 80.80.80.80 auf eth0
Private Host-IP 192.168.1.10 auf eth1
docker run -d -p 3306:3306 mysql
Blockieren Sie alle Verbindungen zu Host / Container 3306 mit Ausnahme der Hosts 4.4.4.4 und 8.8.8.8
Ich bin gerne bereit, den Container nur an die lokale IP-Adresse zu binden, benötige jedoch Anweisungen zum ordnungsgemäßen Einrichten der iptables-Weiterleitungsregeln, die den Docker-Prozess und Host-Neustarts überstehen.
Zwei Dinge, die Sie bei der Arbeit mit den Firewall-Regeln von Docker beachten sollten:
Um zu vermeiden, dass Ihre Regeln von Docker überlastet werden, verwenden Sie die DOCKER-USER Kette
Docker macht das Port-Mapping in der PREROUTING kette der nat Tabelle. Dies geschieht vor dem filter regeln, also --dest und --dport sehen Sie die interne IP und den Port des Containers. Um auf das ursprüngliche Ziel zuzugreifen, können Sie Folgendes verwenden -m conntrack --ctorigdstport.
Beispielsweise:
iptables -A DOCKER-USER -i eth0 -s 8.8.8.8 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j ACCEPTiptables -A DOCKER-USER -i eth0 -s 4.4.4.4 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j ACCEPTiptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 3306 --ctdir ORIGINAL -j DROP
HINWEIS: Ohne --ctdir ORIGINAL, dies würde auch mit den Antwortpaketen übereinstimmen, die für eine Verbindung vom Container zum Port 3306 auf einem anderen Server zurückkommen, was mit ziemlicher Sicherheit nicht das ist, was Sie wollen! Sie brauchen das nicht unbedingt, wenn Ihre erste Regel wie ich lautet -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT, da das mit allen Antwortpaketen umgehen wird, aber es wäre sicherer, immer noch zu verwenden --ctdir ORIGINAL Wie dem auch sei.
Im Gegensatz zum Ketten-DOCKER wird es beim Erstellen / Starten von Containern nicht zurückgesetzt. Sie können diese Zeilen also zu Ihrer iptables-Konfiguration / Ihrem iptables-Skript hinzufügen, um den Server bereitzustellen, noch bevor Sie Docker installieren und die Container starten:
Jetzt ist der Port für MySQL für den externen Zugriff gesperrt (eth0), obwohl Docker den Port für die Welt öffnet. (Diese Regeln setzen voraus, dass Ihre externe Schnittstelle eth0 ist.)
Schließlich müssen Sie iptables bereinigen und zuerst den Docker-Dienst neu starten, wenn Sie es zu sehr durcheinander gebracht haben, den Port wie ich zu sperren.
Ich habe ein Docker-Image erstellt, das diese Methode verwendet, um die Iptables automatisch für Sie zu verwalten, entweder mithilfe von Umgebungsvariablen oder dynamisch mit etcd (oder beidem):
Die Vorwärtsregeln von Docker erlauben standardmäßig alle externen Quell-IPs. Um nur einer bestimmten IP oder einem bestimmten Netzwerk den Zugriff auf die Container zu gestatten, fügen Sie oben in der DOCKER-Filterkette eine negierte Regel ein. Um beispielsweise den externen Zugriff so einzuschränken, dass nur die Quell-IP 8.8.8.8 auf die Container zugreifen kann, könnte die folgende Regel hinzugefügt werden: iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP