¿Cómo actualizo las reglas de iptables del host de Linux para redirigir el tráfico dentro de un contenedor acoplable?

¿Cómo actualizo las reglas de iptables del host de Linux para redirigir el tráfico dentro de un contenedor acoplable?

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:8080desde 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 8e8799c36e69en 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.2en 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:8080solicitar 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

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

Respuesta1

Ok, lo descubrí.

Si quisiera redirigir el tráfico de 192.168.86.30:80a 192.168.86.30:8084a un contenedor con una dirección IP, 172.17.0.2entonces 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.

REDIRECTno 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.

información relacionada