web-dev-qa-db-ja.com

Dockerコンテナーから転送されないUDPトラフィック-> Dockerホスト

Dockerコンテナーがありますが、dockerホストからは正常に機能しますが、コンテナー内からDNSルックアップを実行できません。

Dockerホストを構築する構成管理コードは、市場の標準RHEL 7イメージで動作することがわかっているため、問題はSOE RHEL 7イメージ内にあることがわかっています。

RHEL 7.2/Dockerバージョン1.12.6、ビルド88a4867/1.12.6。コンテナーはRHEL 7.3です。有効/許容モードのSELinux。 Docker HostはAmazon EC2インスタンスです。

いくつかの設定:

# /etc/sysconfig/docker
OPTIONS='--dns=10.0.0.10 --dns=10.0.0.11 --dns-search=example.com'
DOCKER_CERT_PATH=/etc/docker
ADD_REGISTRY='--add-registry registry.example.com'
no_proxy=169.254.169.254,localhost,127.0.0.1,registory.example.com
http_proxy=http://proxy.example.com:8080
https_proxy=http://proxy.example.com:8080
ftp_proxy=http://proxy.example.com:8080

コンテナーとホストのリゾルバー構成は同じです:

# /etc/resolv.conf
search example.com
nameserver 10.0.0.10
nameserver 10.0.0.11

--debugでdockerデーモンを再起動すると、journalctl -u docker.serviceに次のように表示されます。

Aug 08 11:44:23 myhost.example.com dockerd-current[17341]: time="2017-08-08T11:44:23.430769581+10:00" level=debug msg="Name To resolve: http://proxy.example.com."
Aug 08 11:44:23 myhost.example.com dockerd-current[17341]: time="2017-08-08T11:44:23.431488213+10:00" level=debug msg="Query http://proxy.example.com.[1] from 172.18.0.6:38189, forwarding to udp:10.162.182.101"
Aug 08 11:44:27 myhost.example.com dockerd-current[17341]: time="2017-08-08T11:44:27.431772666+10:00" level=debug msg="Read from DNS server failed, read udp 172.18.0.6:38189->10.162.182.101:53: i/o timeout"

さらにその観察の結果、プロキシのDNS名の代わりにIPアドレスを指定すると、ネットワークが機能することがわかりました。ただし、これはDNSの使用を回避するための単なる方法であり、実際の修正ではありません。

