Linux ホストの iptables ルールを更新して、Docker コンテナ内のトラフィックをリダイレクトするにはどうすればよいですか?

Linux ホストの iptables ルールを更新して、Docker コンテナ内のトラフィックをリダイレクトするにはどうすればよいですか?

Docker コンテナ内からの送信トラフィックを別のポートに再マップしたいと思います。例:curl 1.2.3.4:8080コンテナ内から を行い、リクエストが実際に に送信されるようにしますcurl 1.2.3.4:8181(これは、kubernetes に対して kube-proxy が行うことと似ています)。

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 ネットワークがあり8e8799c36e69iptables-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 アドレスがあります。そこで、次のルールを追加しました:

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:8080172.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

github.com/kubernetes/kubernetes/blob/84dc7046797aad80f258b6740a98e79199c8bb4d/pkg/proxy/userspace/proxier.go#L1180-L1200 を参照してください。

答え1

わかりました。分かりました。

IP アドレスを持つコンテナのトラフィック192.168.86.30:80を にリダイレクトする場合は、次のルールを追加できます。192.168.86.30:8084172.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 では機能していなかったのはそのためだと思います。

関連情報