소스 IP를 올바르게 유지하면서 iptables 전달 사용

소스 IP를 올바르게 유지하면서 iptables 전달 사용

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:2525Docker 컨테이너에서 내 실제 IP 주소( )를 볼 수 있습니다 1.2.3.4. port 에 연결할 때 server:25Docker 컨테이너는 다음에서 제공하는 로컬 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-proxyDocker는 이미 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실행하여 전역적으로 비활성화합니다 .dockerduserland-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 화이트리스트 도커

관련 정보