Служба обнаружения ssdp windows 10

Современные ОС предусматривают современные подходы ко многим привычным вещам, отказываясь от многих устаревших технологий. С одной стороны это правильно, с другой — может вызвать и вызывает проблемы в переходный период. Поэтому системный администратор всегда должен интересоваться всеми нововведениями используемых систем, а также уметь применять их на практике. Здоровый консерватизм — это хорошо, но он не должен препятствовать прогрессу. Сегодня мы поговорим об одной часто встречающейся проблеме — не включается сетевое обнаружение в последних версиях Windows 10 и Windows Server.

Онлайн-курс по устройству компьютерных сетей
На углубленном курсе «Архитектура современных компьютерных сетей» вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Долгое время взаимоотношения систем семейства Windows c сетевой безопасностью были достаточно сложными. Ситуация начала меняться с выходом Windows XP, в которой появился встроенный брандмауэр, начиная с Vista были введены ограничения для учетных записей пользователей и произошло разделение подключенных сетей на домашние, рабочие и общественные.

Причиной этому стало широкое распространение интернета и широкополосных сетей, когда постоянное подключение к сети стало из роскоши нормой жизни. За ними последовало развитие домовых и личных сетей и сегодня практически каждое устройство так или иначе подключено к какой-либо сети c обязательным выходом в интернет. Это заставило по-новому посмотреть на вопросы безопасности, в частности в сторону ужесточения политик по умолчанию. Вторая проблема — это старые, уязвимые протоколы, многие из которых поддерживались в угоду совместимости, но дальнейшее их применение ставило серьезные проблемы безопасности, обусловленные самой архитектурой этих протоколов.

В современных ОС все сети делятся на частные и общедоступные, любая неизвестная сеть по умолчанию определяется как общедоступная и для нее включаются повышенные меры безопасности. Частные сети предполагают больший уровень доверия и позволяют включить Сетевое обнаружение, которое позволяет текущему узлу находить другие компьютеры в сети и быть видному самому. Ранее за этот функционал отвечал протокол NetBIOS over TCP/IP, но он не удовлетворяет современным требованиям безопасности и поэтому от его применения начали отказываться. На смену ему пришел новый протокол SSDP (Простой протокол обнаружения сервисов, Simple Service Discovery Protocol), который является частью более широкого протокола UPnP (Universal Plug and Play).

Новые протоколы позволяют сетевым устройствам не только обнаруживать и взаимодействовать друг с другом, но и самостоятельно конфигурировать активное сетевое оборудование, например, пробрасывать нужные порты на роутере.

Но вернемся к озвученной в заголовке проблеме. Достаточно часто можно столкнуться с ситуацией, когда сетевое обнаружение в системах Windows не хочет включаться. При этом нет никаких сообщений об ошибках, вы вроде бы включаете сетевое обнаружение, но оно все равно оказывается отключенным.

Windows-cannot-turn-on-network-discovery-001.png

Причина такого поведения заключается в том, что старые службы (NetBIOS over TCP/IP) оказываются выключенными, а новые (SSDP и прочие) не включенными. Чтобы решить данную проблему нужно включить автоматический запуск и запустить в указанном порядке следующие службы:

  • Обнаружение SSDP — включает поддержку протокола SSDP
  • Узел универсальных PNP-устройств — включает поддержку UPnP
  • Хост поставщика функции обнаружения — отвечает за обнаружение других устройств в локальной сети
  • Публикация ресурсов обнаружения функции — обеспечивает видимость компьютера в локальной сети

Также удостоверьтесь что у вас работает и настроена на автоматический запуск служба:

  • DNS-клиент

Windows-cannot-turn-on-network-discovery-002.png

Теперь можно включить сетевое обнаружение и удостовериться что вам доступны ресурсы локальной сети.

Онлайн-курс по устройству компьютерных сетей
На углубленном курсе «Архитектура современных компьютерных сетей» вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Category:

  • Компьютеры
  • Cancel

Пвозившись со службами Windows, я искоренил данную проблему. Для тех, кто столкнется с проблемой сетевого обнаружения в семерке, я привожу небольшой алгоритм решения.
Для решения этой проблемы нужно включить следующие службы Windows 7 (10) в Панели управление — Администрирование:
— DNS-клиент (DNS Client)
— Обнаружение SSDP (SSDP Discovery)
— Узел универсальных PNP-устройств (UPnP Device Host)
— Публикация ресурсов обнаружения функции (Function Discovery Resource Publication)
— Сервер

— Рабочая станция

Панель управления => программы и компоненты => Включение или отключение компонентов Windows => Поддержка общего доступа к файлам SMB 1.0/CISF ставим галочку

После включения этих служб автоматически включится сетевое обнаружение.
Точно работает

