So erhalten Sie die wahre Client-IP für einen Dienst, der in Docker ausgeführt wird

7

Mein Szenario: Ich möchte, dass meine Docker-basierten Dienste wissen, welche IP sie aus dem Web aufruft (eine Anforderung meiner Anwendung).

Ich laufe auf einem Cloud-VPS, Debian Jessie, mit Docker 1.12.2.

Ich benutze ncim ausführlichen Modus, um den Port zu öffnen 8080.

docker run --rm -p "8080:8080" centos bash -c "yum install -y nc && nc -vv -kl -p 8080"

Angenommen, der VPS hat die Domäne example.comund von meinem anderen Computer, der beispielsweise die IP-Adresse hat, die dead:::::beefich anrufe

nc example.com 8080

Der Server sagt:

Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Listening on :::8080
Ncat: Listening on 0.0.0.0:8080
Ncat: Connection from 172.17.0.1.
Ncat: Connection from 172.17.0.1:49799.

172.17.0.1befindet sich im lokalen Netzwerk des Servers und hat natürlich nichts mit meinem Client zu tun. Eigentlich:

docker0   Link encap:Ethernet  HWaddr ....
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0

Wenn ich den Container im Host-Netzwerkmodus starte

docker run --rm --net=host -p "8080:8080" centos bash -c "yum install -y nc && nc -vv -kl -p 8080"

und rufe meinen Server erneut an

nc example.com 8080

Ich bekomme das erwartete Ergebnis:

Ncat: Connection from dead:::::beef.
Ncat: Connection from dead:::::beef:55650.

Meine Fragen sind:

  • Warum "maskiert" Docker IPs, wenn es sich nicht im Host-Netzwerkmodus befindet? Ich denke, der Docker-Daemon-Prozess ist wahrscheinlich derjenige, der den Port öffnet, die Verbindung empfängt und sie dann über seine eigene interne virtuelle Netzwerkschnittstellenverbindung an den Containerprozess weiterleitet. ncWenn Sie im Container ausgeführt werden, wird nur angezeigt, dass der Aufruf von der IP-Adresse des Docker-Daemons stammt.
  • (Wie) kann ich meinen Docker-Dienst über externe IP-Adressen informieren, die ihn aufrufen, ohne alles in den Host-Modus zu versetzen?
Aleksandar Dimitrov
quelle

Antworten:

6

Gemäß der Dokumentation , der Standardtreiber (dh , wenn Sie nicht angeben , --net=hostin docker run, ist der bridgeNetzwerktreiber.

Es geht nicht darum, dass Docker die IP-Adressen "maskieren", sondern darum, wie bridgedund hostNetzwerkmodi variieren.

In Bezug auf Docker verwendet ein Brückennetzwerk eine Softwarebrücke, mit der Container, die mit demselben Brückennetzwerk verbunden sind, kommunizieren können, während eine Isolierung von Containern bereitgestellt wird, die nicht mit diesem Brückennetzwerk verbunden sind. Der Docker-Brückentreiber installiert automatisch Regeln auf dem Hostcomputer, sodass Container in verschiedenen Brückennetzwerken nicht direkt miteinander kommunizieren können.

Docker erstellt ein isoliertes Netzwerk, sodass jeder Container im überbrückten Netzwerk kommunizieren kann, in Ihrem Fall docker0. Standardmäßig kommunizieren die Container auf Ihrem Docker-Host innerhalb dieses Netzwerks.

Wie Sie vielleicht bereits herausgefunden haben, ist yes 172.17.0.1die Standardroute im docker0Netzwerk, aber dies fungiert nicht als Router, der Pakete an das Ziel weiterleitet. Daher sehen Sie es als Quelle aus der Ausgabe von netcat.

Sie können dies überprüfen, indem Sie es ss -tulnpauf Ihrem Docker-Host ausführen. Sie sollten sehen, dass der Prozess, der Port 8080 überwacht, Docker ist.

Auf der anderen Seite bedeutet die Verwendung des Host- Netzwerktreibers, dass keine Isolation zwischen dem Container und dem Host besteht. Sie können dies überprüfen, indem Sie es ss -tulnpauf Ihrem Docker-Host ausführen. Sie sollten sehen, wie der Prozess auf Socket anstatt auf Docker lauscht (in Ihrem Fall sollten Sie sehen nc).

Lester
quelle
1
Ich merke gerade, dass ich auf einen 2 Jahre alten unbeantworteten Beitrag geantwortet habe. Selbst wenn OP die Antwort nicht mehr benötigt, würde dies hoffentlich noch jemand nützlich finden.
Lester
1
Genau deshalb erlauben und fördern wir die Beantwortung alter Fragen. 1600 Menschen kamen hierher und fanden keine Antwort. Jetzt werden zukünftige Leute.
Michael Hampton
Danke für die Antwort, egal ob es spät ist. Ich weiß nicht, ob ich herausfinden kann, ob dies die akzeptierte Antwort sein sollte, da ich vergessen habe, dass ich jemals dieses Problem hatte. Ich werde sehen, ob ich es herausfinden kann und ob es das ursprüngliche Problem löst. Danke trotzdem!
Aleksandar Dimitrov
Ich habe ein ähnliches Problem, obwohl die Container nicht direkt miteinander sprechen: Ich habe einen Prometheus- und einen Grafana-Container auf derselben Box, vor denen ein einzelner Nginx (kein Container) die TLS-Terminierung und das Routing übernimmt. Grafana verwendet den Public-Domain-Namen von prometheus. In den Nginx-Protokollen für Prometheus wird jedoch die Anfrage aus dem Subnetz 172.17.0.0/24 anstelle der öffentlichen IP-Adresse meines Servers angezeigt, was ich äußerst verwirrend finde.
Sakis Vtdk