Как обновить правила iptables хоста Linux для перенаправления трафика внутри контейнера Docker?

Как обновить правила iptables хоста Linux для перенаправления трафика внутри контейнера 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 на хосте, чтобы получить ту же функциональность.

У меня есть сеть 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 Bridge и я могу каким-то образом фильтровать трафик, поступающий изнутри контейнера?

редактировать:

Когда я запускаю 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

У контейнера есть ip addr 172.17.0.2на моей машине. Поэтому я добавил это правило:

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-адресами.

Связанный контент