Le noyau Linux ne passe pas par les paquets UDP multicast

35

Récemment, j'ai configuré un nouveau serveur Ubuntu 10.04 et j'ai constaté que mon serveur UDP ne pouvait plus voir les données de multidiffusion envoyées à l'interface, même après avoir rejoint le groupe de multidiffusion. J'ai exactement la même configuration sur deux autres machines LTS Ubuntu 8.04.4 et il n'y a aucun problème à recevoir des données après avoir rejoint le même groupe de multidiffusion.

La carte Ethernet est un Broadcom netXtreme II BCM5709 et le pilote utilisé est:

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

J'utilise smcroute pour gérer mes enregistrements multicast.

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

Après avoir rejoint le groupe, maddr affiche l'enregistrement nouvellement ajouté.

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

Jusqu'ici tout va bien, je peux voir que je reçois des données pour ce groupe de multidiffusion.

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

Je peux également confirmer que l'interface reçoit des paquets mcast.

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

Maintenant, voici le problème. Lorsque je tente de capturer le trafic à l'aide d'un simple serveur Ruby UDP, je ne reçois aucune donnée! Voici un serveur simple qui lit les données envoyées sur le port 15572 et imprime les deux premiers caractères. Cela fonctionne sur les deux serveurs 8.04.4 Ubuntu, mais pas sur le serveur 10.04.

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

Si j'envoie un paquet UDP fabriqué en ruby ​​à localhost, le serveur le reçoit et imprime les deux premiers caractères. Je sais donc que le serveur ci-dessus fonctionne correctement.

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)

Lorsque je vérifie les statistiques de protocole, je constate qu'InMcastPkts n'augmente pas. Sur les autres serveurs 8.04, sur le même réseau, ont reçu quelques milliers de paquets en 10 secondes.

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 je tente de forcer l'interface en mode promisc rien ne change.

À ce stade, je suis coincé. J'ai confirmé que la multidiffusion du noyau est activée pour la multidiffusion. Peut-être y a-t-il d'autres options de configuration que je devrais vérifier?

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

Des idées sur où aller d'ici?

buecking
la source
Allez comprendre. Je vais entrer dans une nouvelle question, l'algorithme associé me montre avec joie que cette question existe, mais qu'elle n'a pas de réponse significative. Boo :(.
VxJasonxV
Je ne sais pas exactement comment je vais attribuer la prime. Un collègue a découvert le problème et j'ai compris POURQUOI cela s'est passé ainsi. Je suis plus que disposé à recevoir des suggestions sur la manière d'attribuer la prime.
VxJasonxV
tu es toujours là? J'ai quelques questions pour toi.
VxJasonxV
J'ai aussi ce problème. Cher Buecking, le résolvez-vous?
Lisez à toutes les réponses à cette question, car d’autres problèmes O / S doivent être corrigés. Nous avons résolu ce problème en changeant rp_filteret /proc/sys/net/ipv4/icmp_echo_ignore_broadcastspuis il a commencé à travailler.
Sam Goldberg

Réponses:

35

Dans notre cas, notre problème a été résolu par des paramètres sysctl, différents de ceux de Maciej.

S'il vous plaît noter que je ne parle pas pour l'OP (buecking), je suis venu sur ce post en raison du problème étant lié aux détails de base (pas de trafic multicast en mode utilisateur).

Nous avons une application qui lit les données envoyées à quatre adresses de multidiffusion et à un port unique par adresse de multidiffusion, à partir d’une appliance connectée (généralement) directement à une interface du serveur de réception.

Nous essayions de déployer ce logiciel sur un site client lorsqu'il a mystérieusement échoué sans raison connue. Les tentatives de débogage de ce logiciel ont abouti à l’inspection de chaque appel système. En fin de compte, ils nous ont tous dit la même chose:

Notre logiciel demande des données et le système d'exploitation n'en fournit jamais.

Le compteur de paquets de multidiffusion incrémenté, tcpdump a montré le trafic atteignant la boîte / interface spécifique, mais nous ne pouvions rien faire avec. SELinux était désactivé, iptables était en cours d'exécution, mais aucune règle ne figurait dans les tables.

Stumped, nous étions.

En fouillant au hasard, nous avons commencé à réfléchir aux paramètres du noyau que sysctl gère, mais aucune des fonctionnalités documentées n'était particulièrement pertinente ou, si elles concernaient du trafic multidiffusion, elles étaient activées. Oh, et ifconfig a bien répertorié "MULTICAST" dans la ligne de fonctions (haut, diffusion, exécution, multidiffusion). Par curiosité nous avons regardé /etc/sysctl.conf. Et voilà, l'image de base de ce client avait quelques lignes supplémentaires ajoutées en bas.

