Ich habe Probleme beim Zugriff auf eine private Host-Schnittstelle (IP) von einem Docker-Container. Ich bin mir ziemlich sicher, dass es mit meinen Iptables-Regeln (oder vielleicht dem Routing) zusammenhängt. Wenn ich die --net=host
Flagge hinzufüge docker run
, funktioniert alles wie erwartet. Wenn ich festlege, dass die INPUT-Richtlinie liberal ist -P INPUT ACCEPT
, funktionieren die Dinge auch so, wie ich es erwartet hätte. Dies sind jedoch unerwünschte und unsichere Optionen, die ich vermeiden möchte.
Da es nicht spezifisch für meine Dienste (DNS) ist, habe ich das vom Problem ausgeschlossen, da die Suche in Kombination mit Docker in einem anderen (beliebten) Problembereich zu Rauschen in den Suchergebnissen führt.
Auch das Verknüpfen von Docker-Containern ist keine praktikable Option, da bestimmte Container mit der Option --net = host ausgeführt werden müssen, um das Verknüpfen zu verhindern, und ich möchte, wo immer möglich, eine konsistente Situation erstellen.
Ich habe die folgenden Iptables-Regeln. Eine Kombination aus CoreOS, Digital Ocean und Docker nehme ich an.
-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth1 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
Meine (relevanten) Host-Schnittstellen:
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
inet 10.129.112.210/16 brd 10.129.255.255 scope global eth1
valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
inet 172.17.42.1/16 scope global docker0
valid_lft forever preferred_lft forever
Und ich betreibe einen Docker-Container:
$ docker run --rm -it --dns=10.129.112.210 debian:jessie # Specifying the DNS is so that the public DNS servers aren't used.
An dieser Stelle möchte ich einen lokalen Dienst verwenden können, der am 10.129.112.210:53 gebunden ist. Damit das Folgende eine Antwort ergibt:
$ ping google.com
^C
$ ping user.skydns.local
^C
Wenn ich denselben Befehl von meinem Host aus ausführe:
$ ping photo.skydns.localPING photo.skydns.local (10.129.112.206) 56(84) bytes of data.
64 bytes from 10.129.112.206: icmp_seq=1 ttl=64 time=0.790 ms
^C
Meine resolv.conf
$ cat /etc/resolv.conf
nameserver 10.129.112.210
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4
Hier geht es nicht darum, über den lokalen DNS-Dienst, der auf dem Host verfügbar ist (über eine andere Docker-Instanz), auf öffentliche, sondern auf interne Hosts zuzugreifen.
Um es noch weiter zu veranschaulichen (Meine Fähigkeiten als Kunstdesigner übertreffen meine iptables fu, so dass an dieser Stelle genug gesagt werden sollte):
______________________________________________
| __________________________ Host |
| | Docker DNS container | |
| ``````````````````````|``` |
| | |
| ,----------,---( private n. interface ) |
| | | |
| | | ( public n. interface )---
| | | |
| | | ( loopbck n. interface ) |
| | | |
| | | |
| | __|_______________________ |
| | | Docker service container | |
| | `````````````````````````` |
| | |
| | |
| [ Local host service using DNS. ] |
| |
|______________________________________________|
private (host) network interface: eth1 (10.129.0.0/16)
Docker network interface: docker0 (172.17.0.0/16)
Ich habe verschiedene Beispiel-Iptables-Konfigurationen gesucht, gelesen und angewendet, aber ich kenne zu wenig der "fortgeschritteneren" Iptables-Regeln, um zu verstehen, was vor sich geht, und so das gewünschte Ergebnis zu erzielen.
Ausgabe von iptables -t nat -nL
:
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
Chain DOCKER (2 references)
target prot opt source destination
Ausgabe von cat /proc/sys/net/ipv4/ip_forward
:
1
iptables -t nat -nL
? Haben Sie eine Paketanalyse durchgeführt, z. B. einen Ping aus dem Quellcontainer ausgeführt und tcpdump verwendet, um die Pakete auf dem Host zu erfassen?$ cat /proc/sys/net/ipv4/ip_forward -> 1
und-A INPUT -i eth1 -j ACCEPT
akzeptiert alle Verbindungen auf der privaten Schnittstelle. Welche Regeln vermisst du?-A INPUT -i docker0 -j ACCEPT
Antworten:
Der Container kommuniziert mit dem Host über die
docker0
Schnittstelle. So lassen Sie Datenverkehr aus dem Container zu:quelle
iptables -A INPUT -j LOG
. Der StempelIN=docker0
wäre sehr nützlich gewesen, um herauszufinden, welche Regeloptimierung erforderlich war. Nicht von Laurentius Arbeit wegzunehmen, die ausgezeichnet war - +1 von mir!Ich bin auf eine sehr ähnliche Situation gestoßen, aber das Hinzufügen
-A INPUT -i docker0 -j ACCEPT
öffnet alle Zugriffe über meine eth0-Schnittstelle des Docker-Hosts auf Container, was absolut nicht das ist, was ich beabsichtigt habe.Und da mir aufgefallen ist, dass mein Container nur eingeschränkten Zugriff (z. B. nur Port 22) auf die Hostschnittstelle hatte, anstatt vom Hostnetzwerk herunterzufahren, habe ich meine iptables-Regeln überprüft und in der Kette IN_public_allow eine Regel gefunden, die dafür verantwortlich sein sollte. Die Regel ist
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
. Daher habe ich ähnliche Regeln hinzugefügt, um meinem Container den Zugriff auf andere gewünschte Host-Ports zu ermöglichen. Dies könnte meiner Meinung nach eine etwas präzisere Möglichkeit sein, den Host-Netzwerkzugriff auf Container zu öffnen.quelle
-i docker0
sollten sicherstellen, dass dies keinen Einfluss auf den Datenverkehr hat, der nicht über das docker0-Netzwerk eingeht. Ihre Grammatik ist jedoch unklar. Vielleicht sagten Sie, dass der ausgehende Zugriff von Docker-Hosts über eth0 aktiviert war, was wahr sein könnte. Ich bin damit einverstanden, dass gezieltere Regeln nur so oft geöffnet werden können, wie Sie es benötigen.