iptables転送を使用し、送信元IPを適切に維持する

iptables転送を使用し、送信元IPを適切に維持する

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) を見ることができます。ポート に接続する場合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 はすでに、ルールセットの最後のルールで、このポートを 172.18.0.2 アドレスの実行中のコンテナーに正しく DNAT + ルーティングしています (この役割を果たすホスト自体からは除きますdocker-proxy)。ただし、ポート 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がルートレスで実行されている場合は追加の設定が必要です。特権ポートの公開に関するドキュメント


アップデート-p 25:25(OPのコメントを考慮すると):OPは現在、ローカルホストのSMTPサーバーと衝突し、ホストのポート25でリッスンするために競合するため使用できませんdocker-proxy。これが、最初の(間違った)理由です。iptablesリダイレクトは OP によって行われました。

次のいずれかが可能です:

  • プロパティを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
    

    コンテナの IP アドレスはプログラムで取得できます (mx単一のアドレスで名前が付けられたコンテナの単純なケースの場合)。

    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 --to-destination 172.18.0.2:25

    そして、Docker自身のファイアウォールルールがそのようなトラフィックをブロックしないようにするには、filter/から同様のことを行ってくださいFORWARDDOCKER-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を割り当てる

  • こちらもUL SE Q/Aで、Dockerとのやりとりで発生する問題についての私の回答です(nftablesDOCKER-USERしかし、チェーンやブリッジの相互作用に関するいくつかの部分はbr_netfilter依然として興味深いです):nftables ホワイトリスト docker

関連情報