Dans notre cas, le client était prêt net.ipv4.all.rp_filter = 1. rp_filter est le filtre Route Path, qui (si j'ai bien compris) rejette tout le trafic qui n'aurait pas pu atteindre cette zone. Saut de sous-réseau, l'idée étant que l'adresse IP source est usurpée.

Ce serveur se trouvait sur un sous-réseau 192.168.1 / 24 et l’adresse IP source de l’appliance pour le trafic multidiffusion se trouvait quelque part sur le réseau 10. *. Ainsi, le filtre empêchait le serveur de faire quelque chose de significatif avec le trafic.

Quelques modifications approuvées par le client; net.ipv4.eth0.rp_filter = 1et net.ipv4.eth1.rp_filter = 0et nous courions heureux.

VxJasonxV
la source
2
Cela a fonctionné! Le rp_filterpour notre interface réseau 10 Gb vidait tous nos paquets UDP multicast. Couper le filtre laisse tout passer à travers.
chrisaycock
Nous avions des problèmes lors de la configuration de la diffusion via la multidiffusion AMT sur le périphérique tun sur un récepteur Ubuntu et nous pouvions voir les paquets être livrés au périphérique via tcpdump, mais l'application ne souhaite tout simplement pas diffuser en continu. Ce post nous a sauvé!
ingénieur logiciel
2
Fonctionnant sous Ubuntu 14.04, cela ne fonctionnait que pour moi après que je me sois également installé net.ipv4.all.rp_filter = 0. Plus précisément, avec les données de multidiffusion arrivant sur eth2, je devais définir les deux net.ipv4.eth2.rp_filter = 0et net.ipv4.all.rp_filter = 0.
T-Hawk
4

TL / DR Assurez-vous également que votre multidiffusion ne provient pas d'un vlan. tcpdump -eaiderait à déterminer si elles le font.

En toute justice, quelqu'un devrait créer une page avec une liste de contrôle permettant d'éviter que la multidiffusion n'atteigne le pays de l'utilisateur. Cela fait deux jours que je me bats avec cela et, naturellement, rien que je n'ai trouvé sur le Web ne m'aide.

Non seulement je pouvais voir les paquets dans le tcpdump, mais je pouvais en réalité recevoir d'autres paquets multicast, pour d'autres producteurs, juste sur une interface différente. La commande que j'ai finalement utilisée pour vérifier si je pouvais recevoir du multidiffusion était:

$ 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 raison en straceest que je ne pouvais en fait pas socatimprimer les paquets sur la stracesortie standard, mais en sortie, vous pouvez voir clairement si socatles données réelles sont reçues du socket lié (le son sera mis en sourdine après quelques selectappels initiaux )

  • rp_filtersysctl - ne s'applique pas, les systèmes sont sur le même réseau IP (je les ai réglés de 0la même manière, semble 1être un paramètre par défaut maintenant, du moins pour Ubuntu).
  • pare-feu / etc - le système de réception est dépourvu de pare-feu (je ne pense pas que les paquets apparaîtront dans tcpdump s'ils étaient protégés par un pare-feu, mais je suppose que c'est possible si le pare-feu est amusant)
  • Routage IP / Multicast et interfaces multiples - J'ai explicitement rejoint le groupe sur l'interface correcte
  • Matériel réseau Wacky - c'était mon dernier recours, mais changer un ordinateur portable en Intel NUC n'a pas aidé. C'est à propos de l'endroit où j'ai commencé à mâcher mes coudes et à publier ce message sur SE.
  • Le problème dans mon cas était l’utilisation des VLAN par le matériel spécialisé qui produisait ces paquets de multidiffusion. Pour voir si cela est votre problème, assurez-vous d'inclure -eflag à tcpdump, et vérifiez les balises vlan. Il sera nécessaire de configurer une interface dans le bon vlan avant que userland puisse récupérer ces paquets. Le cadeau pour moi était en fait que les producteurs de multidiffusion ne feraient pas un ping, mais n'entreraient même pas dans le cache ARP, même si je pouvais clairement voir les réponses ARP.

Pour le faire fonctionner avec un réseau local virtuel, ce lien peut être utile pour configurer le routage multidiffusion. (Malheureusement, je suis nouveau dans ce domaine et la réputation ne me permet pas d'ajouter une réponse. D'où cette modification.)

Voici ce que j'ai fait (utilisez sudo si nécessaire):

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 cette façon, une interface supplémentaire est créée pour le trafic vlan avec vlan id 100. L'adresse vlan peut être inutile. Ensuite, une adresse de multidiffusion est configurée pour la nouvelle interface (01: 00: 5e: 01: 01: 01 est l'adresse de la couche de liaison pour 239.1.1.1) et tout le trafic de multidiffusion entrant est lié à eth0_100. J'ai également fait toutes les étapes possibles dans les réponses ci-dessus (vérifiez iptables, rp_filter, etc.).

Pawel Veselov
la source
@Gero: L'ajout d'une route de multidiffusion configure la multidiffusion sortante et non la multidiffusion entrante. Vous ne devriez pas lier directement les adresses IP de multidiffusion aux interfaces, à moins que vous ne fassiez quelque chose de génial, c'est normalement le travail de l'application.
Pawel Veselov
2

Vous voudrez peut-être essayer de regarder ces paramètres:

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

Celles-ci ont été utilisées pour permettre la multidiffusion dans RHEL.

Vous voudrez peut-être vous assurer que votre pare-feu autorise le trafic mutlicast; Encore une fois avec RHEL, j'ai activé ce qui suit:

# 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
utilisateur64259
la source
Les options "broadcast" s'appliquent également à "multicast"?
Raedwald
0

Utilisez-vous un commutateur géré? Certains ont des options pour empêcher les "tempêtes de diffusion" ou d'autres problèmes de multidiffusion, ce qui les inciterait à empêcher certains types de paquets. Je vous suggère de consulter la documentation de votre commutateur.

devicenull
la source
0
s.bind("", 15572)

Sûr de ""? Pourquoi ne pas utiliser l'adresse IP de multidiffusion pour se lier?

poige
la source
Les adresses hôtes vides signifient généralement "toutes les interfaces".
VxJasonxV