Ich möchte ausgehenden Datenverkehr innerhalb eines Docker-Containers auf einen anderen Port umleiten. Beispiel: Ich möchte curl 1.2.3.4:8080
aus dem Container heraus und die Anforderung tatsächlich an senden curl 1.2.3.4:8181
. (Dies ist ähnlich dem, was kube-proxy für Kubernetes macht.)
Ich verstehe, dass ich in einem Docker-Container Folgendes ausführen kann:
iptables -t nat -A OUTPUT -p tcp -d 1.2.3.4 --dport 8080 -j DNAT --to-destination 1.2.3.4:8181
Und dann verhalten sich die Anfragen wie gewünscht. Ich möchte jedoch nur die iptables-Regeln auf dem Host bearbeiten, um die gleiche Funktionalität zu erhalten.
Ich habe ein Docker-Netzwerk mit der ID 8e8799c36e69
. Wenn ich es iptables-save | grep 8e8799c36e69
auf dem Host ausführe, erhalte ich die folgenden Regeln:
-A POSTROUTING -s 172.18.0.0/16 ! -o br-8e8799c36e69 -j MASQUERADE
-A DOCKER -i br-8e8799c36e69 -j RETURN
-A FORWARD -o br-8e8799c36e69 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-8e8799c36e69 -j DOCKER
-A FORWARD -i br-8e8799c36e69 ! -o br-8e8799c36e69 -j ACCEPT
-A FORWARD -i br-8e8799c36e69 -o br-8e8799c36e69 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i br-8e8799c36e69 ! -o br-8e8799c36e69 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-2 -o br-8e8799c36e69 -j DROP
Ist es möglich, diese Regeln anzuzapfen, sodass ich meine Port-Neuschreibung nur innerhalb dieses Netzwerks einrichten kann? (Ist dieses Ereignis der richtige Ansatz?).
Vielleicht einfach so etwas?
iptables -t nat -I OUTPUT -o br-8e8799c36ec9 --src 0/0 --dst 1.2.3.4 -p tcp --dport 8080 -j REDIRECT --to-ports 8181
Oder brauche ich das Docker-Bridge-Netzwerk vielleicht nicht und kann den Datenverkehr, der aus dem Container kommt, irgendwie filtern?
bearbeiten:
Wenn ich einen Docker-Container starte, werden diese Regeln erstellt:
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 8080 -j MASQUERADE
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:8080
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8080 -j ACCEPT
Der Container hat eine IP-Adresse 172.17.0.2
auf meinem Rechner. Daher habe ich diese Regel hinzugefügt:
sudo iptables -t nat -A OUTPUT -s 172.17.0.2/32 -p tcp -d 172.217.3.110 --dport 8080 -j DNAT --to-destination 172.217.3.110:80
Ich habe versucht, eine Testanfrage zu erhalten 172.217.3.110:8080
, 172.217.3.110:80
aber es scheint nicht zu funktionieren.
Bearbeitung 2:
Wenn ich versuche, einen Port für einen lokal lauschenden Dienst neu zu schreiben, funktioniert es folgendermaßen:
LOCAL_IP=192.168.86.30
REQUESTED_PORT=80
DESTINATION_PORT=8080
CONTAINER_IP=172.17.0.2
sudo iptables -t nat -A OUTPUT -p tcp -d $LOCAL_IP --dport $REQUESTED_PORT -j DNAT --to-destination :$DESTINATIO_PORT
sudo iptables -t nat -I PREROUTING -s $CONTAINER_IP -d $LOCAL_IP -p tcp --dport $REQUESTED_PORT -j REDIRECT --to-ports $DESTINATION_PORT
das scheint nur mit lokalen IPs zu funktionieren
Bearbeitung 3: Die Kube-Proxy-Quelle enthält weitere Informationen zu ihrem Ansatz und verschiedenen Fallstricken:
https://github.com/kubernetes/kubernetes/blob/84dc704/pkg/proxy/userspace/proxier.go#L1133-L1165
Antwort1
OK, habe es herausgefunden.
192.168.86.30:80
Wenn ich den Datenverkehr von zu 192.168.86.30:8084
einem Container mit einer IP-Adresse umleiten möchte, 172.17.0.2
können Sie die folgende Regel hinzufügen:
sudo iptables -t nat -A PREROUTING --protocol tcp --destination 192.168.86.30 \
--dport 80 --source 172.17.0.2 \
--jump DNAT --to-destination 192.168.86.30:8084
Dies scheint auch mit öffentlichen externen IP-Adressen zu funktionieren.
REDIRECT
scheint nicht zu funktionieren, weil[Quelle]:
Es leitet das Paket an die Maschine selbst um, indem es die Ziel-IP in die primäre Adresse der eingehenden Schnittstelle ändert (lokal generierte Pakete werden der Adresse 127.0.0.1 zugeordnet).
Ich bin mir immer noch nicht ganz sicher, was da los war, aber ich glaube, das ist der Grund, warum REDIRECT bei einigen lokal bereitgestellten Dingen funktionierte (insbesondere bei allem, was auf 0.0.0.0 lauschte), aber nicht bei externen IPs.