Soru UDP trafiği Docker konteynerlerinden iletilmedi -> Docker host


Bir docker kabım var ve docker ana bilgisayarından düzgün çalışıyor olsa da, DNS kapsayıcılarını iç kapsayıcılardan çalıştıramıyorum.

Docker ana bilgisayarını oluşturan konfigürasyon yönetimi kodunun piyasadan standart bir RHEL 7 görüntüsü üzerinde çalıştığı biliniyor, dolayısıyla sorunun SOE RHEL 7 görüntüsünde bir şey olduğu biliniyor.

RHEL 7.2 / Docker sürüm 1.12.6, inşa 88a4867 / 1.12.6. Konteyner RHEL 7.3. SELinux etkin / izin modunda. Docker ana bilgisayarı bir Amazon EC2 örneğidir.

Bazı yapılandırmalar:

# /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

Kapsayıcıda ve ana makinede çözümleme yapılandırması aynıdır:

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

Docker daemon'unu yeniden başlatırsam --debug Aşağıdakileri görüyorum 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"

Bu gözlemi takiben, proxy'nin DNS adı yerine bir IP adresi belirlersem ağ bağlantısının çalışmasını sağlayabilirim; Her ne kadar bu gerçek bir düzeltme değil, DNS kullanmanın sadece bir yolu.

Aslında, (3. güncellemesi), TCP'yi UDP yerine TCP kullanmak için basitçe yapılandırarak sorunun tamamen ortadan kaldırılabileceğine işaret ediyor.

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

(Çizgi ekleme use-vc çözümleyiciye UDP yerine TCP kullanmasını söyler.

Iptables'de bazı şüpheli görünen kurallara dikkat ettim, ama bunlar normal çıktı:

# 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           

Bu iki DROP kuralını sildikten sonra, sorunu görmeye devam ettim.

Tam 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           

Köprü yapılandırması

# 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

ve

# 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": {}
    }
]

Günlüklerlerde:

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.

Kapsayıcıdan, varsayılan ağ geçidine ping yapabilirim ancak tüm ad çözümlemesi başarısız oluyor.

