Iptables-Regelsatz, mit dem ein Docker-Container auf einen Dienst auf einer Host-IP zugreifen kann


18

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=hostFlagge 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

Kannst du die Ausgabe von posten 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?
Daniel t.

Sicher, danke für deine Hilfe: pastebin.com/TAaT73nk (Nicht in den Kommentar gepasst.) - Bearbeiten -> Der Link zu einem Pastebin, der nicht abläuft, wurde aktualisiert.
Dynom

Vielleicht habe ich Ihr Problem nicht richtig verstanden, aber ich sehe keine Regel, um DNS-Abfragen auf dem Host zuzulassen. Ist auch ip_forward aktiviert?
Laurentiu Roescu

Hi @LaurentiuRoescu. $ cat /proc/sys/net/ipv4/ip_forward -> 1und -A INPUT -i eth1 -j ACCEPTakzeptiert alle Verbindungen auf der privaten Schnittstelle. Welche Regeln vermisst du?
Dynom

2
Ich denke, Pakete aus Container kommen von Docker0-Schnittstelle, nicht eth1. versuchen-A INPUT -i docker0 -j ACCEPT
Laurentiu Roescu

Antworten:


14

Der Container kommuniziert mit dem Host über die docker0Schnittstelle. So lassen Sie Datenverkehr aus dem Container zu:

-A INPUT -i docker0 -j ACCEPT

2
Dynom, eine Lehre, die Sie vielleicht daraus ziehen möchten, ist, dass es nützlich ist, alle Ihre Ablehnungen zu protokollieren, z iptables -A INPUT -j LOG. Der Stempel IN=docker0wäre sehr nützlich gewesen, um herauszufinden, welche Regeloptimierung erforderlich war. Nicht von Laurentius Arbeit wegzunehmen, die ausgezeichnet war - +1 von mir!
MadHatter unterstützt Monica

5
Für Benutzer, die UFW verwenden, habe ich Folgendes getan, um die gesamte Kommunikation von Docker-Containern zum Host zuzulassen: ufw allow in on docker0
Ali Ok

0

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.


-i docker0sollten 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.
mc0e
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.