El kernel de Linux no pasa a través de paquetes UDP multicast

35

Recientemente configuré un nuevo Ubuntu Server 10.04 y noté que mi servidor UDP ya no puede ver los datos de multidifusión enviados a la interfaz, incluso después de unirse al grupo de multidifusión. Tengo exactamente la misma configuración en otras dos máquinas Ubuntu 8.04.4 LTS y no hay ningún problema para recibir datos después de unirme al mismo grupo de multidifusión.

La tarjeta ethernet es una Broadcom netXtreme II BCM5709 y el controlador utilizado es:

b $ ethtool -i eth1
driver: bnx2
version: 2.0.2
firmware-version: 5.0.11 NCSI 2.0.5
bus-info: 0000:01:00.1

Estoy usando smcroute para administrar mis registros de multidifusión.

b$ smcroute -d
b$ smcroute -j eth1 233.37.54.71

Después de unirse al grupo, ip maddr muestra el registro recién agregado.

b$ ip maddr

    1:  lo
        inet  224.0.0.1
        inet6 ff02::1
    2:  eth0
        link  33:33:ff:40:c6:ad
        link  01:00:5e:00:00:01
        link  33:33:00:00:00:01
        inet  224.0.0.1
        inet6 ff02::1:ff40:c6ad
        inet6 ff02::1
    3:  eth1
        link  01:00:5e:25:36:47
        link  01:00:5e:25:36:3e
        link  01:00:5e:25:36:3d
        link  33:33:ff:40:c6:af
        link  01:00:5e:00:00:01
        link  33:33:00:00:00:01
        inet  233.37.54.71 <------- McastGroup.
        inet  224.0.0.1
        inet6 ff02::1:ff40:c6af
        inet6 ff02::1

Hasta ahora todo bien, puedo ver que estoy recibiendo datos para este grupo de multidifusión.

b$ sudo tcpdump -i eth1 -s 65534 host 233.37.54.71
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65534 bytes
09:30:09.924337 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212
09:30:09.947547 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212
09:30:10.108378 IP 192.164.1.120.58866 > 233.37.54.71.15574: UDP, length 268
09:30:10.196841 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212
...

También puedo confirmar que la interfaz está recibiendo paquetes mcast.

b $ ethtool -S eth1 | grep mcast_pack
rx_mcast_packets: 103998
tx_mcast_packets: 33

Ahora aquí está el problema. ¡Cuando trato de capturar el tráfico usando un simple servidor ruby ​​UDP, recibo cero datos! Aquí hay un servidor simple que lee el envío de datos en el puerto 15572 e imprime los dos primeros caracteres. Esto funciona en los dos servidores Ubuntu 8.04.4, pero no en el servidor 10.04.

require 'socket'
s = UDPSocket.new
s.bind("", 15572)
5.times do
  text, sender = s.recvfrom(2)
  puts text
end

Si envío un paquete UDP creado en rubí a localhost, el servidor lo recibe e imprime los dos primeros caracteres. Entonces sé que el servidor anterior funciona correctamente.

irb(main):001:0> require 'socket'
=> true
irb(main):002:0> s = UDPSocket.new
=> #<UDPSocket:0x7f3ccd6615f0>
irb(main):003:0> s.send("I2 XXX", 0, 'localhost', 15572)

Cuando reviso las estadísticas del protocolo, veo que InMcastPkts no está aumentando. Mientras que en los otros servidores 8.04, en la misma red, recibió unos pocos miles de paquetes en 10 segundos.

b $ netstat -sgu ; sleep 10 ; netstat -sgu
IcmpMsg:
    InType3: 11
    OutType3: 11
Udp:
    446 packets received
    4 packets to unknown port received.
    0 packet receive errors
    461 packets sent
UdpLite:
IpExt:
    InMcastPkts: 4654 <--------- Same as below
    OutMcastPkts: 3426
    InBcastPkts: 9854
    InOctets: -1691733021
    OutOctets: 51187936
    InMcastOctets: 145207
    OutMcastOctets: 109680
    InBcastOctets: 1246341
IcmpMsg:
    InType3: 11
    OutType3: 11
Udp:
    446 packets received
    4 packets to unknown port received.
    0 packet receive errors
    461 packets sent
UdpLite:
IpExt:
    InMcastPkts: 4656  <-------------- Same as above
    OutMcastPkts: 3427
    InBcastPkts: 9854
    InOctets: -1690886265
    OutOctets: 51188788
    InMcastOctets: 145267
    OutMcastOctets: 109712
    InBcastOctets: 1246341

Si trato de forzar la interfaz a modo promisc, nada cambia.

En este punto estoy atascado. He confirmado que la configuración del núcleo tiene habilitada la multidifusión. ¿Quizás hay otras opciones de configuración que debería verificar?

b $ grep CONFIG_IP_MULTICAST /boot/config-2.6.32-23-server
CONFIG_IP_MULTICAST=y