実際、(update#3)DNSを使用するように構成するだけで問題を完全に回避できることがわかりますTCP UDPの代わりに、すなわち.

# head -1 /etc/sysconfig/docker
OPTIONS="--dns=10.0.0.10 --dns=10.0.0.11 --dns-search=example.com --dns-opt=use-vc"

(行use-vcを追加すると、リゾルバーはTCPをUDPの代わりに使用するように指示されます。)

Iptablesに疑わしい外観のルールがいくつかありましたが、これらは正常であることがわかりました。

# iptables -n -L DOCKER-ISOLATION -v --line-numbers
Chain DOCKER-ISOLATION (1 references)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 DROP       all  --  br-1d6a05c10468 docker0  0.0.0.0/0            0.0.0.0/0           
2        0     0 DROP       all  --  docker0 br-1d6a05c10468  0.0.0.0/0            0.0.0.0/0           
3    34903   11M RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0           

これら2つのDROPルールを削除した後も、問題が発生し続けました。

完全なiptables:

# iptables -nL -v
Chain INPUT (policy ACCEPT 2518 packets, 1158K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
23348 9674K DOCKER-ISOLATION  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  docker0 docker0  0.0.0.0/0            0.0.0.0/0           
23244 9667K DOCKER     all  --  *      br-1d6a05c10468  0.0.0.0/0            0.0.0.0/0           
23232 9667K ACCEPT     all  --  *      br-1d6a05c10468  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
  104  6230 ACCEPT     all  --  br-1d6a05c10468 !br-1d6a05c10468  0.0.0.0/0            0.0.0.0/0           
   12   700 ACCEPT     all  --  br-1d6a05c10468 br-1d6a05c10468  0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 2531 packets, 414K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  !br-1d6a05c10468 br-1d6a05c10468  0.0.0.0/0            172.18.0.2           tcp dpt:443
    0     0 ACCEPT     tcp  --  !br-1d6a05c10468 br-1d6a05c10468  0.0.0.0/0            172.18.0.2           tcp dpt:80
    0     0 ACCEPT     tcp  --  !br-1d6a05c10468 br-1d6a05c10468  0.0.0.0/0            172.18.0.3           tcp dpt:389

Chain DOCKER-ISOLATION (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  br-1d6a05c10468 docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 DROP       all  --  docker0 br-1d6a05c10468  0.0.0.0/0            0.0.0.0/0           
23348 9674K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0           

ブリッジ構成

# ip addr show docker0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
    link/ether 02:42:a8:73:db:bb brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
# ip addr show br-1d6a05c10468
3: br-1d6a05c10468: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:d5:b6:2d:f5 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 scope global br-1d6a05c10468
       valid_lft forever preferred_lft forever

そして

# docker network inspect bridge 
[
    {
        "Name": "bridge",
        "Id": "e159ddd37386cac91e0d011ade99a51f9fe887b8d32d212884beace67483af44",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.Host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

ログで:

Aug 04 17:33:32 myhost.example.com systemd[1]: Starting Docker Application Container Engine...
Aug 04 17:33:33 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:33.056770003+10:00" level=info msg="libcontainerd: new containerd process, pid: 2140"
Aug 04 17:33:34 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:34.740346421+10:00" level=info msg="Graph migration to content-addressability took 0.00 seconds"
Aug 04 17:33:34 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:34.741164354+10:00" level=info msg="Loading containers: start."
Aug 04 17:33:34 myhost.example.com dockerd-current[2131]: .........................time="2017-08-04T17:33:34.903371015+10:00" level=info msg="Firewalld running: true"
Aug 04 17:33:35 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:35.325581993+10:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address" 
Aug 04 17:33:36 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:36+10:00" level=info msg="Firewalld running: true"
Aug 04 17:33:37 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:37+10:00" level=info msg="Firewalld running: true"
Aug 04 17:33:37 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:37+10:00" level=info msg="Firewalld running: true"
Aug 04 17:33:38 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:38+10:00" level=info msg="Firewalld running: true"
Aug 04 17:33:39 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:39+10:00" level=info msg="Firewalld running: true"
Aug 04 17:33:40 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:40+10:00" level=info msg="Firewalld running: true"
Aug 04 17:33:40 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:40+10:00" level=info msg="Firewalld running: true"
Aug 04 17:33:42 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:42+10:00" level=info msg="Firewalld running: true"
Aug 04 17:33:42 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:42+10:00" level=info msg="Firewalld running: true"
Aug 04 17:33:43 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:43.541905145+10:00" level=info msg="Loading containers: done."
Aug 04 17:33:43 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:43.541975618+10:00" level=info msg="Daemon has completed initialization"
Aug 04 17:33:43 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:43.541998095+10:00" level=info msg="Docker daemon" commit="88a4867/1.12.6" graphdriver=devicemapper version=1.12.6
Aug 04 17:33:43 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:43.548508756+10:00" level=info msg="API listen on /var/run/docker.sock"
Aug 04 17:33:43 myhost.example.com systemd[1]: Started Docker Application Container Engine.

コンテナーから、デフォルトゲートウェイにpingを実行できますが、すべての名前解決が失敗します。

ログに奇妙なことが1つあることに気づきました(Update#2これが赤いニシンであることがわかりました-以下の説明を参照してください):

# journalctl -u docker.service |grep insmod > /tmp/log # \n's replaced below
Jul 26 23:59:02 myhost.example.com dockerd-current[3185]: time="2017-07-26T23:59:02.056295890+10:00" level=warning msg="Running modprobe bridge br_netfilter failed with message: insmod /lib/modules/3.10.0-514.26.2.el7.x86_64/kernel/net/bridge/bridge.ko 
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-arptables: No such file or directory
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: No such file or directory
modprobe: ERROR: Error running install command for bridge
modprobe: ERROR: could not insert 'bridge': Unknown error 253
insmod /lib/modules/3.10.0-514.26.2.el7.x86_64/kernel/net/llc/llc.ko 
insmod /lib/modules/3.10.0-514.26.2.el7.x86_64/kernel/net/802/stp.ko 
install /sbin/modprobe --ignore-install bridge && /sbin/sysctl -q -w net.bridge.bridge-nf-call-arptables=0 net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-ip6tables=0 
insmod /lib/modules/3.10.0-514.26.2.el7.x86_64/kernel/net/bridge/br_netfilter.ko 
, error: exit status 1"

Update#1:これは次の場所から取得されます:

# tail -2 /etc/modprobe.d/dist.conf
# Disable netfilter on bridges when the bridge module is loaded
install bridge /sbin/modprobe --ignore-install bridge && /sbin/sysctl -q -w net.bridge.bridge-nf-call-arptables=0 net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-ip6tables=0

また:

# cat /proc/sys/net/bridge/bridge-nf-call-{arp,ip,ip6}tables
1
1
1

ただし、これを行った後でも:

# for i in /proc/sys/net/bridge/bridge-nf-call-{arp,ip,ip6}tables ; do echo 0 > $i ; done 

まだ運がない。

私はこれに丸一日を費やしたので、今では髪を抜いています。私が他に何を試すことができるか、または他にどのような問題があるかについての考えは大いに感謝されます。

更新#4

Netcatを使用していくつかの実験を行ったところ、コンテナから送信された場合、すべてのUDPパケットが転送されないことが判明しました->ホスト。 53、2115、および50000を含むいくつかのポートを使用してみました。TCPパケットは問題ありません。iptables -Fを使用してiptablesルールをフラッシュする場合も同様です。

さらに、あるコンテナから別のコンテナにUDPパケットを送信できます-コンテナからのUDPトラフィックのみ->ホストは転送されません。

テストを設定するには:

IP 10.1.1.10のホスト:

# nc -u -l 50000

コンテナ:

# echo "foo" | nc -w1 -u 10.1.1.10 50000

TCPダンプキャプチャ中に私が見る:

17:20:36.761214 IP (tos 0x0, ttl 64, id 48146, offset 0, flags [DF], proto UDP (17), length 32)
    172.17.0.2.41727 > 10.1.1.10.50000: [bad udp cksum 0x2afa -> 0x992f!] UDP, length 4
        0x0000:  4500 0020 bc12 4000 4011 53de ac11 0002  E.....@[email protected].....
        0x0010:  0aa5 7424 a2ff c350 000c 2afa 666f 6f0a  ..t$...P..*.foo.
        0x0020:  0000 0000 0000 0000 0000 0000 0000 0000  ................
17:20:36.761214 IP (tos 0x0, ttl 64, id 48146, offset 0, flags [DF], proto UDP (17), length 32)
    172.17.0.2.41727 > 10.1.1.10.50000: [bad udp cksum 0x2afa -> 0x992f!] UDP, length 4
        0x0000:  4500 0020 bc12 4000 4011 53de ac11 0002  E.....@[email protected].....
        0x0010:  0aa5 7424 a2ff c350 000c 2afa 666f 6f0a  ..t$...P..*.foo.
        0x0020:  0000 0000 0000 0000 0000 0000 0000 0000  ................

this を使用して、不正なUDPチェックサムの修正に失敗しました。

ただし、UDPパケット(ホスト->ホスト)およびコンテナー->コンテナーの送信が成功している間でも、不正なUDPチェックサムが表示されることに注意しました。

要約すると、私は今知っています:

  • ルーティングは問題ありません

  • iptablesがフラッシュされる

  • SELinuxは許容範囲です

  • すべてTCPはすべての方向で機能します

  • コンテナからのすべてのUDP->コンテナは問題ありません

  • ホストからのすべてのUDP->ホストは問題ありません

  • ホストからのすべてのUDP->コンテナは問題ありません

  • [〜#〜] but [〜#〜]コンテナからのUDPパケットはありません->ホストは転送されます

8
Alex Harvey

私はそれを考え出した。

私たちは知らなかったSOEでTrend Micro(アンチウイルス)エージェントを実行していました。

修正は次のように簡単でした:

# systemctl stop ds_agent.service
# pkill ds_agent

現時点では、UDPがコンテナーからブロックされている理由や、UDPを停止する方法は正確にはわかりません。

3
Alex Harvey

動作しないmodprobe installディレクティブがあるようです。おそらく、RHEL 7.2への不完全なアップデートまたはいくつかの手動修正の結果です。

はじめにgrep -r bridge /etc/modprobe.d /lib/modprobe.dを試すか、そうでなければ/etc/modprobe.dまたは/lib/modprobe.dを調べて、sysctl -q -w net.bridge.bridge-nf-call-arptables=0 net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-ip6tables=0を呼び出すinstallルールがどこで定義されているかを見つけてください

このsysctlは明らかに間違った場所にあります。不要であるか、前ではなくbr_netfilterの後に表示する必要があります。どうして?最近、/proc/sys/net/bridgeの処理がbridgeモジュールからbr_netfilterモジュールに移動しました。これはkernel*.rpmの一部のバージョンで発生しますが、modprobe.dディレクトリの内容は他の個々のパッケージとともに配布されます。 RHEL 7.2で確認しました。

# modprobe bridge
# sysctl -q -w net.bridge.bridge-nf-call-iptables=0
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory
# modprobe br_netfilter
# sysctl -q -w net.bridge.bridge-nf-call-iptables=0    # ok now

バニラRHEL 7.1でこれらの「壊れた」ルールが表示されない 彼らの起源は私には不思議です。私はもう試した:

# modprobe -n -vvv bridge
modprobe: INFO: custom logging function 0x40a130 registered
insmod /lib/modules/3.10.0-229.11.1.el7.x86_64/kernel/net/llc/llc.ko
insmod /lib/modules/3.10.0-229.11.1.el7.x86_64/kernel/net/802/stp.ko
insmod /lib/modules/3.10.0-229.11.1.el7.x86_64/kernel/net/bridge/bridge.ko
modprobe: INFO: context 0xf1c270 released
# echo "install bridge echo example_of_a_modprobe_rule" > /etc/modprobe.d/zzz5.conf
# modprobe -n -vvv bridge
modprobe: INFO: custom logging function 0x40a130 registered
insmod /lib/modules/3.10.0-229.11.1.el7.x86_64/kernel/net/llc/llc.ko
insmod /lib/modules/3.10.0-229.11.1.el7.x86_64/kernel/net/802/stp.ko
install echo example_of_a_modprobe_rule
modprobe: INFO: context 0xeaa270 released
# rm /etc/modprobe.d/zzz5.conf

更新:xenserverは同様のmodprobe hack を使用するように見えます実際にxenserverを実行しているかどうかに関係なく、すべての人のカーネルモジュールの動作をグローバルに変更するのは厄介なバグです。そしてバグは私たちに反撃しました。

Update 2:これで、/etc/modprobe.d/dist.confがDockerではなくこの問題の原因であることがわかりました。 Dockerの有無にかかわらず、modprobe bridgeは常に1を返し、エラーを出力します。通常、dist.confはRHEL6のmodule-init-toolsパッケージの一部です。このファイルはRHEL7での使用を想定していません。それは私のRHEL7システムのどれにもありません、そしてそれらはうまく動きます。 RHEL7では、パッケージはkmodであり、dist.confは含まれていません。私は...するだろう:

rpm -qf /etc/modprobe.d/dist.conf  # what package owns this file?

Dist.confがパッケージによって所有されていない場合は、それをバックアップし、明らかな利益をもたらさない行を削除します(ファイルを完全に削除することさえ可能です)。

Dist.confがパッケージによって所有されている場合は、RHEL 7.2の互換性の点で明らかにバグがあるため、そのパッケージを削除/更新することを検討してください。

3
kubanczyk