Преобразовать одноадресный пакет UDP в широковещательную рассылку?


8

Нам нужно разбудить некоторые компьютеры во внутренней локальной сети из Интернета.
У нас есть несколько закрытый маршрутизатор, и у него очень мало способов его настройки.
Я хотел бы использовать netfilter (iptables), чтобы сделать это, потому что он не включает демон или подобное, но другие решения в порядке.

Что я имею в виду:

  • внешний компьютер выдает пакет WOL (Wake-On-LAN) на общедоступный IP-адрес (с правильным MAC-адресом внутри)
  • правильный порт открыт на маршрутизаторе (скажем, 1234), перенаправляя данные в окно Linux
  • коробка Linux преобразует одноадресный пакет UDP в широковещательный пакет (точно такой же контент, только адрес назначения изменяется на 255.255.255.255 или 192.168.0.255)
  • пакет многоадресной рассылки поступает на каждый сетевой адаптер, и нужный компьютер теперь не спит

Для этого очень простое правило сетевого фильтра:
iptables --table nat --append PREROUTING --in-interface eth+ --protocol udp --destination-port 1234 --jump DNAT --to-destination 192.168.0.255

Увы, netfilter, похоже, игнорирует преобразование в трансляцию. 192.168.0.255 и 255.255.255.255 ничего не дает. Также протестирован с 192.168.0.0 и 0.0.0.0
Я использовал tcpdump, чтобы увидеть, что происходит:
tcpdump -n dst port 1234
13:54:28.583556 IP www.xxx.yyy.zzz.43852 > 192.168.0.100.1234: UDP, length 102
и ничего больше. У меня должна быть вторая строка вроде:
13:54:28.xxxxxx IP www.xxx.yyy.zzz.43852 > 192.168.0.255.1234: UDP, length 102

Если я перенаправлю на адрес без многоадресной рассылки, все в порядке. У меня есть 2 ожидаемые линии. Но очевидно, что это не работает для WOL.

Есть ли способ сказать netfilter выдавать широковещательные пакеты?

Другие методы, о которых я думаю:

  • используйте iptables для сопоставления желаемых пакетов, зарегистрируйте их и используйте демон для мониторинга файла журнала и запуска широковещательного пакета
  • используйте iptables для перенаправления нужных пакетов локальному демону, который запускает широковещательный пакет (проще)
  • использовать socat (как?)

Широковещательный пакет - это не просто пакет, отправленный на широковещательный адрес. Для сокетов есть флаг, который называется SO_BROADCAST. Я пытаюсь выяснить, как iptables может изменить его.
lgeorget

@lgeorget: iptables не относится к таким сокетам.
Бертран Щитс

Верно. Я не смотрю в нужном месте. Где-то должна быть опция для iptables, позволяющая отправлять широковещательные пакеты.
lgeorget

1
Вы пробовали iptables --table nat --append PREROUTING --in-interface eth + --protocol udp --destination-port 1234 --jump DNAT --to-destination 192.168.0.0?
lgeorget

@lgeorget: спасибо за идею. Но результат тот же.
Обновляю

Ответы:


12

socatутилита-убийца Поместите где-нибудь в свои сценарии инициализации:

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

У некоторых пользователей возникают проблемы с UDP-LISTEN, поэтому использование UDP-RECV выглядит лучше (предупреждение: может отправлять широковещательные пакеты в бесконечном цикле):

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

forkПозволяет вести сокат прослушивание следующих пакетов.
T1ограничить срок службы разветвленных подпроцессов до 1 секунды.
255.255.255.255является более общим, чем 192.168.0.255. Позволяет вам просто копировать и вставлять, не думая о вашей текущей структуре сети. Предупреждение: это, вероятно, отправляет широковещательные пакеты на каждый интерфейс.

Как и вы, я заметил, что WOL работает с любым портом. Интересно, это надежно? Во многих документах говорится только о портах 0, 7 и 9.
Это позволяет использовать порт без pivilegied, поэтому вы можете работать socatс пользователем nobody.

Спасибо lgeorget Hauke Lagingи Gregory MOUSSATприняли участие в этом ответе.
Не стесняйтесь добавлять детали.


Я пробовал это, но проблема в том, что UDP-LISTEN закроет сокет после того, как первый пакет прибыл, независимо от разветвления. Вместо этого используйте UDP-RECV.
lgeorget

Здесь нет проблем. Вы использовали вариант «вилка»? Я вижу в человеке UDP-RECV пакеты слияния. Я понятия не имею, что это значит. UDP-RECVFROM не отображает эту информацию, но это может быть ошибкой в ​​человеке.
Бертран Щитс

Да, я использовал «вилку». Я попытался с помощью socat и двух процессов netcat (один для отправки пакетов в socat, другой для получения широковещательных пакетов). С UPD-LISTEN socat имитирует соединение и закрывает сокет в конце. В UDP-RECV используется стандартное поведение UDP без подключения. От socat man: «Обычно сокетные соединения заканчиваются shutdown (2), который завершает сокет, даже если он используется несколькими процессами».
lgeorget

2
Собирается ли socat вещать на всех интерфейсах?
Hauke ​​Laging

1
@lgeorget: "echo 'dummy' | nc -u -q 0 127.0.0.1 1234" отлично работает с -UDP-LISTEN. Я могу запустить его несколько раз. Но у меня проблемы с -UDP-RECV и -UDP-RECVFROM: пакеты передаются с максимальной скоростью, пока не будет уничтожен socat. Вы видите ту же проблему с tcpdump?
Бертран Щитс

