Trasformare un pacchetto unicast UDP in una trasmissione?


8

Dobbiamo riattivare alcuni computer sulla nostra LAN interna, da Internet.
Abbiamo un router piuttosto chiuso, con pochissimi modi per configurarlo.
Mi piacerebbe usare netfilter (iptables) per farlo perché non coinvolge un demone o simile, ma altre soluzioni vanno bene.

Quello che ho in mente:

  • il computer esterno emette un pacchetto WOL (Wake-On-LAN) all'indirizzo IP pubblico (con il MAC corretto all'interno)
  • la porta corretta è aperta sul router (diciamo 1234), reindirizzando i dati su un box Linux
  • la scatola di Linux trasforma il pacchetto unicast UDP in un pacchetto di trasmissione (stesso contenuto esatto, solo l'indirizzo di destinazione viene modificato in 255.255.255.255 o 192.168.0.255)
  • il pacchetto multicast arriva in ogni scheda di rete e il computer desiderato è ora attivo

Per questo, una regola netfilter molto semplice è:
iptables --table nat --append PREROUTING --in-interface eth+ --protocol udp --destination-port 1234 --jump DNAT --to-destination 192.168.0.255

Purtroppo netfilter sembra ignorare la trasformazione da trasmettere. 192.168.0.255 e 255.255.255.255 non danno nulla. Testato anche con 192.168.0.0 e 0.0.0.0
ho usato tcpdump per vedere cosa succede:
tcpdump -n dst port 1234
13:54:28.583556 IP www.xxx.yyy.zzz.43852 > 192.168.0.100.1234: UDP, length 102
e nient'altro. Dovrei avere una seconda riga come:
13:54:28.xxxxxx IP www.xxx.yyy.zzz.43852 > 192.168.0.255.1234: UDP, length 102

Se reindirizzo a un indirizzo non multicast, va tutto bene. Ho le 2 linee previste. Ma ovviamente questo non funziona per WOL.

C'è un modo per dire a netfilter di emettere pacchetti di trasmissione?

Altri metodi a cui penso:

  • usa iptables per abbinare i pacchetti desiderati, registrali e usa un demone per monitorare il file di registro ed eseguire il pacchetto di trasmissione
  • usa iptables per reindirizzare i pacchetti desiderati su un demone locale, che attiva il pacchetto di trasmissione (più semplice)
  • usa socat (come?)

Un pacchetto di trasmissione non è solo un pacchetto inviato a un indirizzo di trasmissione. C'è un flag per i socket chiamato SO_BROADCAST. Sto cercando di capire come iptables può modificarlo.
lgeorget,

@lgeorget: iptables non è correlato a così socket.
Bertrand SCHITS

Infatti. Non sto guardando nel posto giusto. Ci deve essere un'opzione da qualche parte per iptables per consentirgli di inviare pacchetti di trasmissione.
lgeorget,

1
Hai provato iptables --table nat --append PREROUTING --in-interface eth + --protocol udp --destination-port 1234 --jump DNAT - to-destination 192.168.0.0?
lgeorget,

@lgeorget: grazie per l'idea. Ma stesso risultato. Aggiornamento la domanda
Gregory MOUSSAT,

Risposte:


12

socatè un'utilità killer. Metti da qualche parte nei tuoi script init:

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

Alcuni utenti hanno problemi con UDP-LISTEN, quindi l'utilizzo di UDP-RECV sembra migliore (avviso: potrebbe inviare i pacchetti di trasmissione in un ciclo infinito):

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

forkconsentire di continuare ad ascoltare socat per i pacchetti successivi.
T1limitare la durata dei sottoprocessi a forcella a 1 secondo.
255.255.255.255è più generale di 192.168.0.255. Permettendoti di copiare e incollare senza pensare alla tua attuale struttura di rete. Avvertenza: questo probabilmente invia i pacchetti trasmessi a tutte le interfacce.

Come te, ho notato che WOL funziona con qualsiasi porta. Mi chiedo se sia affidabile. Molti documenti parlano solo delle porte 0, 7 e 9.
Ciò consente di utilizzare una porta non pivile, in modo da poter eseguire socatcon l'utente nobody.

Grazie lgeorget Hauke Laginge Gregory MOUSSATper aver partecipato a questa risposta.
Sentiti libero di aggiungere dettagli.


L'ho provato, ma il problema è che UDP-LISTEN chiuderà il socket dopo l'arrivo del primo pacchetto, indipendentemente dal fork. Utilizzare invece UDP-RECV.
lgeorget,

Nessun problema qui. Hai usato l'opzione "fork"? Vedo nell'uomo UDP-RECV unire i pacchetti. Non ho idea di cosa significhi. UDP-RECVFROM non mostra questo comportamento, ma potrebbe essere un errore nell'uomo.
Bertrand SCHITS

Sì, ho usato il "fork". Ho provato con un processo socat e due netcat (uno per inviare i pacchetti a socat, l'altro per ricevere i pacchetti di trasmissione). Con UPD-LISTEN, socat simula una connessione e chiude il socket alla fine. Con UDP-RECV, utilizza il comportamento predefinito senza connessione di UDP. Da socat man: "Normalmente, le connessioni socket saranno terminate con shutdown (2) che termina il socket anche se è condiviso da più processi."
lgeorget,

2
Socat trasmetterà quindi su tutte le interfacce?
Hauke ​​Laging,

1
@lgeorget: "echo 'dummy' | nc -u -q 0 127.0.0.1 1234" funziona perfettamente con -UDP-LISTEN. Posso eseguirlo più volte. Ma ho problemi con -UDP-RECV e -UDP-RECVFROM: i pacchetti vengono trasmessi alla massima velocità di collegamento fino alla morte di socat. Vedi lo stesso problema con tcpdump?
Bertrand SCHITS

3

Il traffico di trasmissione per definizione è destinato al computer locale. Questo significa che il pacchetto ottiene DNAT su 192.168.0.255 e quindi il kernel vede il pacchetto e decide che è destinato al router stesso, quindi vedrai questo pacchetto nella catena INPUT. Il router (e qualsiasi altro dispositivo) penserà che i pacchetti 192.168.0.255 siano destinati a se stesso e non li inoltrerà ulteriormente. I pacchetti di trasmissione non vengono instradati / inoltrati in base alla progettazione.

C'è una grande soluzione con il trucco ARP menzionato. "Perderai" un indirizzo IP. In 192.168.0.254questo esempio userò dummy - ricordati di non assegnare mai 192.168.0.254a nessun dispositivo della tua rete:

  1. Crea una voce ARP statica sull'interfaccia LAN per l'indirizzo IP che non utilizzerai mai per nessuna macchina:

    arp -i ethLAN --set 192.168.0.254 FF:FF:FF:FF:FF:FF
    
  2. DNAT il tuo taffic UDP Wake-On-Lan sull'interfaccia WAN a questo indirizzo IP fittizio:

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

Funziona perfettamente con i pacchetti WOL. Questa soluzione alternativa funziona anche con prodotti basati sul kernel Linux, come i dispositivi Mikrotik e i dispositivi openwrt. Uso questo trucco sui dispositivi Mikrotik per riattivare la mia macchina da remoto con il mio cellulare.


I pacchetti ricevuti da Internet non vengono trasmessi. Ecco perché la domanda è "Trasforma UNICAST in BROADCAST"
Gregory MOUSSAT,

2

Ho trovato questa domanda su Serverfault .

Tuttavia, non sono riuscito a ottenere tale traffico di trasmissione attraverso il mio router. I pacchetti DNATted non arrivarono nemmeno alla mia catena FORWARD. Forse c'è qualche strana opzione del kernel che non lo consente.

Ma l'idea ARP è interessante. Immagino che dovrebbe essere accompagnato da una regola in OUTPUT che proibisce i pacchetti a questo indirizzo in modo che possa essere raggiunto solo con il traffico inoltrato.


1

Socat OpenWRT

Socat è già stato dichiarato come una risposta, tuttavia la risposta dichiarata non ha funzionato per me sulla mia piattaforma, OpenWRT, con un indirizzo WAN dinamico.

Il mio obiettivo è di inoltrare pacchetti Wake-on-lan UDP unicast dalla porta UDP 9 dell'interfaccia WAN a una sottorete trasmessa su 192.168.20.255.

The Broken (iptables)

Anch'io ho provato con iptables, ma ogni volta che aggiungo una regola che termina con 255, la regola viene trasformata in poltiglia con l'indirizzo di destinazione 0.0.0.0 quando stampo con:

iptables -t nat -L

Credo che iptables non sia in grado di multiplexare il traffico, come richiesto in un unicast per trasmettere la conversione.

Il cattivo (voci di arp contraffatte)

Fingendo voci arp non è poi così male, perché i pacchetti arrivano a tutti sul segmento Ethernet, ma presenta i seguenti svantaggi

  • "Consumi" un indirizzo IP
  • L'IP di destinazione nel pacchetto WoL è errato, anche se lo ottieni perché l'indirizzo MAC è tutto FFFF ...
  • Un malfunzionamento IP può verificarsi se qualcuno sulla rete utilizza quell'indirizzo IP.
  • È una trasmissione Ethernet e non una trasmissione IP.

Nota: questo può essere fatto con il arpcomando o il ip neighcomando.

Il bene

socat, come indicato dalla risposta precedente, è tosto. La precedente risposta socat, tuttavia, mi sono imbattuto in alcuni problemi con esso.

  1. La mia socat non ha inoltrato il traffico quando la destinazione di trasmissione UDP era 255.255.255.255. Ho evitato questo restringendo la sottorete di trasmissione a quella che uso è probabilmente più sicura.
  2. Quando ho impostato l'indirizzo di bind su 0.0.0.0, mi sono imbattuto in una tempesta di trasmissione a causa del ritorno del traffico in rete dalla mia LAN. Per prima cosa ho risolto il problema vincolando i miei DNS pubblici, tuttavia questo non è l'ideale perché i DNS potrebbero non essere disponibili e il mio indirizzo IP assegnato dinamicamente alla mia modifica.

Sono stato in grado di legare a 0.0.0.0 (tutti gli indirizzi) ed evitare la tempesta di trasmissione aggiungendo una regola iptables per impedire che la trasmissione in arrivo riprendesse in socat dal lato LAN. Questa regola, oltre a una regola iptables per accettare il traffico sulla porta UDP 9, e una regola iptables per registrarla otteniamo le seguenti tre regole oltre al comando 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 &

Per gli OpenWRTer, è sufficiente incollarlo /etc/firewall.usere rilasciarlo /etc/init.d/firewall restart.

Congratulazioni, ora dovresti avere WoL funzionante per la tua rete da qualsiasi parte del Web.


0

In realtà netfilter non può fare alcuna trasmissione, il meccanismo di routing lo fa.

Ma lascia cadere qualsiasi trasmissione inoltrata di default.

È diventato possibile inoltrare la trasmissione UDP diretta nel recente kernel Linux (circa la versione 5.0)

È necessario modificare il bc_forwardingparametro per l'interfaccia di rete di trasmissione:

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

(Nota: sembra che l'opzione net.ipv4.conf. All .bc_forwarding non funzioni)

Quindi ora, kernel circa 5.0 + iptables dovrebbe essere abbastanza per te

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.