Transformar um pacote unicast UDP em uma transmissão?

8

Precisamos ativar alguns computadores em nossa LAN interna, da Internet.
Temos um roteador um pouco fechado, com poucas maneiras de configurá-lo.
Eu gostaria de usar o netfilter (iptables) para fazer isso porque ele não envolve um daemon ou similar, mas outras soluções estão bem.

O que tenho em mente:

  • o computador externo emite um pacote WOL (Wake-On-LAN) para o endereço IP público (com o MAC correto dentro)
  • a porta correta está aberta no roteador (digamos 1234), redirecionando os dados para uma caixa do Linux
  • a caixa Linux transforma o pacote unicast UDP em um pacote de difusão (exatamente o mesmo conteúdo, somente o endereço de destino é modificado para 255.255.255.255 ou 192.168.0.255)
  • o pacote multicast chega a cada NIC e o computador desejado está agora ativo

Para isso, uma regra muito simples do netfilter é:
iptables --table nat --append PREROUTING --in-interface eth+ --protocol udp --destination-port 1234 --jump DNAT --to-destination 192.168.0.255

Alas netfilter parece ignorar a transformação para transmissão. 192.168.0.255 e 255.255.255.255 não dá nada. Também testado com 192.168.0.0 e 0.0.0.0
Eu usei o tcpdump para ver o que acontece:
tcpdump -n dst port 1234
13:54:28.583556 IP www.xxx.yyy.zzz.43852 > 192.168.0.100.1234: UDP, length 102
e nada mais. Eu deveria ter uma segunda linha como: 13:54:28.xxxxxx IP www.xxx.yyy.zzz.43852 > 192.168.0.255.1234: UDP, length 102

Se eu redirecionar para um endereço não multicast, tudo está bem. Eu tenho as duas linhas esperadas. Mas obviamente isso não funciona para o WOL.

Existe uma maneira de dizer ao netfilter para emitir pacotes de broadcast?

Outros métodos em que penso:

  • use iptables para corresponder aos pacotes desejados, registre-os e use um daemon para monitorar o arquivo de log e disparar o pacote de transmissão
  • use iptables para redirecionar os pacotes desejados para um daemon local, que dispara o pacote de transmissão (mais simples)
  • usa socat (como?)
por Gregory MOUSSAT 01.06.2013 / 14:20

4 respostas

10

socat é um utilitário matador. Coloque em algum lugar em seus scripts de inicialização:

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

Alguns usuários têm problemas com o UDP-LISTEN, portanto, usar UDP-RECV parece melhor (aviso: poderia enviar os pacotes de transmissão em um loop infinito):

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

fork permite continuar a ouvir os próximos pacotes.
T1 limita a vida dos subprocessos bifurcados a 1 segundo.
255.255.255.255 é mais geral que 192.168.0.255. Permitindo que você apenas copie e cole sem pensar em sua estrutura de rede atual. Advertência: provavelmente, enviar os pacotes transmitidos para todas as interfaces.

Como você, notei que o WOL funciona com qualquer porta. Eu me pergunto se isso é confiável. Muitos documentos falam apenas sobre as portas 0, 7 e 9.
Isso permite usar uma porta não privilegiada, para que você possa executar socat com o usuário nobody .

Agradecimentos a lgeorget Hauke Laging e Gregory MOUSSAT por terem participado dessa resposta.
Sinta-se à vontade para adicionar detalhes.

    
por 01.06.2013 / 15:06
3

O tráfego de transmissão, por definição, é destinado à máquina local. Isso significa que o pacote é DNAT'ed para 192.168.0.255 e, em seguida, o kernel vê o pacote e decide que ele é destinado ao próprio roteador, então você verá este pacote na cadeia INPUT. O roteador (e qualquer outro dispositivo) achará que 192.168.0.255 pacotes são destinados a ele e não os encaminharão mais. Os pacotes de transmissão não são encaminhados / encaminhados por design.