Microsoft усилила безопасность и теперь, на сборке 1709, не работает безпарольное подключение по локальной сети к другим компьютерам, как было до этого.
Благодаря рекомендациям, я сделал так (лучше сделать ещё на сборке 1703, до обновления, но то же самое можно сделать и на сборке 1709).
1 — задал пароли всем Windows устройствам, с которыми будет локалка.
2 — зашёл в эти компы по сети с вводом логина и пароля.
3 — запустил программу Netplwiz.exe из папки Windows\System32.
4 — убрал галку «Требовать ввод имени пользователя и пароля» (чтобы после включения/перезагрузки/гибернации/спящего режима не вводить пароль входа каждый раз.
5 — там-же во вкладке «Дополнительно» нажал «Упраление паролями», далее «Учётные данные Windows» и убедился, что есть учётки других компов локальной сети.
Всё. Сетка работает.

Цитата с answers.microsoft.com:
«Решение:
1. Открываем Win+R (Пуск->Выполнить) и пишем gpedit.msc
2. Нам нужно найти «Конфигурация компьютера>Административные шаблоны>Сеть>Рабочая станция Lanmann» Параметр «Включить небезопасные гостевые входы» и выставить его в «Включено»

Однако, имейте в виду, что данное решение временное и не рекомендуется открывать доступ без проверки подлинности для кого угодно.»

Добавлено через 2 минуты
У меня 10 Про на сетевых ресурсах доступ по паролю — таких проблем нет. В «Включить небезопасные гостевые входы» параметр «Не задано».

Добавлено через 4 минуты
Ещё, если есть в журнале событий ошибки 1068, 1075: «в командной строке от Администратора Net stop p2pimsvc, затем в C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\PeerNetworking
удалить idstore.sst».

Добавлено через 48 секунд
Я до принтера расшаренного не мог «достучаться» при таких симптомах. Последний способ помог.

Discovers networked devices and services that use the SSDP discovery protocol, such as UPnP devices. Also announces SSDP devices and services running on the local computer. If this service is stopped, SSDP-based devices will not be discovered. If this service is disabled, any services that explicitly depend on it will fail to start.

Default Settings

Startup type: Manual
Display name: SSDP Discovery
Service name: SSDPSRV
Service type: share
Error control: normal
Object: NT AUTHORITY\LocalService
Path: %SystemRoot%\system32\svchost.exe -k LocalServiceAndNoImpersonation -p
File: %SystemRoot%\System32\ssdpsrv.dll
Registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SSDPSRV
Privileges:
  • SeChangeNotifyPrivilege
  • SeCreateGlobalPrivilege

Default Behavior

SSDP Discovery is a Win32 service. In Windows 10 it is starting only if the user, an application or another service starts it. When the SSDP Discovery service is started, it is running as NT AUTHORITY\LocalService in a shared process of svchost.exe along with other services. If SSDP Discovery fails to start, the failure details are being recorded into Event Log. Then Windows 10 will start up and notify the user that the SSDPSRV service has failed to start due to the error.

Dependencies

SSDP Discovery cannot be started under any conditions, if the following services are disabled, deleted or working improperly:

  • HTTP Service
  • Network Store Interface Service

While SSDP Discovery is stopped, the UPnP Device Host service cannot be launched.

Restore Default Startup Configuration of SSDP Discovery

Before you begin doing this, make sure that all the services on which SSDP Discovery depends are configured by default and function properly. See the list of dependencies above.

1. Run the Command Prompt as an administrator.

2. Copy the command below, paste it into the command window and press ENTER:

sc config SSDPSRV start= demand

3. Close the command window and restart the computer.

The SSDPSRV service is using the ssdpsrv.dll file that is located in the C:\Windows\System32 directory. If the file is removed or corrupted, read this article to restore its original version from Windows 10 installation media.

Что больше всего бесит при первом запуске устройств с управлением по Ethernet? Необходимость его искать в сети с использованием зоопарка из подходов. Тут используются программы автопоиска (например Winbox для MikroTik), дефолтные IP адреса (все эти 192.168.1.1, 192.168.100.1, 192.168.2.1 — кто во что горазд). Иногда надо со смартфона показывать QR коды в камеру устройства или передавать настройки тональными сигналами в микрофон. Мы задались целью найти стандарт для поиска устройств в сети и внедрить его в свои устройства на основе микроконтроллеров и/или одноплатных компьютеров. Это статья о стандартах, их особенностях, преодолённых трудностях и об открытом коде, который мы написали для себя и считаем лучшей в мире открытой реализацией SSDP сервера и клиента.

Почему Ethernet?

Кабельный Ethernet это прекрасный стандарт для индустриальных применений. Кабельное подключение надежнее беспроводного, кабели бывают с экраном, выпускаются индустриальные разъёмы RJ-45, соединение гальванически развязано (чрезмерно высокое напряжение может привести к поломке одного устройства в сети, но на другие не распространится). Соединение легко транслируется в оптоволокно медиаконвертерами, либо передаётся через коммутаторы, что обеспечивает большую дальность в интрасети, а при желании позволяет соединяться и на любой дальности по Интернету. Немаловажно, что сеть Ethernet скорее всего уже существует на объекте внедрения, так что затраты на создание канала управления минимальны. Про скорости передачи данных даже говорить не стоит. RS-232 и рядом не стоял. Ethernet почти всегда есть в одноплатных компьютерах, да и в микроконтроллеры его частенько встраивают, а иногда даже со встроенным PHY (https://www.ti.com/product/TM4C1294NCPDT).

Минусы у Ethernet тоже есть. Если в соединениях точка-точка, как в RS-232 или RS-485, пакет данных всегда будет доставлен, то в Ethernet доставка пакетов негарантированная. Либо, в случае использования поверх Ethernet протоколов гарантированной доставки (TCP), будет непредсказуемая задержка. С потерей пакетов можно бороться, используя оборудование с заведомо большей пропускной способностью, чем теоретическая пиковая нагрузка. А еще одним минусом Ethernet является плохая предсказуемость адресов устройств (что MAC, что IP) и сложная диагностика отказов связи (тут RS-232 сильно выигрывает).

  1. Начнём с MAC адреса. Например, у каждого устройства должен быть уникальный MAC адрес для приёма и передачи пакетов в пределах подсети. Встречал я китайские устройства с одним MAC адресом на всю серию. Это не создаёт проблем, пока вы используете одно такое устройство, но после включения второго, как-то всё перестаёт работать. Простого пользователя такая история ставит в тупик.

  2. Если с MAC адресами производитель не накосячил и хотя бы сгенерировал их для каждого устройства случайными в рамках стандарта, то следующий уровень адресации это IP адрес (здесь и далее я буду говорить только об IPv4). И тут снова не предсказать условия эксплуатации. В обычных пользовательских сетях принято использовать DHCP сервер, который выдаст адрес автоматически (а также маршруты, сервер времени NTP, сервер DNS и т.п.). Это очень удобно, но узнать-то адрес как? Мы, например, раньше ходили на сервер к dhcpd и смотрели там недавно выданные lease. Еще сканировали сеть с помощью nmap, а потом включали и выключали устройство и смотрели какой адрес появляется и исчезает. Так себе методы.

  3. Но если сеть индустриальная, то часто DHCP сервер не используется и IP адреса нужно назначить каждому устройству вручную. Заранее производителю оборудования совершенно непонятно, будет ли устройство в сети 192.168/16, 10/8, 172.16/20 или любой более узкой подсети. Поэтому без DHCP любой статический адрес, заданный по-умолчанию в устройстве, маршрутизироваться почти наверняка не будет.

В итоге самым распространённым способом уже 20 лет было назначать дефолтный IP адрес, писать его в инструкции, заставлять пользователя менять настройки своей сети (IP, маска подсети), через админку менять настройки сети устройства, восстанавливать настройки пользователя, profit. Однако, поскольку задача поиска устройств в сети довольно распространенная, то она была решена многими производителями самостоятельно. Например, в ПО Winbox для MikroTik есть механизм поиска устройств даже в другой подсети; в протоколе GigЕ Vision также есть механизм поиска устройств в сети, но только в той же; и т.д. Мы тоже в своё время сделали свой примитивный протокол обнаружения устройств через broadcast запрос на определённый порт и ожидание unicast ответа.

Напрашивается мысль, что должен существовать относительно универсальный протокол поиска и настройки сетевых устройств. И лучше использовать его, чем строить очередной велосипед.

Выбор протокола обнаружения устройств

Сразу скажу, что мы хотим охватывать мир Windows, Linux и Mac. Поэтому нам не подходят Mac only решения, где в рамках замкнутой экосистемы всё работает само. Не подходят решения, основанные на закрытом коде, чтобы не получить vendor lock. Нужно легковесное решение, которое реально реализовать в микроконтроллере. Сам поиск нужно уметь встраивать в наш софт, но будет хорошо, если операционная система тоже умеет устройство обнаруживать.

Удалось найти несколько относительно стандартных и распространенных протоколов:

  • mDNS (multicast, zeroconf, avahi): https://datatracker.ietf.org/doc/html/rfc6762, https://datatracker.ietf.org/doc/html/rfc6763

  • SSDP как часть UPnP (multicast, HTTP): https://web.archive.org/web/20151107123618/, http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v2.0.pdf

  • SLP (UDP multicast): https://docs.oracle.com/cd/E19455-01/806-1412/806-1412.pdf

Было решено попробовать найти и запустить примеры для каждой из перечисленных выше технологий обнаружения.

С SSDP/UPnP всё пошло неплохо. Достаточно быстро нашёлся пример сервера, который запускаются и обнаруживаются стандартными средствами Windows (https://github.com/ZeWaren/python-upnp-ssdp-example), пример с клиентом и сервером, которые можно запустить, как на Windows, так и на Linux и они находят друг друга (https://github.com/MoshiBin/ssdpy), готовые библиотеки с примерами для C (http://miniupnp.free.fr) и Python (https://pypi.org/project/ssdpy/), а самое главное стандарт, написанный понятным языком с пояснениями и примерами (http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf).

Для поиска на базе mDNS тоже нашлись какие-то примеры. Но работали они менее стабильно. В нашей сети есть несколько сетевых принтеров. И с помощью найденных примеров их обнаружение носило вероятностный характер. С чем было связано обнаружение или необнаружение устройств, быстро понять не удалось. Также выяснилось, что встроенная поддержка mDNS появилась только в Windows 10. Для Windows 7 придётся вручную ставить Apple Bonjour или какие-то другие дополнительные компоненты (https://www.chiefdelphi.com/t/enable-mdns-on-windows/155295). Но даже в Windows 10 в зависимости от наличия обновлений поддержка может быть не полной и нацелена в основном на поиск сетевых принтеров (https://en.wikipedia.org/wiki/Multicast_DNS, https://learn.microsoft.com/en-us/answers/questions/266761/does-windows-10-support-mdns, https://superuser.com/questions/1330027/how-to-enable-mdns-on-windows-10-build-17134). Вдобавок ко всему описание mDNS в виде «машинописных» RFC (https://datatracker.ietf.org/doc/html/rfc6763) субъективно менее приятно в работе по сравнению с описанием UPnP.

Первые две технологии достаточно популярны. В интернете для них можно легко найти примеры, библиотеки и обсуждения проблем. SLP на их фоне выглядит гораздо скромнее. В частности, по запросу «Service Location Protocol library» первой ссылкой у нас вышел пакет pyslp для python с полностью отсутствующим описанием: https://pypi.org/project/pyslp/ Документация потом нашлась https://pythonhosted.org/pyslp/ Но при попытке запуска примера он упал с ошибкой `local variable ‘error_code’ referenced before assignment`. После некоторых доработок примеры запустились, но сервера, расположенный дальше localhost всё-равно найти не получилось. Стоит отметить что для SLP есть и другие библиотеки с примерами и относительно неплохое описание стандарта (https://docs.oracle.com/cd/E19455-01/806-1412/806-1412.pdf). Но время на исследование у нас было ограничено. Поэтому мы решили остановить свой выбор на SSDP / UPnP.

SSDP

SSDP это Simple Service Discovery Protocol, но есть и другая расшифровка: Stupidly Simple DDoS Protocol (https://habr.com/ru/articles/332812/) из-за его подверженности amplification DDoS attack.

Обнаружение устройств делается в 2 этапа (M-SEARCH и HTTP):

Сначала клиент SSDP посылает специальный поисковый UDP-запрос M-SEARCH выделенному мультикастному адресу на конкретный SSDP-порт 239.255.255.250:1900 с заданным форматом пакета, в который входят следующие строки:

  • M-SEARCH * HTTP/1.1обязательная строка в начале запроса

  • HOST:239.255.255.250:1900поле содержит мультикастный адрес и порт, зарегистрированные в Internet Assigned Numbers Authority

  • MAN:»ssdp:discover»должен иметь такое значение

  • MX:2время ожидания ответа в секундах; может принимать целочисленные значения между 1 и 5 включительно; ответ устройства должен иметь задержку на случайное время от 0 до MX секунд

  • ST:upnp:rootdeviceцель поиска; в протоколе UPnP указаны варианты значений этого поля, от которых зависит процесс формирования ответа устройств и то, какие устройства в принципе будут на него отвечать

  • в конце запроса должна быть пустая строка

Этот M-SEARCH запрос пересылается всем участникам мультикастной группы, которые слушают адрес 239.255.255.250 на 1900 порту, после чего все устройства, которые подпадают под условия поиска (входят в группу устройств, запрошенных в поле ST), должны сформировать ответ и отправить его юникастной посылкой UDP-пакета на адрес и порт устройства клиента, который делал изначальный M-SEARCH запрос. Формат пакета с ответом с учетом только обязательных полей будет состоять из следующих строк:

  • HTTP/1.1 200 OK — обязательное поле; обязательная строка в начале

  • CACHE-CONTROL:max-age=1800 — обязательное поле; максимальное время валидности ответа в секундах; минимум 1800 секунд

  • DATE: дата формирования ответа — необязательное поле; дата формирования ответа на запрос

  • EXT: — пустое поле для обратной совместимости с версией протокола UPnP 1.0

  • LOCATION: http://192.168.4.207:8088/jambon-3000.xml — обязательное поле; URL расположения описания этого устройства

  • SERVER:unix/5.1 UPnP/2.0 MyProduct/1.0 — обязательное поле; строка в формате: OS name/OS version UPnP/2.0 product name/product version

  • ST:upnp:rootdevice — обязательное поле; ответ устройства на цель поиска; ответ зависит от запроса, на upnp:rootdevice однократный upnp:rootdevice

  • USN:uuid:device-UUID::upnp:rootdevice — обязательное поле; Unique Service Name, задаёт уникальное имя устройства на основе его UUID, которое может быть сгенерировано любым подходящим алгоритмом

  • BOOTID.UPNP.ORG:0 обязательное поле; содержит в себе число, которое должно увеличиваться каждый раз, когда устройство повторно подключается к сети и отправляет начальное уведомление — «перезагрузка» в терминах UPnP

Следующим этапом для получения более полной информации об устройстве может идти обычный HTTP-запрос XML-файла из поля LOCATION, в котором должна содержаться более развернутая информация об устройстве. Основные поля в данном XML-описании следующие:

  • <root> раздел — обязателен:

    • <device> раздел — обязателен:

      • <deviceType> — обязательное поле; тип UPnP устройства в формате urn::schemas-upnp-org:device:deviceType:ver, где deviceType — стандартизированное название типа устройства (как правило, для обычных устройств это Basic, а некоторые другие значениями можно посмотреть здесь), ver — максимальная поддерживаемая версия устройства

      • <friendlyName> — обязательно поле; понятное имя устройства

      • <manufacturer> — обязательное поле; название производителя

      • <manufacturerURL> — разрешенное поле; веб-страница производителя

      • <modelDescription> — рекомендованное поле; описание модели устройства; может быть длиной < 128 символов

      • <modelName> — обязательное поле; название модели

      • <modelNumber> — рекомендованное поле; номер модели

      • <modelURL> — разрешенное поле; веб-страница модели

      • <serialNumber> — рекомендованное поле; серийный номер устройства

      • <UDN> — обязательное поле; Unique Device Name, уникальное имя устройства, uuid:device-UUID; device-UUID должен совпадать с переданным в поле USN в ответах на M-SEARCH и NOTIFY-уведомлениях

Альтернативным способом для первого этапа является рассылка уведомлений устройством о своём присутствии в сети (NOTIFY). Однако вместо мультикаст запроса M-SEARCH с клиента и юникаст ответа от сервера в данном случае предполагается периодическая отправка NOTIFY-пакетов самим SSDP-устройством на мультикастный SSDP-адрес 239.255.255.250:1900 и постоянное прослушивание клиентом рассылки в мультикастной группе. Формат NOTIFY-пакета состоит из следующих строк:

  • NOTIFY * HTTP/1.1 — обязательное поле; строка должна быть в начале каждого NOTIFY-уведомления

  • HOST: 239.255.255.250:1900 — обязательное поле; SSDP мультикастный адрес и порт

  • CACHE-CONTROL: 1800 — обязательное поле; максимальное время валидности ответа в секундах; минимум 1800 секунд

  • LOCATION: — обязательное поле; URL расположения описания этого устройства

  • NT: — обязательное поле; тип устройства, которое посылает NOTIFY-уведомление

  • NTS: ssdp:alive — обязательное поле; тип NOTIFY-объявления; может быть ssdp:alive (при добавлении в сеть и при истечении времени в CACHE-CONTROL), ssdp:byebye (при отключении из сети), ssdp:update (при изменении свойств)

  • SERVER: unix/5.1 UPnP/2.0 MyProduct/1.0 — обязательное поле; строка в формате: OS name/OS version UPnP/2.0 product name/product version

  • USN:uuid:device-UUID::upnp:rootdevice — обязательное поле; Unique Service Name, задаёт уникальное имя устройства на основе его UUID, которое может быть сгенерировано любым подходящим алгоритмом

  • BOOTID.UPNP.ORG: — обязательное поле; содержит в себе число, которое должно увеличиваться каждый раз, когда устройство повторно подключается к сети и отправляет начальное уведомление — «перезагрузка» в терминах UPnP

  • CONFIGID.UPNP.ORG: — обязательное поле; число, определяющее номер конфигурации

  • SEARCHPORT.UPNP.ORG: — необязательное поле; номер порта, с которого устройство будет отвечать на юникастный M-SEARCH; может быть отличным от 1900 только если 1900 порт недоступен

Может взять готовые инструменты?

Выбрав SSDP протокол, мы продолжили тестирование готовых инструментов для SSDP, которые делятся на программы поиска по SSDP (клиент), а также программ эмуляции устройств, отвечающих по SSDP (сервер). Стало сюрпризом, что чаще всего они несовместимы между собой. Многие авторы воспринимают SSDP, как HTTP notify поверх UDP Multicast на 239.255.255.250:1900, а дальше – кто во что горазд. Ниже идёт сводная таблица наших экспериментов с клиентами, где мы отбирали только те, что написаны на С/С++ и Python, имеют открытый код, а еще добавили встроенный инструмент Windows. Внизу добавили сравнение с тем инструментом, который написали мы:

Во-первых, почти все клиенты делятся на 2 группы. Те, кто останавливается на стадии M-SEARCH и не запрашивает XML конфигурацию на стадии HTTP. И те, кто наоборот игнорирует устройство, если на M-SEARCH оно ответило, а по HTTP — нет. Исключением оказался пакет upnpy поверх которого мы быстро написали клиентскую утилиту. Но функций для доступа ко всем полям XML описания там нет. Чтобы это исправить придётся самостоятельно парсить XML.

Отдельной проблемой оказался выбор сетевого интерфейса, на котором работает сервер. Счастливы неведующие, у которых такой интерфейс один. Но в случае нескольких интерфейсов (Ethernet, WiFi, …) логично сканировать их все. Кстати Windows так и делает. Вместо этого часто предлагалось выбирать конкретный интерфейс или довериться автовыбору. В пакете upnpy выбрать интерфейс вообще нельзя (мы не нашли как).

Кроссплатформенность встречалась тоже редко. Тут лидером является библиотека miniupnp и их клиент miniupnpc. Они единственные охватили большую тройку Win/Lin/Mac. Но в своей серверной части Windows они уже не поддерживают.

Кроссплатформенность и выбор сетевых интерфейсов это не так просто. Если сервер подписывается на мультикастную группу со всех адаптеров компьютера, подобный код не получается автоматически кроссплатформенным, так как процедура подписи в Linux должна проводиться с помощью использования группы 0.0.0.0, а в Windows с помощью явного перебора всех сетевых адаптеров и подписи с их реальным IP-адресом. В своём коде сервера мы сделали ответ по всем интерфейсам, а вот в доступных в интернете примерах это не всегда поддерживалось.

А вообще, чего хочется от клиента поиска устройств по сети? Чтобы нашел по-максимуму. Чтобы искал быстро. Чтобы был доступ ко всей информации, а не только IP адрес и имя. Но и тонуть в информации о разных uuid:device-UUID не хочется. Кроссплатформенности хочется, чтобы можно было эту утилиту предлагать широкому кругу пользователей для поиска сделанных тобой устройств. Ну и тогда уж графический режим нужен. И тут лучше посмотреть своими глазами, кто как реализовал UX.

Windows тут стоит поставить на первое место. Microsoft прорабатывает свои решения. Но средств диагностики обычно не закладывает. В итоге сетевое окружение Windows, выступая, как клиент, показывает устройство в сетевом окружении, только если пройдены оба этапа обнаружения и XML файл содержит поле <deviceType>, а отсутствие остальных обязательных полей прощает. Зато показывает и иконку, и подробную информацию по запросу, и информация структурирована.

Сетевое окружение в Windows находит наш сервер SSDP и показывает его свойства

Сетевое окружение в Windows находит наш сервер SSDP и показывает его свойства

gssdp-discover это утилита линуксоида. Минимум информации, консоль. HTTP предлагается запрашивать самостоятельно.

Утилита gssdp-discover выводит информацию о найденных устройствах

Утилита gssdp-discover выводит информацию о найденных устройствах

miniupnpc недалеко ушло от gssdp-discover.

miniupnpc выводит информацию о найденных устройствах

miniupnpc выводит информацию о найденных устройствах

ssdp гораздо лучше для диагностики, так как выводит всю информацию. Тоже без HTTP уровня. Но нужно учесть, что без установленного в системе Python 3.8 или выше, последняя версия ssdp работать не будет. А более ранние версии сильно отличаются по функциям. Не надо думать, что это не проблема. Сейчас 2025 год, а клиенты продолжают спрашивать работает ли наш софт на WinXP и на Python 3.4. Так что наша реализация клиента, например, сделана для Python 3.6 и выше.

ssdp показывает полную информацию из M-SEARCH уровня поиска

ssdp показывает полную информацию из M-SEARCH уровня поиска

В UPnP Scanner совсем другой подход. Это Windows решение. Графический интерфейс. Выводится вся информация. Очень похоже на встроенное сетевое окружение Windows с GUI начального уровня, но зато доступны исходные коды. К сожалению есть еще отдельная проблема с версиями UPnP. В версиях UPnP 2.0 в XML описании не должно присутствовать поле URLBase, но для предыдущих версий UPnP оно могло присутствовать и использовалось, как абсолютный URL, к которому добавляется относительный путь presentationURL. В итоге UPnP Scanner считает невалидными и не показывает все устройства, которые соответствуют UPnP 2.0 и выше.

UPnP Scanner близок к встроенному в Windows сетевому окружению

UPnP Scanner близок к встроенному в Windows сетевому окружению

ssdpy-discover. Мы тестировали на Windows и запускали клиента через client.py. Вывод похож на другие подобные консольные утилиты. Но основные поля есть, а второстепенные отфильтрованы.

ssdpy клиент похож на другие консольные утилиты M-SEARCH уровня

ssdpy клиент похож на другие консольные утилиты M-SEARCH уровня

upnpy. Про эту библиотеку я уже писал выше. Она найдёт устройства на обоих уровнях поиска, но не позволит выбрать интерфейс поиска. Также клиент придётся писать самостоятельно, а доступ ко всем информационным полям устройства можно сделать через парсинг XML. Мы этого делать не стали. На скриншотах видны поля, где доступ был встроенный в библиотеку.

Клиент, написанный нами для upnpy неплох, но тоже сложен для пользователя

Клиент, написанный нами для upnpy неплох, но тоже сложен для пользователя

ssdp-scan отличается тем, что умеет собирать NOTIFY сообщения. Правда занимать это может много времени. M-SEARCH он тоже умеет и быстро строит список в консоли Linux. Информация в нём скудная.

Немногословный ssdp-scan

Немногословный ssdp-scan

Серверов мы нашли меньше, чем клиентов. Это неудивительно, ведь они больше нужны производителям оборудования, как мы. Ниже сводная таблица наших экспериментов с серверами и наша реализация для сравнения:

Все сервера умеют отвечать на M-SEARCH. Все сервера, кроме ssdpy-server, умеют отвечать на HTTP стадии и обнаружились у нас средствами Windows. А ssdpy-server у нас обнаруживался только тем клиентом, что входит с ним в одну библиотеку. Несмотря на обнаружение в Windows, чаще всего реализация стандарта полей XML описания в серверах была неполной. С кросплатформенностью еще хуже. Нужной нам тройки Win/Lin/Mac никто не собрал.

Найти всегда

Итак, есть много частично работающих готовых реализаций сервера и клиента, написанных под разные ОС, написанные на разных языках (нас волновал и Си, и Python). Если их скомбинировать, поотлаживать сниффером Ethernet, например Wireshark, а также почитать различные RFC, то можно довести клиент и сервер до совершенства, а дальше встраивать сервер в одноплатники и микроконтроллеры, а клиент — выдавать пользователям.

Однако одна из наших целей, чтобы устройство обнаруживалось всегда. Даже, когда в нём неизвестные статические настройки сети. А описанный выше способ поиска принципиально не может работать для случая, когда маски подсети на клиенте и на сервере разные. Сервер сможет получить от клиента мультикаст M-SEARCH запрос благодаря магии мультикаста, но ответ будет через UDP unicast, который не способен дойти до клиента в другой подсети. Однако эта проблема оказалась решаема в рамках стандарта SSDP. Мы используем вторую часть SSDP — advertisement с помощью NOTIFY сообщений. Стандарт не запрещает добавлять собственные поля, где мы передаём информацию о текущих сетевых настройках. Сообщения NOTIFY идут на мультикастный SSDP-адрес, поэтому они доходят от сервера до клиента вне зависимости от того, в какой подсети они находятся. Однако вместо периодической отсылки NOTIFY мы делаем их отсылку вслед за получением M-SEARCH. То есть запрос по multicast и ответ по multicast. Таким образом, мы гарантируем, что полный список найденных устройств будет готов через 2 секунды после запроса на клиенте, а не отловом случайных нотифаев раз в 1800+ секунд. Мы не знаем кого-то еще, кто додумался до такого приёма с SSDP.

DHCP и AutoIP

Отдельно нужно рассмотреть случай, когда в устройстве стояло автоматическое определение настроек сети (DHCP). Если DHCP сервер недоступен или отсутствует, то устройство окажется вообще без подсети и без сетевых настроек. И тут нам на помощь приходит AutoIP.

AutoIP базируется на стандарте RFC 3927 и присваивает устройству случайный, равновероятный IP-адрес из выделенной подсети 169.254.1.0-169.254.254.255. Мы генерируем его на основе MAC-адреса устройства, что тоже допустимо. AutoIP включается после нескольких неудачных попыток получить сетевые настройки от DHCP сервера. Диапазон адресов AutoIP считается всегда входящим в подсеть IPv4. Таким образом, пакеты на эти адреса направляются адресату в локальной сети напрямую, а не на шлюз, который вообще может отсутствовать. По-простому это означает, что два компьютера с поддержкой AutoIP (Windows, например), могут включить автоматическое определение настроек, не получить их от DHCP сервера, но, тем не менее, присвоить себе 2 разных IP адреса и быть связанными на L3 уровне. Всё это важно понимать для реализации в микроконтроллере, так как в Windows/Linux эти механизмы включены по-умолчанию. В микроконтроллерной библиотеке lwIP уже поддерживался механизм AutoIP, поэтому главное было включить его и понимать почему и как он работает.

Beyond SSDP

Теперь мы можем находить свои устройства вне зависимости от их сетевых настроек, но только на стадии M-SEARCH/NOTIFY. Стадию HTTP провести невозможно, если устройства находятся в разных подсетях. Поэтому сменить IP адрес стандартным способом через админку не получится. Как же установить новые настройки найденному устройству? Для этого мы снова использовали свойство M-SEARCH и NOTIFY пакетов, что в них можно дописывать новые поля. Неизвестные поля по стандарту отбрасываются. Мы же добавляем поддержку этих полей и прописываем туда IP/маску подсети, шлюз и флаг включения DHCP. Если наше устройство получает через мультикаст сетевые настройки, то оно их применяет. Теперь мы можем не только всегда найти своё устройство, но и сразу вбить ему новые настройки, несмотря на то, что устройство может быть в другой подсети и недоступно по UDP/TCP. Да, это функция будет работать только для нашей реализации сервера в микроконтроллере и для одноплатников (pyssdp_server) и только через клиент (revealer), который мы написали. Но по всем остальным функциям SSDP совместимость сохраняется.

Тут еще возникает вопрос безопасности. Коллега может по незнанию, неосторожности или ради шутки поменять сетевые настройки и устройство перестанет быть доступно из управляющей программы, что выведет из строя всю систему, куда устройство интегрировано. Придётся звать настройщика, что обычно означает задержку в работе на часы или на дни. Поэтому добавляем защиту паролем с возможностью его смены. Добавляем альтернативный сервисный пароль, который вычисляется секретным алгоритмом на основе серийника, неизвестен пользователю, и является fallback вариантом, когда пользователь пароль поменял, но забыл. Тогда пароль под конкретный серийник можно запросить в техподдержке. Всё это работает без шифрования и не претендует на секьюрность, так как располагается, как правило, в закрытой сети.

Сделали ли мы неубиваемую схему? Почти. Какой IP нельзя ставить на интерфейсе, чтобы не сломать связь с ним? Это вообще хороший вопрос для собеседования на сисадмина. Кто-то вспомнит про популярный IP localhost (127.0.0.1). Но вряд ли многие знают про диапазоны 0.0.0.0/8 и 127.0.0.0/8. Также к запретным IP был добавлен весь мультикаст 224.0.0.0/4. Вот теперь не сломаешь.

Реализация в микроконтроллере

Мы используем микроконтроллер Texas Instruments TM4C1294KPDT. Довольно уникальным свойством этого семейства является встроенный Ethernet PHY, что позволяет подключать микроконтроллер ножками напрямую на разъём Ethernet (со встроенными трансформаторами). Для этого микроконтроллера производитель даёт примеры, реализующие UDP сокет, а также HTTP сервер. Работает это всё поверх стека lwIP (lightweight Internet Protocol) версии 1.4.1, адаптированного для TI контроллеров с использованием FreeRTOS или без него. Этих примеров достаточно, чтобы написать свою небольшую реализацию SSDP сервера с ответом на M-SEARCH запросы, на запрос XML-файла и посылку NOTIFY пакетов. Писать реализацию с нуля было бы очень накладно.

Забавно, что Texas Instruments предлагает в SDK свою утилиту поиска микроконтроллеров в сети, не являющейся реализацией одного из стандартных протокола поиска. То есть это очередной велосипед, основанный на broadcast, в ответ на который присылается IP адрес, MAC адрес, идентификатор платы, тип платы, название приложения, версия прошивки.

С микроконтроллерами всё не так просто. Поэтому пришлось решить несколько проблем интеграции lwIP в нашу прошивку.

Например, сначала мы вызывали методы lwIP из тех прерываний, где нам было это удобно, но иногда получали сбои. А затем мы прочитали, что библиотека lwIP не является потокобезопасной. То есть все вызовы её методов должны идти последовательно, быть сериализованы.

А еще у нас не получалось сменить настройки сети на автоматические (DHCP), если текущий шлюз был не из той подсети, откуда приходит запрос на смену настроек. Комбинация странная. А причина оказалась в нехватке памяти микроконтроллера на то, чтобы одновременно ответить через несуществующий шлюз и создать нужное количество запросов к DHCP. AutoIP в такой ситуации тоже не срабатывал. Увеличили память — проблема ушла.

Сервер на ПК pyssdp_server

Микроконтроллерную реализацию сервера показывать довольно бессмысленно. Она завязана на конкретный чип и FreeRTOS. А вот реализацию сервера для компьютера мы вывесили в открытый доступ: https://github.com/EPC-MSU/pyssdp_server Это кроссплатформенное Win/Lin/Mac приложение для Python 3.6+, распространяемое в исходных кодах. За основу мы взяли https://github.com/ZeWaren/python-upnp-ssdp-example, который был существенно переработан, чтобы он обнаруживался в сети более стабильно и для всех сетевых интерфейсов, поддерживал обнаружение из другой подсети, поддерживал смену настроек сети через наше расширение SSDP, поддерживал HTTP сервер с переадресацией, выделение настроек в конфиг, скрипты инсталляции для systemd и т.п.

Что в итоге получилось? Получилось серверное приложение, которое через релиз в виде zip архива или через git копируется на любой одноплатник (а можно компьютер с Windows или macOS), в нём меняется файл конфига на вашу информацию (название устройства, ссылки на компанию и на продукт, имя производителя и т.д.), далее сервер запускается и ваше устройство появляется в сетевом окружении Windows, ищется через любую программу поиска из таблицы выше, ищется через наш клиент (https://github.com/EPC-MSU/revealer) в других подсетях. При клике на найденное устройство обычно открывается его HTML страница, которая обслуживается встроенным HTTP сервером, использующимся и для отсылки XML описания устройства. Файлы HTML можно поменять на свои и получить полноценный статический встроенный сайт (серверные скрипты не поддерживаются). Для того чтобы серверное приложение работало и после перезагрузки, есть готовый скрипт инсталляция сервера в виде systemd сервиса.

Кто регулярно превращает свои программы в сервисы, стартующие при загрузке компьютера, знает, как много может пойти не так. Наш pyssdp_server оказался не исключением. Проблему того, что сетевой интерфейс может быть не готов к открытию в нём соединений, мы предусмотрели. Сервер ожидал хотя бы одного активного сетевого интерфейса. Но когда интерфейсов 2, то сервер норовил стартовать, как только поднимется хотя бы один из них. В итоге все остальные сетевые интерфейсы не обнаруживались, пока не перезапустишь pyssdp_server. Пришлось делать фоновое отслеживание сетевых интерфейсов. Теперь, если к проводному Ethernet вдруг добавится WiFi или VPN, то обнаружение будет работать и на нём.

Неожиданный нюанс, с которым мы столкнулись, что иногда на наших одноплатниках уже работает встроенная админка на 80 порту. А HTTP сервер, встроенный в SDDP, выделен на порт 5050. И хотелось бы, чтобы при клике на устройство, например в сетевом окружении Windows, открывалась именно встроенная админка. То есть хочется, чтобы presentationURL указывал на один порт, а Location — на другой. Однако в стандарте UPnP считается, что presentationURL должен быть на том же адресе и порту, что и Location поле. Пришлось это обходить через включаемый в конфиге Redirect со встроенного HTTP сервера на нужный порт главной админки.

Во время тестов мы запускали сервер и клиент на одном компьютере и получали ошибку, что порт 1900 уже занят. Логично, ведь и сервер, и клиент слушают порт 1900, чтобы получать M-SEARCH и NOTIFY пакеты. И тут мы видим, что Windows прекрасно находит наш сервер на этом же компьютере, слушая тот же порт 1900. Как? А так — оказывается можно слушать один порт несколькими приложениями. Для этого есть флаги сокета SO_REUSEADDR и SO_REUSEPORT (их различия описаны вот тут сразу после слов «Welcome to the wonderful world of portability…» https://stackoverflow.com/questions/14388706/how-do-so-reuseaddr-and-so-reuseport-differ). Да, поведение флагов не кроссплатформенное. В Windows SO_REUSEADDR включает в себя поведение SO_REUSEPORT (за исключением старых версий до 2003), а в Linux флаг SO_REUSEPORT, без которого одновременные подключения не возможны, был добавлен на версиях >=3.9. Причем в линуксе приходящие requests будут распределены между открытыми подключениями, а в Windows первое подключение будет основным, а остальные ждут в резерве.

В итоге мы сделали, чтобы несколько экземпляров клиентского приложения могли работать одновременно на одном компьютере, да еще и с запущенным там же сервером SSDP. Но вот 2 сервера одновременно запретили как раз через флаги SO_REUSEADDR и SO_REUSEPORT, так как компьютер не должен идентифицировать себя двумя способами одновременно. Несмотря на то, что все клиенты слушают один порт, каждый из них получает свой список устройств и не получает пакеты, предназначенные для другого клиента. Дело в том, что HTTP ответ же идёт через unicast, где указывается порт, а unicast порты у клиентских приложений различаются. Порт 1900 используется в SSDP только для мультикаста.

Естественно мы добавили не только поиск из другой подсети, но и возможность смены настроек, чтобы работало не хуже микроконтроллеров. И тут две проблемы. Во-первых, нужно знать на каком сетевом интерфейсе меняем настройки, если их несколько. У микроконтроллера интерфейс-то один. С этим оказалось всё легко. Сервер слушает и отвечает сразу по всем интерфейсам. При этом он использует разные UUID. Поэтому запрос на смену настроек мы привязали к интерфейсу. А во-вторых, чудесный мир кроссплатформенности… Мы же хотим менять настройки на Win/Lin/Mac, а одних видов Linux существует порядка 1000 (https://habr.com/ru/companies/lanit/articles/562484/). И для каждого есть еще разные по времени версии релизов. Как тут написать единый код смены сетевых настроек? Поэтому мы пошли следующим путём: полученные настройки передаются в консольный скрипт параметрами. Скрипт, работающий на более-менее всех современных Линуксах мы написали. А если нужен скрипт для Windows, хитрого Linux или Mac, то его может написать пользователь сам. Да и вообще он сможет в скрипте кастомизировать реакцию на такое важное событие, как смена сетевых настроек.

В Windows вскрылся еще ряд странностей. Во-первых, нужно отключить брандмауэр или не будет работать отсылка и получение мультикаст пакетов из другой подсети. А ведь это важное и ценное свойство SSDP, чтобы можно было всегда найти устройство. Но внутренняя жизнь сети в Windows оказалась еще сложнее. Если запустить pyssdp_server на компьютере с WiFi и проводным адаптером Ethernet, то обнаружение по проводу работает всегда. А по WiFi оно работает только первые 10 секунд после вставления или вынимания кабеля Ethernet. То есть, изменение линка на одном из адаптеров прочищает WiFi адаптер на 10 секунд и он ловит поисковые запросы. А потом перестаёт. И Wireshark не показывает больше приходящие multicast запросы. Поиском нашлась похожая проблема (https://community.intel.com/t5/Wireless/Intel-WiFi-chips-are-blocking-multicast-after-resuming-from/td-p/684849):

I believe that once the NIC/Windows is in this deprecated state the issue lies with the NIC/Windows not properly using IGMP to indicate the client is interested in receiving traffic from the mDNS multicast groups.

IGMP is used by networking hardware (APs/Switches) to figure out which clients are interested in the multicast traffic being broadcasted.

If the AP that sits between the clients does not see the IGMP join message coming from the client it won’t forward multicast traffic for that IGMP group to that client, since it doesn’t know that the client is «interested» in receiving that multicast traffic.

То есть точка доступа WiFi может считать, что мы не хотим получать мультикасты по WiFi, так как на низкоуровневом протоколе IGMP, используемом для управления мультикастными подписками, мы не сообщили ей такой трафик нам пересылать. И причина может быть в некорректном использовании IGMP в Windows или в сетевом адаптере. Дальше я решил не копать.

Наш клиент Revealer

В клиентском приложении хотелось достичь кроссплатформенности Win/Lin/Mac, которой нет ни у кого из готовых приложений. Хотелось соответствия стандарту SSDP, которая в примерах из интернета встречается редко. Хотелось выводить все информационные поля из стандарта на обеих стадиях обнаружения устройств (M-SEARCH и HTTP), что тоже делают нечасто. Для отладки нужно видеть все данные, а не их обрывочные представления. Например, в нашем приложении мы увидели, что одно из устройств Zyxel на M-SEARCH стадии передаёт строку SERVER с пробелом в одном из полей, что приводит к её некорректному распознаванию и в Windows устройство не показывается. Мы, кстати, про проблему с пробелами указываем в комментариях конфига, идущего в комплекте с pyssdp_server. Хотелось графического режима для того, чтобы приложение было удобно обычным пользователям. В итоге получилось вот так:

Главное окно Revealer

Главное окно Revealer

Приложение с одной кнопкой и найденными устройствами, на которые можно кликать. Если нажать на значок информации, то откроется окно с полями структур описания устройства:

Окно свойств отдельного устройства с секциями информации из M-SEARCH и HTTP стадий поиска

Окно свойств отдельного устройства с секциями информации из M-SEARCH и HTTP стадий поиска

Вверху поля HTTP стадии. Внизу поля M-SEARCH стадии. Если нажать на значок шестерёнки, который появляется только для устройств с поддержкой наших расширений протокола SSDP, то появляется окно с установкой сетевых настроек:

Окно установки сетевых настроек через наше расширение M-SEARCH запросов

Итог

Я считаю, что у нас получилась лучшая в мире открытая кроссплатформенная реализация SSDP клиента и сервера. У неё низкий порог входа. Поэтому я мимоходом поставил pyssdp_server и на свой компьютер для домашнего кинотеатра. Самое долгое было заполнять конфиг желаемыми строчками текста. Теперь я не буду вспоминать его IP, когда захочу зайти на него по ssh.
Клиентское приложение Revealer не только используется для поиска наших устройств, но и показывает некоторые принтеры, IP камеры, виртуальные машины, в которых поддерживается SSDP. Некоторые наши клиенты начинают волноваться, когда понимают, что их сетевая инфраструктура себя неплохо анонсирует в сети. Статья написана для того, чтобы сберечь время тем, кто хочет сделать свои устройства обнаружимыми в сети. Для этого можно пользоваться нашими готовыми реализациями. Статья написана для тех, кто хочет реализовывать свои велосипеды и может быть передумает. Поэтому разобраны многие подводные камни, дан обзор текущих инструментов. Статья написана для получения критики и обмена опытом, поэтому наш путь описан подробно и с обоснованием принятых решений. В мире поиска сетевых устройств слишком много хаоса. Надо что-то с этим делать.

Авторы статьи: Запуниди Сергей, Надежда Тарабрина.

В продолжении вопроса «не сохраняется сетевое обнаружение в дополнительных параметрах общего доступа»
1. Работаю год на windows server 2022, до 01.07.22 без проблем, обновление 2022 поймал в январе.
2. 01.07.22 после перезагрузки сервера потерял удаленный доступ к нему (локально и из внешней сети). IP виден,т.е. сервер в сети.
3. Вот это делал и с Брандмауром переключался.
DNS-клиент
Публикация ресурсов обнаружения функции
Обнаружение SSDP
Узел универсальных PNP-устройств
4. Понял что причина в отсутсвии службы «Узел универсальных PNP-устройств» вообще, т.е. не вкл/выкл, а вообще нет в списке служб.
Отсюда вопросы:
1. Возможно ли скачать службу и установить?
2. Могло ли повлиять обновление до server2022 (хотя понимаю что с января после обновы месяца было более 20 перезагрузок, проблем не было)
3. Не верю конечно, но все же..Майкрософт пугало санкциями… может рубанули как то ?

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Zabbix disk space windows
  • Windows поддержка utf 8
  • Как из ноутбука сделать монитор через hdmi windows 10
  • Microsoft windows publisher вирус
  • Windows show size of folders