¿Alguna idea sobre a dónde ir desde aquí?

buecking
fuente
Imagínate. Voy a ingresar una nueva pregunta, el algoritmo relacionado felizmente me muestra que esta pregunta existe, pero no tiene respuestas significativas. Boo :(.
VxJasonxV
No estoy seguro de cómo exactamente voy a otorgar la recompensa. Un compañero de trabajo encontró el problema y descubrí POR QUÉ sucedió cómo sucedió. Estoy más que dispuesto a recibir sugerencias sobre cómo otorgar la recompensa.
VxJasonxV
sigues por ahí? Tengo algunas preguntas para ti.
VxJasonxV
Tengo este problema también. Querido buecking, ¿lo resuelves?
Para otros que tuvieron este problema, lea todas las respuestas a esta pregunta, porque hay 2-3 configuraciones de O / S que deben corregirse. Se resolvieron este problema cambiando rp_filtery /proc/sys/net/ipv4/icmp_echo_ignore_broadcastsy luego empezamos a trabajar.
Sam Goldberg

Respuestas:

35

En nuestro caso, nuestro problema se resolvió mediante parámetros sysctl, uno diferente de Maciej.

Tenga en cuenta que no hablo por el OP (buecking), llegué a esta publicación debido a que el problema está relacionado con los detalles básicos (no hay tráfico de multidifusión en el país de usuario).

Tenemos una aplicación que lee los datos enviados a cuatro direcciones de multidifusión, y un puerto único por dirección de multidifusión, desde un dispositivo que (generalmente) está conectado directamente a una interfaz en el servidor receptor.

Intentábamos implementar este software en el sitio de un cliente cuando falló misteriosamente sin razón conocida. Los intentos de depurar este software resultaron en la inspección de cada llamada al sistema, en última instancia, todos nos dijeron lo mismo:

Nuestro software solicita datos y el sistema operativo nunca proporciona ninguno.

El contador de paquetes de multidifusión aumentó, tcpdump mostró que el tráfico llegaba a la interfaz box / específica, pero no pudimos hacer nada con él. SELinux estaba deshabilitado, iptables se estaba ejecutando pero no tenía reglas en ninguna de las tablas.

Perplejos, estábamos.

Al hurgar aleatoriamente, comenzamos a pensar en los parámetros del núcleo que maneja sysctl, pero ninguna de las características documentadas era particularmente relevante, o si tenían que ver con el tráfico de multidifusión, estaban habilitadas. Ah, y ifconfig enumeró "MULTICAST" en la línea característica (arriba, transmisión, ejecución, multidifusión). Por curiosidad miramos /etc/sysctl.conf. Bueno, he aquí, la imagen base de este cliente tenía un par de líneas adicionales agregadas en la parte inferior.

En nuestro caso, el cliente había establecido net.ipv4.all.rp_filter = 1. rp_filter es el filtro Ruta de ruta, que (según tengo entendido) rechaza todo el tráfico que posiblemente no podría haber llegado a este cuadro. Salto de subred de red, la idea es que la IP de origen se está falsificando.

Bueno, este servidor estaba en una subred 192.168.1 / 24 y la dirección IP de origen del dispositivo para el tráfico de multidifusión estaba en algún lugar de la red 10. *. Por lo tanto, el filtro impedía que el servidor hiciera algo significativo con el tráfico.

Un par de ajustes aprobados por el cliente; net.ipv4.eth0.rp_filter = 1y net.ipv4.eth1.rp_filter = 0y estábamos corriendo felices.

VxJasonxV
fuente
2
Esto funcionó! La rp_filterde nuestra interfaz de red de 10 Gb estaba volcando todos nuestros paquetes de multidifusión UDP. Al apagar el filtro, todo fluye.
chrisaycock
Tuvimos problemas al configurar la transmisión a través de AMT multicast a través del dispositivo tun en un receptor Ubuntu, y pudimos ver los paquetes que se entregan al dispositivo a través de tcpdump, pero la aplicación simplemente no quiere transmitir. Esta publicación nos salvó!
ingeniero de software
2
Funcionando en Ubuntu 14.04, esto solo funcionó para mí después de configurarlo net.ipv4.all.rp_filter = 0. Específicamente, con los datos de multidifusión llegando a eth2, tuve que configurar ambos net.ipv4.eth2.rp_filter = 0y net.ipv4.all.rp_filter = 0.
T-Hawk
4

TL / DR También asegúrese de que su multidifusión no provenga de un vlan. tcpdump -eayudaría a determinar si lo hacen.

Para ser justos, alguien debería construir una página con una lista de verificación de las cosas que pueden evitar que la multidifusión llegue al país de los usuarios. He estado luchando con eso durante un par de días, y naturalmente nada de lo que pude encontrar en la web me ayudó.

No solo podía ver los paquetes en el tcpdump, sino que también podía recibir otros paquetes de multidifusión, para otros productores, solo en una interfaz diferente. El comando que terminé usando para probar si puedo recibir multidifusión fue:

$ GRP=224.x.x.x # set me to the group
$ PORT=yyyy # set me to the receiving port
$ IFACE=mmmm # set me to the name or IP address of the interface
$ strace -f socat -  UDP4-DATAGRAM:$GRP:$PORT,ip-add-membership=$GRP:$IFACE,bind=0.0.0.0:$PORT,multicast-loop=0

La razón de straceesto es que en realidad no pude socatimprimir los paquetes en la stracesalida estándar, pero en la salida puede ver claramente si socatestá recibiendo datos reales del socket enlazado (de lo contrario, se silenciará después de un par de selectllamadas iniciales )

  • rp_filtersysctl: no se aplica, los sistemas están en la misma red IP (los configuré de 0todos modos, parece que ahora 1es una configuración predeterminada, al menos para Ubuntu).
  • cortafuegos / etc: el sistema receptor no tiene cortafuegos (no creo que los paquetes aparezcan en tcpdump si fueron cortafuegos, pero supongo que es posible si el cortafuegos es divertido)
  • Enrutamiento IP / Multicast y múltiples interfaces: me uní explícitamente al grupo en la interfaz correcta
  • Hardware de red loco: este fue mi último recurso, pero cambiar alguna computadora portátil a una Intel NUC no ayudó. Aquí es donde comencé a masticarme los codos y a perpetrar publicar esto en SE.
  • El problema en mi caso fue el uso de VLAN por parte del hardware especializado que producía esos paquetes de multidifusión. Para ver si este es tu problema, asegúrate de incluir -eflag to tcpdumpy verifica las etiquetas de vlan. Será necesario configurar una interfaz en el vlan correcto antes de que userland pueda obtener esos paquetes. El regalo para mí en realidad fue que los productores de multidifusión no harán ping, pero ni siquiera entrarán en el caché ARP, aunque pude ver claramente las respuestas ARP.

Para que funcione con VLAN, este enlace puede ser útil para configurar el enrutamiento de multidifusión. (Lamentablemente, soy nuevo en esto, por lo que Reputation no me permite agregar una respuesta. De ahí esta edición).

Esto es lo que hice (use sudo si es necesario):

ip link add link eth0 name eth0_100 type vlan id 100
ip addr add 192.168.100.2/24 brd 192.168.100.255 dev eth0_100
ip link set dev eth0_100 up
ip maddr add 01:00:5e:01:01:01 dev eth0_100
route -n add -net 224.0.0.0 netmask 240.0.0.0 dev eth0_100

De esta manera, si se crea una interfaz adicional para el tráfico vlan con vlan id 100. La ip vlan podría ser innecesaria. Luego, se configura una dirección de multidifusión para la nueva interfaz (01: 00: 5e: 01: 01: 01 es la dirección de la capa de enlace para 239.1.1.1) y todo el tráfico de multidifusión entrante está vinculado a eth0_100. También hice todos los pasos posibles en las respuestas anteriores (consulte iptables, rp_filter, etc.).

Pawel Veselov
fuente
@Gero: Agregar ruta de multidifusión configura la multidifusión saliente , no la multidifusión entrante. No debe vincular las direcciones IP de multidifusión a las interfaces directamente, a menos que esté haciendo algo raro, normalmente es el trabajo de la aplicación.
Pawel Veselov
2

Es posible que desee probar y ver estas configuraciones:

proc

echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

sysctl.conf

sed -i -e 's|^net.ipv4.icmp_echo_ignore_broadcasts =.*|net.ipv4.icmp_echo_ignore_broadcasts = 0|g' /etc/sysctl.conf

Estos se han utilizado para habilitar la multidifusión en RHEL.

Es posible que desee asegurarse de que su firewall esté permitiendo el tráfico de multidifusión; De nuevo con RHEL he habilitado lo siguiente:

# allow anything in on multicast addresses
-A INPUT -s 224.0.0.0/4 -j ACCEPT
-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT
# needed for multicast ping responses
-A INPUT -p icmp --icmp-type 0 -j ACCEPT
usuario64259
fuente
¿Las opciones de "transmisión" se aplican también a "multidifusión"?
Raedwald
0

¿Estás utilizando un conmutador administrado? Algunos tienen opciones para evitar 'tormentas de difusión' u otros problemas de multidifusión, que podrían hacer que eviten ciertos tipos de paquetes. Sugeriría echar un vistazo a la documentación de su interruptor.

devicenull
fuente
0
s.bind("", 15572)

Seguro acerca de ""? ¿Por qué no usar la dirección IP de multidifusión para enlazar?

poige
fuente
direcciones de host vacías comúnmente significa "todas las interfaces".
VxJasonxV