Existe uma ótima solução com o truque ARP mencionado. Você "perderá" um endereço IP. Usarei dummy 192.168.0.254 neste exemplo - lembre-se de nunca atribuir 192.168.0.254 a nenhum dispositivo na sua rede:

  1. Crie uma entrada ARP estática na interface LAN para o endereço IP que você nunca usará em qualquer máquina:

    arp -i ethLAN --set 192.168.0.254 FF:FF:FF:FF:FF:FF
    
  2. DNAT seu protocolo UDP Wake-On-Lan na interface WAN para este endereço IP fictício:

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

Isso funciona perfeito para pacotes WOL. Esta solução alternativa também funciona em produtos baseados no kernel do Linux, como dispositivos Mikrotik e dispositivos openwrt. Eu uso esse truque em dispositivos Mikrotik para ativar minha máquina remotamente com meu celular.

    
por 06.05.2014 / 23:43
2

Eu encontrei esta pergunta no Serverfault .

No entanto, não consegui obter esse tráfego de transmissão através do meu router. Os pacotes DNATted nem chegaram à minha cadeia FORWARD. Talvez haja alguma opção estranha do kernel que proíba isso.

Mas a ideia do ARP é interessante. Eu acho que deveria ser acompanhado por uma regra em OUTPUT que proíbe pacotes para este endereço para que ele possa ser alcançado somente com o tráfego encaminhado.

    
por 01.06.2013 / 15:49
0

Socat OpenWRT

Socat já foi declarado como uma resposta, no entanto, a resposta declarada não funcionou para mim na minha plataforma, OpenWRT, com um endereço dinâmico de WAN.

Meu objetivo é encaminhar pacotes UDP wake-on-lan unicast da porta UDP 9 da interface WAN para uma transmissão de sub-rede em 192.168.20.255.

O quebrado (iptables)

Eu também tentei com o iptables, mas toda vez que eu adiciono uma regra que termina em 255, a regra é transformada em pasta com o endereço de destino 0.0.0.0 quando eu imprimo com:

iptables -t nat -L

Acredito que o iptables não é capaz de multiplexar o tráfego, conforme exigido em um unicast para transmitir a conversão.

O ruim (falsas entradas de arp)

Fazer entradas arp não é tão ruim, porque os pacotes chegam a todos no segmento ethernet, mas tem as seguintes desvantagens

  • Você "consome" um endereço IP
  • O IP de destino no pacote WoL está errado, mesmo que você o consiga, porque o endereço MAC é todo FFFF ...
  • Um mau funcionamento de IP pode ocorrer se alguém na rede usar esse endereço IP.
  • É uma transmissão Ethernet e não uma transmissão IP.

Nota: Isso pode ser feito com o comando arp ou ip neigh .

O bem

socat, como indicado pela resposta anterior, é foda. A resposta anterior socat, no entanto, me deparei com alguns problemas com ele.

  1. Meu socat não redirecionou o tráfego quando o destino da transmissão UDP era 255.255.255.255. Eu evitei isso, restringindo a sub-rede de transmissão para o que eu uso é provavelmente mais seguro.
  2. Quando defino o endereço de ligação como 0.0.0.0, me deparei com uma tempestade de transmissão devido ao tráfego retornando da minha LAN para a socat. Eu primeiro resolvi isso ligando para o meu ddns público, no entanto, isso não é ideal, porque ddns podem não estar disponíveis e meu endereço IP atribuído dinamicamente a minha mudança.

Eu consegui vincular a 0.0.0.0 (todos os endereços) e evitar a tempestade de broadcast adicionando uma regra iptables para impedir que a transmissão recebida retorne ao socat do lado da LAN. Esta regra, além de uma regra do iptables para aceitar o tráfego na porta UDP 9, e uma regra do iptables para registrá-lo, obtemos as três regras a seguir, além do 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 &

Para os OpenWRTers, colá-lo em /etc/firewall.user e emitir /etc/init.d/firewall restart é suficiente.

Parabéns, agora você deve ter o WoL funcionando para sua rede em qualquer lugar na Web.

    
por 03.08.2016 / 00:40