![소스 IP를 올바르게 유지하면서 iptables 전달 사용](https://rvso.com/image/776289/%EC%86%8C%EC%8A%A4%20IP%EB%A5%BC%20%EC%98%AC%EB%B0%94%EB%A5%B4%EA%B2%8C%20%EC%9C%A0%EC%A7%80%ED%95%98%EB%A9%B4%EC%84%9C%20iptables%20%EC%A0%84%EB%8B%AC%20%EC%82%AC%EC%9A%A9.png)
Wireguard를 실행하는 서버(따라서 가 필요함 masquerade
)와 포트 2525에서 실행되는 컨테이너가 있습니다.
다음과 같은 규칙이 있습니다 iptables
.
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to-destination 172.18.0.1:2525
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
직접 연결하면 server:2525
Docker 컨테이너에서 내 실제 IP 주소( )를 볼 수 있습니다 1.2.3.4
. port 에 연결할 때 server:25
Docker 컨테이너는 다음에서 제공하는 로컬 IP를 확인합니다 docker network
.
Apr 07 12:45:46 mx postfix/smtpd[87]: lost connection after CONNECT from unknown[172.18.0.1]
Apr 07 12:45:46 mx postfix/smtpd[87]: disconnect from unknown[172.18.0.1] commands=0/0
포트 25에 연결하는 동안(포트 2525에 연결할 때뿐만 아니라) Docker 컨테이너가 공용 IP 주소를 올바르게 표시하는지 어떻게 확인합니까?
감사해요
# iptables -L -n -v -t nat
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
52300 3131K DNAT tcp -- eth0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:25 to:172.18.0.1:2525
150K 8524K DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
2 120 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
3385 256K MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
1733K 104M MASQUERADE all -- * !br-b147ffdbc9f3 172.18.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:53
0 0 MASQUERADE udp -- * * 172.17.0.2 172.17.0.2 udp dpt:53
0 0 MASQUERADE tcp -- * * 172.18.0.2 172.18.0.2 tcp dpt:25
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
12 1419 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- br-b147ffdbc9f3 * 0.0.0.0/0 0.0.0.0/0
56 3192 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:5354 to:172.17.0.2:53
0 0 DNAT udp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:5354 to:172.17.0.2:53
107 6020 DNAT tcp -- !br-b147ffdbc9f3 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:2525 to:172.18.0.2:25
# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 32:d0:56:15:0a:64 brd ff:ff:ff:ff:ff:ff
altname enp0s3
altname ens3
inet 159.223.80.86/20 brd 159.223.95.255 scope global eth0
valid_lft forever preferred_lft forever
inet 10.15.0.19/16 brd 10.15.255.255 scope global eth0:1
valid_lft forever preferred_lft forever
inet6 2400:6180:0:d0::f57:6001/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::30d0:56ff:fe15:a64/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 32:dc:4a:e4:27:be brd ff:ff:ff:ff:ff:ff
altname enp0s4
altname ens4
inet 10.130.244.15/16 brd 10.130.255.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::30dc:4aff:fee4:27be/64 scope link
valid_lft forever preferred_lft forever
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 10.200.200.52/24 scope global wg0
valid_lft forever preferred_lft forever
5: wg1: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 10.222.111.1/24 scope global wg1
valid_lft forever preferred_lft forever
6: br-b147ffdbc9f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:46:21:70:c0 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-b147ffdbc9f3
valid_lft forever preferred_lft forever
inet6 fe80::42:46ff:fe21:70c0/64 scope link
valid_lft forever preferred_lft forever
7: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:66:22:41:91 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:66ff:fe22:4191/64 scope link
valid_lft forever preferred_lft forever
9: veth31eff9d@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether e6:fb:80:5d:c7:a3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::e4fb:80ff:fe5d:c7a3/64 scope link
valid_lft forever preferred_lft forever
19: veth01269f5@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-b147ffdbc9f3 state UP group default
link/ether 36:f4:e7:43:5f:da brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::34f4:e7ff:fe43:5fda/64 scope link
valid_lft forever preferred_lft forever
답변1
Docker가 리디렉션을 처리하도록 하세요. 리디렉션은 동적이며 컨테이너가 추가, 제거 또는 다시 시작될 때 변경될 수 있습니다. 하지만 보세요업데이트아래에.
이 리디렉션은 컨테이너가 아닌 호스트인 172.18.0.1로 이루어져서는 안 됩니다. 호스트가 그러한 연결을 받으면 이를 처리합니다.docker-proxy
이를 컨테이너로 프록시하여 프로세스에서 소스 IP 주소를 잃습니다.
docker-proxy
Docker는 이미 DNAT +가 규칙 세트의 마지막 규칙에서 이 포트를 172.18.0.2 주소를 사용하여 실행 중인 컨테이너로 올바르게 라우팅합니다(이 역할을 수행하는 호스트 자체 제외 ). 단, 포트 25가 아닌 포트 2525를 사용하도록 구성되어 있습니다.
107 6020 DNAT tcp -- !br-b147ffdbc9f3 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:2525 to:172.18.0.2:25
이 문제는 수동이 아닌 Docker 설정으로 수정되어야 합니다.iptables컨테이너 레이아웃이 변경될 때마다 변경할 수 없는 규칙입니다. 포트 25는 권한이 있으므로 Docker가 루트 없이 실행 중인 경우 추가 설정이 필요합니다.권한 있는 포트 노출에 대한 문서.
업데이트(OP의 설명 고려): OP는 로컬 호스트의 SMTP 서버와 충돌하고 호스트의 포트 25에서 청취하기 위해 경쟁하기 -p 25:25
때문에 현재 사용할 수 없습니다. docker-proxy
그 이유는 초기 (잘못)iptablesOP에 의해 리디렉션이 이루어졌습니다.
다음 중 하나를 수행할 수 있습니다.
속성을 false로 설정하여
docker-proxy
실행하여 전역적으로 비활성화합니다 .dockerd
userland-proxy
또는매개변수
--userland-proxy=false
또는 속성으로"userland-proxy": false
추가됨/etc/docker/daemon.json
.그러면 다음
docker run ... -p 25:25 ...
과 같이 사용할 수 있습니다.문서화) 충돌 없이: 호스트는 localhost 또는 $HOSTNAME에 도달할 때 자체적으로 도달하고, 원격 시스템은 컨테이너에 도달하며 "이미 사용 중인 주소"가 없으면 호스트의 SMTP 데몬 또는 Docker의 컨테이너가 시작 시 실패하게 됩니다.또는 수동 리디렉션을 추가하세요(거의 자동으로 수행하려면 아래의 긴 설정을 사용하세요).
컨테이너가 다시 시작될 때마다 (내부) IP 주소가 변경될 위험이 있습니다. 그래서 이것을 계산해야 합니다. 따라서
mx
명명된 네트워크mx
와 관련된 단일 IP 주소를 사용하여 명명된 컨테이너의 경우 아래 설명된 대로 수행될 수 있습니다.별도의 사전 라우팅 체인을 생성하고(다른 항목을 플러시할 필요 없이 플러시할 수 있도록) 먼저 호출합니다.
iptables -t nat -N mynat iptables -t nat -I PREROUTING -j mynat
mx
컨테이너의 IP 주소는 프로그래밍 방식으로 검색할 수 있습니다( 단일 주소로 이름이 지정된 컨테이너의 간단한 경우 ).containerip=$(docker container inspect --format '{{.NetworkSettings.IPAddress}}' mx)
(또는 다음을 사용할 수 있습니다.
jq
:)containerip=$(docker container inspect mx | jq '.[].NetworkSettings.IPAddress'
브리지 인터페이스 이름을 찾는 것이 더 복잡하거나 적어도
docker ... inspect
. 따라서 호스트에서 해당 IP 주소를 찾고ip address
이 특정 IP 주소가 설정된 브리지 인터페이스만 찾기 위해 호스트를 쿼리합니다(명령 필요jq
).bridgeip=$(docker network inspect --format '{{(index .IPAM.Config 0).Gateway}}' mx) bridgeinterface=$(ip -json address show to "$bridgeip"/32 | jq -r '.[].ifname')
mynat
컨테이너가 (다시)시작될 때마다 플러시하고 다시 채웁니다 .iptables -t nat -F mynat iptables -t nat -A mynat ! -i "$bridgeinterface" -p tcp --dport 25 -j DNAT --to-destination "$containerip":25
현재의 경우는 다음과 같습니다.
iptables -t nat -I mynat ! -i br-b147ffdbc9f3 -p tcp --dport 25 -j DNAT --대상 172.18.0.2:25
그리고 Docker의 자체 방화벽 규칙이 이러한 트래픽을 차단하지 않도록 하려면 filter/에서 시작하여 비슷한 작업을 수행하세요
FORWARD
.DOCKER-USER
체인.처음에는(부팅에서 먼저 생성해야 할 수도 있습니다)
DOCKER-USER
):iptables -N myforward iptables -I DOCKER-USER 1 -j myforward
그런 다음 나중에 컨테이너가 (다시) 시작될 때마다 다음을 수행합니다.
iptables -F myforward iptables -A myforward -p tcp ! -i "$bridgeinterface" -d "$containerip" -p tcp --dport 25 -j ACCEPT
현재의 경우는 다음과 같습니다.
iptables -A myforward -p tcp ! -i br-b147ffdbc9f3 -d 172.18.0.2 -p tcp --dport 25 -j ACCEPT
노트:
위의 규칙을 단순화하고 일부 계산을 피하기 위해 컨테이너와 해당 브리지 네트워크를 고정 IP 주소로 시작할 수 있습니다. 예를 들어 다음 SO Q/A를 참조하세요.Docker 컨테이너에 고정 IP 할당.
Docker와 상호 작용할 때 발생하는 문제에 대한 답변이 포함된 UL SE Q/A도 있습니다.nftables그러나
DOCKER-USER
체인이나br_netfilter
브릿지 상호작용에 관한 일부 부분은 여전히 관심을 끌고 있습니다.nftables 화이트리스트 도커