Me gustaría reasignar el tráfico saliente desde un contenedor acoplable a un puerto diferente. Por ejemplo: me gustaría hacerlo curl 1.2.3.4:8080
desde dentro del contenedor y que la solicitud se realice realmente a curl 1.2.3.4:8181
. (esto es similar a lo que hace kube-proxy para kubernetes).
Entiendo que dentro de un contenedor acoplable puedo ejecutar:
iptables -t nat -A OUTPUT -p tcp -d 1.2.3.4 --dport 8080 -j DNAT --to-destination 1.2.3.4:8181
Y luego las solicitudes se comportarán como se desee. Sin embargo, me gustaría editar únicamente las reglas de iptables en el host para obtener la misma funcionalidad.
Tengo una red acoplable con id 8e8799c36e69
, si la ejecuto iptables-save | grep 8e8799c36e69
en el host obtengo las siguientes reglas:
-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
¿Es posible conectarme a estas reglas para poder configurar la reescritura de mi puerto solo dentro de esa red? (¿Es este evento el enfoque correcto?).
¿Quizás algo como esto?
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
¿O tal vez no necesito la red Docker Bridge y de alguna manera puedo filtrar el tráfico proveniente del contenedor?
editar:
Cuando inicio un contenedor acoplable, crea estas reglas:
-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
El contenedor tiene dirección IP 172.17.0.2
en mi máquina. Entonces agregué esta regla:
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
Intento obtener una solicitud de prueba para 172.217.3.110:8080
solicitar 172.217.3.110:80
, pero no parece funcionar.
edición 2:
Si estoy intentando reescribir un puerto para un servicio que escucha localmente, lo hago funcionar con esto:
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
eso parece funcionar solo con ips locales
edición 3: La fuente de kube-proxy tiene más información sobre su enfoque y varios problemas:
https://github.com/kubernetes/kubernetes/blob/84dc704/pkg/proxy/userspace/proxier.go#L1133-L1165
Respuesta1
Ok, lo descubrí.
Si quisiera redirigir el tráfico de 192.168.86.30:80
a 192.168.86.30:8084
a un contenedor con una dirección IP, 172.17.0.2
entonces puedo agregar la siguiente regla:
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
Esto también parece funcionar con direcciones IP públicas externas.
REDIRECT
no parece funcionar porque[fuente]:
Redirige el paquete a la máquina cambiando la IP de destino a la dirección principal de la interfaz entrante (los paquetes generados localmente se asignan a la dirección 127.0.0.1).
Todavía no estoy del todo seguro de lo que estaba pasando, pero creo que es por eso que REDIRECT estaba trabajando con algunas cosas servidas localmente (especialmente cualquier cosa que escuchara en 0.0.0.0), pero no con IP externas.