Transformar um pacote unicast UDP em uma transmissão?

8

Precisamos ativar alguns computadores em nossa LAN interna, a partir da Internet.
Temos um roteador um tanto fechado, com muito poucas maneiras de configurá-lo.
Eu gostaria de usar o netfilter (iptables) para fazer isso porque 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 (por exemplo, 1234), redirecionando os dados para uma caixa Linux
  • a caixa Linux transforma o pacote unicast UDP em um pacote de broadcast (exatamente o mesmo conteúdo, apenas o endereço de destino é modificado para 255.255.255.255 ou 192.168.0.255)
  • o pacote multicast chega a todas as placas de rede e o computador desejado agora está ativado

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

Infelizmente, o netfilter parece ignorar a transformação para transmitir. 192.168.0.255 e 255.255.255.255 não oferecem nada. Também testado com 192.168.0.0 e 0.0.0.0
, 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, está tudo bem. Eu tenho as 2 linhas esperadas. Mas, obviamente, isso não funciona para o WOL.

Existe uma maneira de dizer ao netfilter para emitir pacotes de transmissão?

Outros métodos que eu 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 aciona o pacote de transmissão (mais simples)
  • use socat (como?)
Gregory MOUSSAT
fonte
Um pacote de transmissão não é apenas um pacote enviado para um endereço de transmissão. Há um sinalizador para soquetes chamado SO_BROADCAST. Estou tentando descobrir como o iptables pode modificá-lo.
precisa saber é o seguinte
@lgeorget: iptables não está relacionado a so sockets.
Bertrand SCHITS
De fato. Não estou olhando para o lugar certo. Deve haver uma opção em algum lugar do iptables para permitir o envio de pacotes de broadcast.
precisa saber é o seguinte
1
Você já tentou o iptables --table nat --append PREROUTING - na interface eth + --protocol udp --destination-port 1234 --jump DNAT --jump DNAT - to-destination 192.168.0.0?
precisa saber é o seguinte
@lgeorget: obrigado pela idéia. Mas mesmo resultado.
Atualizo

Respostas:

12

socaté um utilitário matador. Coloque em algum lugar nos seus scripts init:

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

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

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

forkpermitir que o socat escute os próximos pacotes.
T1limite a vida útil dos subprocessos bifurcados a 1 segundo.
255.255.255.255é mais geral que 192.168.0.255. Permitindo copiar e colar apenas sem pensar na sua estrutura de rede atual. Advertência: isso provavelmente envia os pacotes transmitidos para todas as interfaces.

Como você, notei que o WOL funciona com qualquer porta. Gostaria de saber se isso é confiável. Muitos documentos falam apenas das portas 0, 7 e 9.
Isso permite usar uma porta não privilegiada, para que você possa executar socatcom o usuário nobody.

Obrigado lgeorget Hauke Laginge Gregory MOUSSATpor ter participado desta resposta.
Fique à vontade para adicionar detalhes.

Bertrand SCHITS
fonte
Eu tentei isso, mas o problema é que o UDP-LISTEN fechará o soquete após a chegada do primeiro pacote, independentemente do fork. Use UDP-RECV.
precisa saber é o seguinte
Não tem problema aqui. Você usou a opção "fork"? Eu vejo no homem pacotes de mesclagem UDP-RECV. Não faço ideia do que isso significa. UDP-RECVFROM não exibe esse comportamento, mas pode ser um erro no homem.
Bertrand SCHITS
Sim, eu usei o 'garfo'. Eu tentei com um socat e dois processos netcat (um para enviar pacotes para o socat, o outro para receber os pacotes de transmissão). Com UPD-LISTEN, o socat simula uma conexão e fecha o soquete no final. Com o UDP-RECV, ele usa o comportamento sem conexão padrão do UDP. De socat man: "Normalmente, as conexões de soquete serão encerradas com shutdown (2), que encerra o soquete, mesmo que seja compartilhado por vários processos".
precisa saber é o seguinte
2
O socat vai transmitir em todas as interfaces então?
perfil completo de Hauke ​​Laging
1
@lgeorget: "echo 'dummy' | nc -u -q 0 127.0.0.1 1234" funciona perfeitamente com -UDP-LISTEN. Eu posso executá-lo várias vezes. Mas tenho problemas com -UDP-RECV e -UDP-RECVFROM: os pacotes são transmitidos na taxa máxima de link até que o socat seja morto. Você vê o mesmo problema com o tcpdump?
Bertrand SCHITS
3

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

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

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

    arp -i ethLAN --set 192.168.0.254 FF:FF:FF:FF:FF:FF
    
  2. DNAT sua capacidade de Wake-On-Lan UDP 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 Linux, como dispositivos Mikrotik e dispositivos openwrt. Eu uso esse truque nos dispositivos Mikrotik para ativar minha máquina remotamente com meu telefone celular.

plagiat0r
fonte
Os pacotes recebidos da internet não são transmitidos. É por isso que a questão é "Transformar UNICAST para transmitir"
Gregory MOUSSAT
2

Encontrei esta pergunta no Serverfault .

Não consegui obter esse tráfego de transmissão através do meu roteador. Os pacotes DNATted nem chegaram à minha cadeia FORWARD. Talvez haja alguma opção estranha do kernel que não permita isso.

Mas a ideia do ARP é interessante. Eu acho que isso deve ser acompanhado por uma regra na SAÍDA que proíbe pacotes para esse endereço, para que possa ser alcançado apenas com o tráfego encaminhado.

Hauke ​​Laging
fonte
1

Socat OpenWRT

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

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 adiciono uma regra que termina em 255, a regra é transformada em mush com o endereço de destino 0.0.0.0 quando imprimo com:

iptables -t nat -L

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

O ruim (falsificando entradas arp)

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

  • Você "consome" um endereço IP
  • O IP de destino no pacote WoL está errado, mesmo que você o obtenha porque o endereço MAC é todo FFFF ...
  • Um mau funcionamento do 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 arpcomando ou ip neighcomando.

O bom

socat, como indicado na resposta anterior, é durão. A resposta socat anterior, no entanto, tive alguns problemas com ela.

  1. Meu socat não encaminhava o tráfego quando o destino de transmissão UDP era 255.255.255.255. Evitei isso restringindo a sub-rede de transmissão à que eu uso, provavelmente é mais segura.
  2. Quando defino o endereço de ligação como 0.0.0.0, encontrei uma tempestade de transmissão devido ao tráfego retornando ao socat da minha LAN. Resolvi isso primeiro vinculando meus ddns públicos, no entanto, isso não é ideal porque os ddns podem não estar disponíveis e meu endereço IP atribuído dinamicamente é minha alteração.

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 retornasse ao socat pelo 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, colar /etc/firewall.usere emitir isso /etc/init.d/firewall restarté suficiente.

Parabéns, agora você deve ter o WoL trabalhando para a sua rede de qualquer lugar da Web.

vittorio88
fonte
0

Na verdade, o netfilter não pode fazer nenhuma transmissão, o mecanismo de roteamento faz isso.

Mas descarta qualquer transmissão encaminhada por padrão.

Tornou-se possível encaminhar a transmissão UDP direcionada no kernel recente do Linux (por volta da versão 5.0)

Você precisa modificar o bc_forwardingparâmetro para transmitir a interface de rede:

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

(Nota: parece que a opção net.ipv4.conf. All .bc_forwarding não funciona)

Então agora, o kernel sobre 5.0 + iptables deve ser suficiente para você

Yury Pavlov
fonte