Tráfico UDP no reenviado desde contenedores Docker - > host Docker

Tengo un contenedor docker y no puedo ejecutar búsquedas de DNS desde contenedores internos, aunque funciona bien desde el host docker.

Se sabe que el código de administración de configuración que crea el host de Docker funciona en una imagen RHEL 7 estándar de marketplace, por lo que se sabe que el problema es algo dentro de la imagen SOE RHEL 7.

RHEL 7.2 / Docker versión 1.12.6, compilación 88a4867/1.12.6. El contenedor es RHEL 7.3. SELinux en modo habilitado/permisivo. El host de Docker es una instancia de Amazon EC2.

Alguna configuración:

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

La configuración del solucionador en el contenedor y el host es la misma:

# /etc/resolv.confsearch example.comnameserver 10.0.0.10nameserver 10.0.0.11

Si reinicio el demonio Docker con --debug Veo lo siguiente en 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"

Siguiendo esa observación, resulta que puedo hacer que algunas redes funcionen si especifico una dirección IP en lugar del nombre DNS del proxy; aunque eso realmente es solo una forma de evitar el uso de DNS y no una solución real.

Efectivamente, (actualización #3) resulta que puedo evitar el problema por completo simplemente configurando DNS para usar TCP en lugar de UDP, es decir,

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

(Añadir una línea use-vc indica al resolutor que use TCP en lugar de UDP.)

Noté algunas reglas de aspecto sospechoso en iptables, pero resultaron ser normales:

# iptables -n -L DOCKER-ISOLATION -v --line-numbersChain 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           

Después de eliminar esas dos reglas de ELIMINACIÓN, continué viendo el problema.

Iptables completas:

# iptables -nL -vChain 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:389Chain 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           

Puente config

# ip addr show docker04: 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-1d6a05c104683: 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

y

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

En los registros:

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.6Aug 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.

Desde el contenedor, puedo hacer ping a la puerta de enlace predeterminada, pero falla toda la resolución de nombres.

Noté una cosa extraña en el registro (Actualización #2 Ahora sé que esto es una pista falsa , vea la discusión a continuación):

# journalctl -u docker.service |grep insmod > /tmp/log # \n's replaced belowJul 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 directorysysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directorysysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: No such file or directorymodprobe: ERROR: Error running install command for bridgemodprobe: ERROR: could not insert 'bridge': Unknown error 253insmod /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"

Actualización #1: y esto viene de:

# tail -2 /etc/modprobe.d/dist.conf# Disable netfilter on bridges when the bridge module is loadedinstall 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

También:

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

Sin embargo, incluso después de hacer esto:

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

Todavía sin suerte.

Pasé un día entero en esto, así que ya me estoy arrancando el pelo. Cualquier idea sobre qué más podría intentar o cuál es el problema podría ser muy apreciada.

Actualización #4

>Realicé algunos experimentos usando Netcat y he demostrado que todos los paquetes UDP no se reenvían si se envían desde cualquier contenedor - host. Intenté usar varios puertos, incluidos 53, 2115 y 50000. Sin embargo, los paquetes TCP están bien. Esto sigue siendo cierto si elimino las reglas de iptables con iptables -F.

>Además, puedo enviar paquetes UDP de un contenedor a otro, solo el tráfico UDP del host del contenedor no se reenvía.

Para configurar la prueba:

En el host, que tiene IP 10.1.1.10:

# nc -u -l 50000

En el contenedor:

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

Durante una captura de volcado de TCP, veo:

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  ................

Intenté sin éxito corregir las sumas de comprobación UDP incorrectas a través de este.

>>Noté, sin embargo, que las sumas de verificación UDP incorrectas se ven incluso durante la transmisión exitosa de paquetes UDP (host - host) y contenedor - contenedor.

En resumen, ahora sé:

  • el enrutamiento está bien

  • iptables se vacía

  • SELinux es permisivo

  • todo TCP funciona en todas las direcciones

  • >todo UDP desde el contenedor-el contenedor está bien

  • >todo UDP del host-host está bien

  • >todo UDP del contenedor de host está bien

  • PERO> no se reenvían paquetes UDP del contenedor-host

Lo descubrí.

Teníamos un agente de Trend Micro (antivirus) que se ejecutaba en el SOE y que yo no conocía.

Arreglarlo era tan simple como:

# systemctl stop ds_agent.service# pkill ds_agent

No estoy exactamente seguro en este momento de por qué está bloqueando UDP de los contenedores o cómo detenerlo.

Parece que tienes un modprobe install directiva que no puede funcionar. Posiblemente sea el resultado de una actualización incompleta a RHEL 7.2 o de algunas correcciones manuales.

Tratar grep -r bridge /etc/modprobe.d /lib/modprobe.d para empezar, o de lo contrario cavar alrededor /etc/modprobe.d o /lib/modprobe.d y tratar de encontrar dónde define el install regla que llama sysctl -q -w net.bridge.bridge-nf-call-arptables=0 net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-ip6tables=0

Este sysctl está claramente en el lugar equivocado. Es superfluo o debería aparecer después br_netfilter, no antes. ¿Por qué? Recientemente el /proc/sys/net/bridge la manipulación se ha trasladado de la bridge módulo al br_netfilter módulo. Esto sucede con alguna versión de kernel*.rpm, mientras que el contenido de modprobe.d los directorios se distribuyen con otros paquetes individuales. Lo he verificado en mi RHEL 7.2:

# modprobe bridge# sysctl -q -w net.bridge.bridge-nf-call-iptables=0sysctl: 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

No veo estas reglas "rotas" en mi vanilla RHEL 7.1 y su origen es misterioso para mí. Lo he intentado:

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

Actualizar: Parece xenserver usa un truco similar de modprobe. Es un error desagradable cambiar globalmente el comportamiento del módulo del kernel para todos, ya sea que realmente ejecute xenserver o no; y el error nos ha respondido.

Actualización 2: Ahora, has encontrado que /etc/modprobe.d/dist.conf causa este problema y no docker. Si tienes Docker o no, modprobe bridge siempre devolverá 1 e imprimirá un error. Normalmente dist.conf es parte de module-init-tools paquete en RHEL6. Se supone que este archivo no debe usarse en RHEL7. No está en ninguno de mis sistemas RHEL7 y funcionan bien. En RHEL7 el paquete es kmod y no contiene dist.conf. Yo lo haría:

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

Si dist.conf no es propiedad del paquete, haga una copia de seguridad y elimine cualquier línea que no le brinde ningún beneficio obvio (tal vez incluso elimine el archivo por completo).

Si dist.conf es propiedad de un paquete, considere eliminar/actualizar ese paquete, ya que se volvió claramente defectuoso en términos de compatibilidad con RHEL 7.2.

Tuve problemas con el solucionador de DNS en nuestros contenedores docker. Probé muchas cosas diferentes, y al final, me di cuenta de que mi VPS en Hostgator no tenía instalado por defecto NetworkManager-tui (nmtui), Acabo de instalarlo y reiniciarlo.

sudo yum install NetworkManager-tui

Y reconfiguré mi resolv.conf con DNS predeterminado como 8.8.8.8.

nano /etc/resolv.conf

@Orphans, actualizado con los resultados de mis experimentos en netcat. Básicamente, se pierde todo el UDP de container - > host, pero TCP está bien, y UDP también está bien de container - > container y de host - > container. Y todo es cierto después de iptables-F.

¿Esto ayuda? How do I publish a UDP Port on Docker? - Stack Overflow

¿En qué interfaz ejecutó tcpdump? Debe ejecutarlo en la interfaz ‘docker0’, la interfaz de salida de su host y en el servidor de nombres para ver dónde se descartan los paquetes (probablemente debido a la suma de comprobación UDP incorrecta). Puede ejecutar ‘iptables-t mangle - A POSTROUTING - o docker0-p udp-j CHECKSUM --checksum-fill’ para ver si soluciona su problema? Si su host es una máquina virtual y el comando anterior no solucionó su problema, hágalo también en la interfaz saliente.

Su comando iptables sugerido no ha tenido ningún efecto que pueda observar. Mi host es una instancia de Amazon EC2, con una interfaz ‘eth0’. Si ejecuto ‘tcpdump-i eth0 port 53’, los paquetes no se ven, lo que significa que se dejaron caer en el puente. Intuitivamente, no puedo creer que las sumas de verificación UDP incorrectas sean el problema, considerando que están presentes en todas las direcciones, pero el tráfico solo se elimina en la dirección contenedor → host.

¿Pueden sus contenedores hablar en el puerto 53?
telnet 8.8.8.8 53

No puedo acceder al puerto 8.8.8.8 (TCP) 53 porque 8.8.8.8 está bloqueado por un firewall de la empresa. Sin embargo, puedo conectarme a mi servidor DNS local en el puerto TCP 53 see vea mi actualización. Por la mañana, tengo la intención de encontrar una manera de usar netcat para tratar de demostrar (lo que creo actualmente) que el problema es realmente que estos contenedores simplemente no reenvían el tráfico UDP saliente.