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
$ 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
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?