3

Широковещательный трафик по определению предназначен для локальной машины. Это означает, что пакет получает DNAT до 192.168.0.255, а затем ядро ​​видит пакет и решает, что он предназначен для самого маршрутизатора, поэтому вы увидите этот пакет в цепочке INPUT. Маршрутизатор (и любое другое устройство) будет считать, что 192.168.0.255 пакетов предназначено для него, и не будет пересылать их дальше. Широковещательные пакеты не маршрутизируются / не пересылаются по проекту.

Существует отличный обходной путь с упомянутым трюком ARP. Вы «потеряете» один IP-адрес. 192.168.0.254В этом примере я буду использовать пустышку - не забывайте никогда не назначать 192.168.0.254никакие устройства в вашей сети:

  1. Создайте статическую запись ARP на интерфейсе локальной сети для IP-адреса, который вы никогда не будете использовать для любой машины:

    arp -i ethLAN --set 192.168.0.254 FF:FF:FF:FF:FF:FF
    
  2. DNAT вашего UDP-трафика Wake-On-Lan по интерфейсу WAN по этому фиктивному IP-адресу:

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

Это прекрасно работает для пакетов WOL. Этот обходной путь также работает с продуктами, основанными на ядре Linux, такими как устройства Mikrotik и устройства openwrt. Я использую этот трюк на устройствах Mikrotik, чтобы дистанционно разбудить мою машину с помощью моего мобильного телефона.


Пакеты, полученные из Интернета, не передаются. Вот почему вопрос «Преобразование UNICAST в BROADCAST»
Грегори МУССАТ

2

Я нашел этот вопрос на Serverfault .

Мне не удалось получить такой широковещательный трафик через мой маршрутизатор. Пакеты с DNAT даже не попали в мою цепочку FORWARD. Может быть, есть какая-то странная опция ядра, которая запрещает это.

Но идея ARP интересна. Я предполагаю, что это должно сопровождаться правилом в OUTPUT, которое запрещает пакеты по этому адресу, чтобы он мог быть достигнут только с переадресованным трафиком.


1

Сокат OpenWRT

Сокат уже был заявлен как ответ, однако указанный ответ не работал для меня на моей платформе OpenWRT с динамическим адресом WAN.

Моя цель - пересылать одноадресные UDP-пакеты пробуждения по локальной сети от UDP-порта 9 интерфейса WAN в широковещательную рассылку подсети 192.168.20.255.

Сломанный (iptables)

Я тоже пытался с iptables, но каждый раз, когда я добавляю правило, заканчивающееся на 255, правило превращается в кашу с адресом назначения 0.0.0.0, когда я печатаю с:

iptables -t nat -L

Я полагаю, что iptables не способен мультиплексировать трафик, как требуется для преобразования одноадресной и широковещательной передачи.

Плохое (фальшивые записи арп)

Подделка записей arp не так уж плоха, потому что пакеты попадают ко всем в сегменте Ethernet, но имеет следующие недостатки

  • Вы «потребляете» IP-адрес
  • IP-адрес назначения в пакете WoL неверен, даже если вы его получили, потому что MAC-адрес - это FFFF ...
  • IP-сбой может произойти, если кто-то в сети использует этот IP-адрес.
  • Это широковещательная рассылка Ethernet, а не IP-рассылка.

Примечание. Это можно сделать с помощью arpкоманды или ip neighкоманды.

Хорошо

Сокат, как указано в предыдущем ответе, задира. В предыдущем ответе на сокат я столкнулся с несколькими проблемами.

  1. Мой socat не переадресовывал трафик, когда в качестве пункта назначения широковещательной передачи UDP было 255.255.255.255. Я избежал этого, ограничив широковещательную подсеть той, которую я использую, возможно, безопаснее.
  2. Когда я установил адрес привязки 0.0.0.0, я столкнулся с широковещательным штормом из-за того, что трафик возвращался в socat из моей локальной сети. Сначала я решил эту проблему путем привязки к моим общедоступным ddns, однако это не идеально, поскольку ddns может быть недоступен, а мой динамически назначенный IP-адрес изменился.

Я смог привязаться к 0.0.0.0 (все адреса) и избежать широковещательного шторма, добавив правило iptables, чтобы блокировать возврат входящей трансляции обратно в socat со стороны локальной сети. Это правило, в дополнение к правилу iptables для приема трафика через UDP-порт 9 и правилу iptables для его регистрации, мы получаем три следующих правила в дополнение к команде 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 &

Для OpenWRTers достаточно вставить это в /etc/firewall.userи выпускать /etc/init.d/firewall restart.

Поздравляем, теперь вы должны иметь WoL, работающий на вашу сеть из любой точки сети.


0

На самом деле netfilter не может выполнять трансляцию, механизм маршрутизации делает это.

Но он отбрасывает любую переадресованную трансляцию по умолчанию.

Стало возможным переадресовывать направленную UDP-трансляцию в недавнем ядре Linux (около версии 5.0)

Вам необходимо изменить bc_forwardingпараметр для сетевого интерфейса вещания:

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

(Примечание: это кажется вариант net.ipv4.conf. Все .bc_forwarding не работает)

Так что теперь вам должно хватить ядра около 5.0+ iptables

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.