Günlükte garip bir şey fark ettim (2. Güncelleme Şimdi bunun kırmızı bir ringa balığı olduğunu biliyorum - aşağıdaki tartışmaya bakınız:

# 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"

1. Güncelleme: ve bu geliyor:

# 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

Ayrıca:

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

Ancak, bunu yaptıktan sonra bile:

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

Hala hayır şans.

Bütün günümü bunun için harcadım, şimdi saçlarımı çekiyorum. Başka ne deneyebileceğime ya da başka ne sorun olduğuna dair herhangi bir düşünce çok takdir edilebilir.

4. Güncelleme

Netcat kullanarak bazı deneyler yaptım ve tüm UDP paketlerinin herhangi bir kapsayıcıdan (host) gönderildiğinde iletilmediğini kanıtladım. 53, 2115 ve 50000 dahil olmak üzere birkaç bağlantı noktası kullanmayı denedim. Ancak, TCP paketleri iyi. Bu iptables kurallarını iptables -F.

Dahası, UDP paketlerini bir konteynırdan diğerine gönderebilirim - sadece konteynerden UDP trafiği -> host iletilmez.

Testi kurmak için:

IP 10.1.1.10'a sahip olan ana bilgisayarda:

# nc -u -l 50000

Kapta:

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

TCP dökümü yakalama sırasında şunu görüyorum:

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.....@.@.S.....
        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.....@.@.S.....
        0x0010:  0aa5 7424 a2ff c350 000c 2afa 666f 6f0a  ..t$...P..*.foo.
        0x0020:  0000 0000 0000 0000 0000 0000 0000 0000  ................

Kötü UDP checksum'larını düzeltmek için başarısız bir şekilde denedim bu.

Ancak UDP paketlerinin (host -> host) ve konteyner -> konteynerinin başarılı bir şekilde iletilmesi sırasında bile kötü UDP checksum'larının görüldüğünü kaydettim.

Özet olarak, şimdi biliyorum:

  • yönlendirme iyidir

  • iptables kızardı

  • SELinux izin vericidir

  • tüm TCP her yönde çalışır

  • konteynerden tüm UDP -> konteyner iyi

  • ana bilgisayardan tüm UDP -> ana bilgisayar iyidir

  • ana bilgisayardan tüm UDP -> kapsayıcı gayet iyi

  • FAKAT konteynerden UDP paketi yok -> ana makine yönlendiriliyor


6
2017-08-04 07:47


Menşei


Konteynerlerin 53 numaralı limanda konuşabilir mi? telnet 8.8.8.8 53 - Orphans
8.8.8.8 (TCP) bağlantı noktası 53'e ulaşamıyorum çünkü 8.8.8.8 bir şirket güvenlik duvarı tarafından engelleniyor. Ancak, TCP bağlantı noktası 53'teki yerel DNS sunucusuna bağlanabiliyorum - güncellememi görün. Sabah, netcat'in, gerçekten de bu konteynerlerin çıkış yapan UDP trafiğini iletmediğini ispatlamaya çalıştığını kanıtlamak için bir yol bulmayı düşünüyorum. - Alex Harvey
@Orphans, netcat denemelerimin sonuçlarıyla güncellendi. Temel olarak, kapsayıcı -> ana bilgisayardaki tüm UDP'ler kaybolur, ancak TCP iyidir ve UDP de kapsayıcıdan - kapsayıcıdan ve ana bilgisayardan - konteynerden iyidir. Ve iptables -F'den sonra hepsi doğru. - Alex Harvey
Bu yardımcı olur mu? stackoverflow.com/questions/27596409/... - Orphans
Teşekkürler, ama hayır, bu port yönlendirme ile ilgili - bir kapsayıcıyı bir kapsayıcıya iletme, böylece bir istemci Docker ana bilgisayarındaki bir adrese bağlanabilir. Benim durumumda, konteyner giden UDP paketlerini göndermeye çalışıyor. - Alex Harvey


Cevaplar:


Görünüşe göre bir modprobe sahipsin install çalışamayan yönerge. Muhtemelen RHEL 7.2 veya bazı manuel düzeltmelerde eksik güncelleme sonucudur.

Deneyin grep -r bridge /etc/modprobe.d /lib/modprobe.d yeni başlayanlar için ya da başka şekilde kazmak /etc/modprobe.d veya /lib/modprobe.d ve nerede tanımladığını bulmaya çalışın install çağrıları yönet sysctl -q -w net.bridge.bridge-nf-call-arptables=0 net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-ip6tables=0

Bu sysctl açıkça yanlış yerde. Gereksiz ya da sonra görünmelidir br_netfilter, önce değil. Niye ya? Son zamanlarda /proc/sys/net/bridge işlemden taşındı bridge modülüne br_netfilter modülü. Bu, bazı sürümü ile olur kernel*.rpmiçeriği ise modprobe.d dizinler diğer bireysel paketler ile dağıtılır. RHEL 7.2'mi doğruladım:

# 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

Bu "kırık" kuralları vanilya RHEL 7.1'de görmüyorum ve kökenleri benim için gizemli. Denedim:

# 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

Güncelleştirme: Benziyor xenserver benzer bir modprobe kesmek kullanır. Gerçekten de xenserver çalıştırıp çalıştırmadığınızı herkes için çekirdek modül davranışını global olarak değiştirmek için kötü bir böcek; ve böcek bize geri ateş etti.

Güncelleme 2: Şimdi bunu buldun /etc/modprobe.d/dist.conf Bu soruna neden olur ve docker değil. Docker var mı, yok mu modprobe bridge her zaman 1 döndürür ve yazdırma hatası. Normalde dist.conf bir parçasıdır module-init-tools RHEL6 paketi. Bu dosya RHEL7'de kullanılmamalıdır. Hiçbir RHEL7 sistemimde yok ve iyi çalışıyorlar. RHEL7'de paket kmod ve dist.conf içermiyor. İsterim:

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

Eğer dist.conf pakete ait değilse, onu yedekleyin ve size herhangi bir belirgin fayda sağlamayan herhangi bir satırı silin (hatta dosyayı tamamen silebilirsiniz).

Eğer dist.conf bir pakete aitse, bu paketi kaldırmayı / güncellemeyi düşünün, çünkü RHEL 7.2 uyumluluğu açısından açıkça buggy olur.


3
2017-08-04 08:44



Dosya gerçekten bir pakete ait değil. Ancak, dosyayı tamamen kaldırdım ve docker ana bilgisayarını yeniden oluşturdum ve korkarım bunun DNS bağlantısı sorununa neden olmadığını kanıtladım. :( - Alex Harvey
Bummer :( Sigh ... - kubanczyk


Bunu anladım.

Bilmediğim SOE'de çalışan bir Trend Micro (anti-virüs) ajanı vardı.

Düzeltmek şu kadar basit:

# systemctl stop ds_agent.service
# pkill ds_agent

Bu noktada, UDP'nin kapsayıcılardan neden engellendiğinden veya nasıl durduracağından tam olarak emin değilim.


1
2017-08-13 09:53



Şirket politikanızın ds_agent'in çalışmasını gerektirmediğini kontrol edin. Trend Micro’da bir hatayı dosyalamak isteyebilirsiniz, böylece kaynakta düzeltebilirler. - Ed Neville
İyi fikir ama Trend Micro'yu yöneten takımım değildi ve o işi şimdi bıraktım! - Alex Harvey