Transformer un paquet de monodiffusion UDP en diffusion?

8

Nous devons réveiller certains ordinateurs de notre réseau local, à partir d'Internet.
Nous avons un routeur quelque peu fermé, avec très peu de façons de le configurer.
J'aimerais utiliser netfilter (iptables) pour ce faire car il n'implique pas de démon ou similaire, mais d'autres solutions sont correctes.

Ce que j'ai en tête:

  • l'ordinateur externe émet un paquet WOL (Wake-On-LAN) à l'adresse IP publique (avec le bon MAC à l'intérieur)
  • le port correct est ouvert sur le routeur (par exemple 1234), redirigeant les données vers une boîte Linux
  • la boîte Linux transforme le paquet de monodiffusion UDP en paquet de diffusion (exactement le même contenu, seule l'adresse de destination est modifiée en 255.255.255.255 ou 192.168.0.255)
  • le paquet de multidiffusion vient à chaque NIC, et l'ordinateur souhaité est maintenant réveillé

Pour cela, une règle de netfilter très simple est:
iptables --table nat --append PREROUTING --in-interface eth+ --protocol udp --destination-port 1234 --jump DNAT --to-destination 192.168.0.255

Hélas, Netfilter semble ignorer la transformation en diffusion. 192.168.0.255 et 255.255.255.255 ne donne rien. Également testé avec 192.168.0.0 et 0.0.0.0,
j'ai utilisé tcpdump pour voir ce qui se passe:
tcpdump -n dst port 1234
13:54:28.583556 IP www.xxx.yyy.zzz.43852 > 192.168.0.100.1234: UDP, length 102
et rien d'autre. Je devrais avoir une deuxième ligne comme:
13:54:28.xxxxxx IP www.xxx.yyy.zzz.43852 > 192.168.0.255.1234: UDP, length 102

Si je redirige vers une adresse non multicast, tout va bien. J'ai les 2 lignes attendues. Mais évidemment, cela ne fonctionne pas pour WOL.

Existe-t-il un moyen de dire à netfilter d'émettre des paquets de diffusion?

D'autres méthodes auxquelles je pense:

  • utilisez iptables pour faire correspondre les paquets souhaités, enregistrez-les et utilisez un démon pour surveiller le fichier journal et déclencher le paquet de diffusion
  • utilisez iptables pour rediriger les paquets souhaités vers un démon local, qui déclenche le paquet de diffusion (plus simple)
  • utiliser socat (comment?)
Gregory MOUSSAT
la source
Un paquet de diffusion n'est pas seulement un paquet envoyé à une adresse de diffusion. Il existe un indicateur pour les sockets appelé SO_BROADCAST. J'essaie de comprendre comment iptables peut le modifier.
lgeorget
@lgeorget: iptables n'est pas lié aux so sockets.
Bertrand SCHITS
En effet. Je ne cherche pas au bon endroit. Il doit y avoir une option quelque part pour iptables pour lui permettre d'envoyer des paquets de diffusion.
lgeorget
1
Avez-vous essayé iptables --table nat --append PREROUTING --in-interface eth + --protocol udp --destination-port 1234 --jump DNAT --to-destination 192.168.0.0?
lgeorget
@lgeorget: merci pour l'idée. Mais même résultat. Je mets à jour la question
Gregory MOUSSAT

Réponses:

12

socatest un utilitaire tueur. Mettez quelque part dans vos scripts d'initialisation:

socat -u -T1 UDP-LISTEN:1234,fork UDP-DATAGRAM:255.255.255.255:5678,broadcast

Certains utilisateurs ont des problèmes avec UDP-LISTEN, donc utiliser UDP-RECV semble mieux (avertissement: pourrait envoyer les paquets de diffusion dans une boucle sans fin):

socat -u UDP-RECV:1234 UDP-DATAGRAM:255.255.255.255:5678,broadcast

forkpermettent de garder socat à l'écoute des prochains paquets.
T1limiter la durée de vie des sous-processus fourchus à 1 seconde.
255.255.255.255est plus général que 192.168.0.255. Vous permettant de simplement copier-coller sans penser à votre structure réseau actuelle. Mise en garde: cela envoie probablement les paquets diffusés à toutes les interfaces.

Comme vous, j'ai remarqué que WOL fonctionne avec n'importe quel port. Je me demande si c'est fiable. Beaucoup de documents ne parlent que des ports 0, 7 et 9.
Cela permet d'utiliser un port non pivotant, afin que vous puissiez exécuter socatavec l'utilisateur nobody.

Merci lgeorget Hauke Laginget Gregory MOUSSATd'avoir participé à cette réponse.
N'hésitez pas à ajouter des détails.

Bertrand SCHITS
la source
J'ai essayé mais le problème est qu'UDP-LISTEN fermera le socket après l'arrivée du premier paquet, peu importe la fourchette. Utilisez plutôt UDP-RECV.
lgeorget
Pas de problème ici. Vous avez utilisé l'option "fork"? Je vois dans l'homme des paquets de fusion UDP-RECV. Je n'ai aucune idée de ce que cela signifie. UDP-RECVFROM ne présente pas ce comportement, mais il peut s'agir d'une erreur chez l'homme.
Bertrand SCHITS
Oui, j'ai utilisé la «fourchette». J'ai essayé avec un socat et deux processus netcat (l'un pour envoyer des paquets à socat, l'autre pour recevoir les paquets de diffusion). Avec UPD-LISTEN, socat simule une connexion et ferme le socket à la fin. Avec UDP-RECV, il utilise le comportement sans connexion par défaut d'UDP. De socat man: "Normalement, les connexions de socket seront terminées par shutdown (2) qui termine le socket même s'il est partagé par plusieurs processus."
lgeorget
2
Socat va-t-il alors diffuser sur toutes les interfaces?
Hauke ​​Laging du
1
@lgeorget: "echo 'dummy' | nc -u -q 0 127.0.0.1 1234" fonctionne parfaitement avec -UDP-LISTEN. Je peux l'exécuter plusieurs fois. Mais j'ai des problèmes avec -UDP-RECV et -UDP-RECVFROM: les paquets sont diffusés au débit de liaison maximum jusqu'à ce que socat soit tué. Voyez-vous le même problème avec tcpdump?
Bertrand SCHITS
3

Le trafic de diffusion est par définition destiné à la machine locale. Cela signifie que le paquet est DNAT à 192.168.0.255, puis le noyau voit le paquet et décide qu'il est destiné au routeur lui-même, vous verrez donc ce paquet dans la chaîne INPUT. Le routeur (et tout autre périphérique) pensera que les paquets 192.168.0.255 sont destinés à lui-même et ne les transmettra plus. Les paquets de diffusion ne sont pas acheminés / transmis par conception.

Il existe une excellente solution de contournement avec l'astuce ARP mentionnée. Vous "perdrez" une adresse IP. Je vais utiliser factice 192.168.0.254dans cet exemple - n'oubliez pas de ne jamais attribuer 192.168.0.254à aucun appareil de votre réseau:

  1. Créez une entrée ARP statique sur l'interface LAN pour l'adresse IP que vous n'utiliserez jamais pour aucune machine:

    arp -i ethLAN --set 192.168.0.254 FF:FF:FF:FF:FF:FF
    
  2. DNAT votre WDP Wake-On-Lan UDP sur l'interface WAN à cette adresse IP factice:

    iptables --table nat --append PREROUTING  --in-interface ethWAN --protocol udp --destination-port 1234 --jump DNAT --to-destination 192.168.0.254
    

Cela fonctionne parfaitement pour les paquets WOL. Cette solution de contournement fonctionne également sur les produits basés sur le noyau Linux, comme les périphériques Mikrotik et les périphériques openwrt. J'utilise cette astuce sur les appareils Mikrotik pour réveiller ma machine à distance avec mon téléphone portable.

plagiat0r
la source
Les paquets reçus d'Internet ne sont pas diffusés. C'est pourquoi la question est "Transformer UNICAST en BROADCAST"
Gregory MOUSSAT
2

J'ai trouvé cette question sur Serverfault .

Je n'ai pas réussi à obtenir un tel trafic de diffusion via mon routeur. Les paquets DNATted ne sont même pas arrivés à ma chaîne FORWARD. Il y a peut-être une étrange option de noyau qui interdit cela.

Mais l'idée ARP est intéressante. Je suppose que cela devrait être accompagné d'une règle dans OUTPUT qui interdit les paquets à cette adresse afin qu'elle ne puisse être atteinte qu'avec du trafic transféré.

Hauke ​​Laging
la source
1

Socat OpenWRT

Socat a déjà été indiqué comme réponse, mais la réponse indiquée n'a pas fonctionné pour moi sur ma plate-forme, OpenWRT, avec une adresse WAN dynamique.

Mon objectif est de transmettre des paquets de réveil sur réseau local monodiffusion depuis le port UDP 9 de l'interface WAN vers un sous-réseau diffusé sur 192.168.20.255.

Les cassés (iptables)

Moi aussi, j'ai essayé avec iptables, mais chaque fois que j'ajoute une règle qui se termine par 255, la règle est transformée en bouillie avec l'adresse de destination 0.0.0.0 lorsque j'imprime avec:

iptables -t nat -L

Je crois qu'iptables n'est pas capable de multiplexer le trafic, comme requis dans une conversion monodiffusion à diffusion.

Le mauvais (fausses entrées d'arp)

La simulation d'entrées d'arp n'est pas si mauvaise, car les paquets atteignent tout le monde sur le segment Ethernet, mais cela présente les inconvénients suivants

  • Vous "consommez" une adresse IP
  • L'IP de destination dans le paquet WoL est incorrecte, même si vous l'obtenez car l'adresse MAC est entièrement FFFF ...
  • Un dysfonctionnement IP peut se produire si quelqu'un sur le réseau utilise cette adresse IP.
  • Il s'agit d'une diffusion Ethernet et non d'une diffusion IP.

Remarque: Cela peut être fait avec la arpcommande ou la ip neighcommande.

Le bon

socat, comme indiqué par la réponse précédente, est un dur à cuire. Cependant, dans la réponse précédente de Socat, j'ai rencontré quelques problèmes.

  1. Mon socat n'a pas retransmis le trafic lorsque la destination de diffusion UDP était 255.255.255.255. J'ai évité cela en limitant le sous-réseau de diffusion à celui que j'utilise est probablement plus sûr.
  2. Lorsque j'ai défini l'adresse de liaison sur 0.0.0.0, j'ai rencontré une tempête de diffusion en raison du trafic rebondissant dans socat depuis mon réseau local. J'ai d'abord résolu ce problème en me liant à mes ddns publics, mais ce n'est pas idéal car les ddns peuvent ne pas être disponibles et mon adresse IP attribuée dynamiquement ma modification.

J'ai pu me lier à 0.0.0.0 (toutes les adresses) et éviter la tempête de diffusion en ajoutant une règle iptables pour empêcher la diffusion entrante de rebondir dans socat du côté LAN. Cette règle, en plus d'une règle iptables pour accepter le trafic sur le port UDP 9, et d'une règle iptables pour le journaliser, nous obtenons les trois règles suivantes en plus de la commande socat.

iptables -I input_wan_rule -p udp --dport 9 -j ACCEPT -m comment --comment "firewall entry to allow udp port 9 to socat"
iptables -I input_wan_rule -p udp --dport 9 -j LOG --log-prefix 'Received MAGIC PACKET on udp/9'
iptables -I input_lan_rule -p udp --dport 9 -d 192.168.20.0/24 -j DROP -m comment --comment "block broadcast from bouncing back to socat to avoid storm"

killall socat 2>/dev/null
socat -u -T1 UDP-LISTEN:9,bind=0.0.0.0,fork UDP-DATAGRAM:192.168.20.255:9,broadcast &

Pour les OpenWRTers, coller cela /etc/firewall.useret émettre /etc/init.d/firewall restartest suffisant.

Félicitations, WoL devrait maintenant fonctionner pour votre réseau depuis n'importe où sur le Web.

vittorio88
la source
0

En fait, netfilter ne peut faire aucune diffusion, le mécanisme de routage le fait.

Mais il supprime toute diffusion retransmise par défaut.

Il est devenu possible de transmettre une diffusion UDP dirigée dans un noyau Linux récent (vers la version 5.0)

Vous devez modifier le bc_forwardingparamètre de diffusion de l'interface réseau:

sudo sysctl -w net.ipv4.conf.eth1.bc_forwarding=1

(Remarque: il semble que l'option net.ipv4.conf. All .bc_forwarding ne fonctionne pas)

Alors maintenant, le noyau sur 5.0 + iptables devrait vous suffire

Yury Pavlov
la source