Docker 컨테이너 내에서 트래픽을 리디렉션하도록 Linux 호스트 iptables 규칙을 어떻게 업데이트합니까?

Docker 컨테이너 내에서 트래픽을 리디렉션하도록 Linux 호스트 iptables 규칙을 어떻게 업데이트합니까?

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 네트워크가 있습니다 . 호스트에서 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 컨테이너를 시작하면 다음 규칙이 생성됩니다.

-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:8080요청하려고 시도했지만 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

알았어, 알아냈어.

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로는 작동하지 않는 이유라고 생각합니다.

관련 정보