如何更新 Linux 主機 iptables 規則以重新導向 Docker 容器內的流量?

如何更新 Linux 主機 iptables 規則以重新導向 Docker 容器內的流量?

我想將 docker 容器內的出站流量重新對應到不同的連接埠。例如:我想curl 1.2.3.4:8080從容器內實際向 發出請求curl 1.2.3.4:8181。 (這類似於 kube-proxy 對 kubernetes 所做的事情)。

我知道在 docker 容器中我可以運行:

iptables -t nat -A OUTPUT -p tcp -d 1.2.3.4 --dport 8080 -j DNAT --to-destination 1.2.3.4:8181

然後請求將按預期運行。但是,我只想編輯主機上的 iptables 規則以獲得相同的功能。

我有一個 id 的 docker 網絡8e8799c36e69,如果我iptables-save | grep 8e8799c36e69在主機上運行,我會得到以下規則:

-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

是否可以加入這些規則,以便我可以在該網路內設定連接埠重寫? (這個事件是正確的做法嗎?)。

也許只是這樣的事情?

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

或者也許我不需要 docker 橋接網絡,並且我可以以某種方式過濾來自容器內的流量?

編輯:

當我啟動 docker 容器時,它會建立以下規則:

-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

容器172.17.0.2在我的機器上有 ip addr。所以我加入了這條規則:

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

嘗試向172.217.3.110:8080request發送測試請求172.217.3.110:80,但似乎不起作用。

編輯2:

如果我嘗試重寫本地偵聽服務的端口,我可以使用以下命令:

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

這似乎只適用於本地 ip

編輯3: kube-proxy 來源有一些關於他們的方法和各種陷阱的更多資訊:

https://github.com/kubernetes/kubernetes/blob/84dc704/pkg/proxy/userspace/proxier.go#L1133-L1165

https://github.com/kubernetes/kubernetes/blob/84dc7046797aad80f258b6740a98e79199c8bb4d/pkg/proxy/userspace/proxier.go#L1180-L1200

答案1

好吧,想通了。

如果我想將流量從192.168.86.30:80重定向到192.168.86.30:8084具有 IP 位址的容器172.17.0.2,那麼您可以新增以下規則:

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

這似乎也適用於公共外部 IP 位址。

REDIRECT似乎不起作用,因為[來源]

它透過將目標 IP 變更為傳入介面的主位址(本地產生的封包映射到 127.0.0.1 位址),將封包重定向到機器本身。

仍然不完全確定發生了什麼,但我認為這就是為什麼 REDIRECT 可以處理本地服務的某些內容(尤其是在 0.0.0.0 上偵聽的任何內容),但不能處理外部 ip。

相關內容