Перейти к содержанию

mDNS (Multicast DNS)

Адрес платы в домашней сети выдаёт DHCP, и завтра он другой. mDNS позволяет назвать устройство my-esp32.local, и любой компьютер в той же сети найдёт его, спросив всех сразу по групповому адресу.

Обновлено Редакция GAW

mDNS (Multicast DNS, многоадресный DNS) — протокол RFC 6762, который разрешает имена в локальной сети без DNS-сервера: узел отправляет обычный DNS-запрос не на адрес сервера, а на групповой адрес, и отвечает тот, кому имя принадлежит. Формат сообщений, синтаксис имён и типы записей те же, что в DNS, новых кодов операций нет (разд. 1). Для mDNS зарезервирован домен .local: имя вида my-esp32.local. узел назначает себе сам и владеет им, пока на канале никто его не оспорил (разд. 3, 9). Вместе с DNS-SD это основа «нулевой настройки», известной как Bonjour в macOS и Avahi в Linux.

Адреса и порт

ПараметрЗначениеИсточник
групповой адрес IPv4224.0.0.251разд. 22
групповой адрес IPv6FF02::FB (из набора FF0X::FB)разд. 22
порт UDP5353разд. 22
домен.local.разд. 3, 22
таймаут одноразового запросаобычно 2–3 сразд. 5.1

Простейший клиент просто шлёт DNS-запрос на 224.0.0.251:5353 и берёт первый ответ (разд. 5.1). Адрес 224.0.0.251 — канальный: маршрутизаторы его не передают, поэтому mDNS работает только внутри одного сегмента Ethernet или Wi-Fi. Узел только с IPv6 и узел только с IPv4 образуют две независимые зоны .local; устройство с двумя стеками регистрируется в обеих (разд. 20), а запросы по IPv6 идут на групповой адрес FF02::FB. Сообщение может быть больше 512 байт классического DNS — до MTU интерфейса за вычетом заголовков, с фрагментами не более 9000 байт (разд. 17).

Жизненный цикл имени

  1. Проверка (probing). После случайной задержки 0–250 мс узел трижды через 250 мс спрашивает своё имя записью типа ANY; если за 750 мс никто не ответил, имя свободно (разд. 8.1). Проверочные запросы ставят бит QU — просьбу ответить одноадресно (разд. 5.4).
  2. Объявление. Не менее двух незапрошенных ответов с интервалом 1 с, можно до восьми с удвоением интервала; периодических объявлений протокол запрещает (разд. 8.3).
  3. Ответы. Узел отвечает только за собственные записи, никогда — из кеша, и на разделяемой среде вроде Ethernet может задержать ответ до 500 мс (разд. 6).
  4. Срок жизни. TTL 120 с для записей с именем хоста (A, AAAA, SRV) и 75 мин для остальных; при выключении — «прощальный» ответ с TTL 0 (разд. 10, 10.1).

Из-за TTL в 120 с смена адреса, который выдал DHCP, становится видна соседям не мгновенно — узел при изменении записей обязан повторить объявление (разд. 8.4).

mDNS на микроконтроллере

На ESP32 компонент mDNS из ESP-Protocols запускается mdns_init(); mdns_hostname_set("my-esp32") даёт имя my-esp32.local, а mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0) объявляет веб-сервер платы. Задать своё имя хоста нужно до объявления служб, а запросы к собственным именам компонент намеренно не поддерживает. Поиск с платы: mdns_query_a("esp32-mdns", 2000, &addr) ищет адрес с таймаутом 2000 мс, mdns_query_ptr("_http", "_tcp", 3000, 20, &results) — службы. Компонент работает в отдельной задаче с приоритетом CONFIG_MDNS_TASK_PRIORITY (по умолчанию 1). В Zephyr клиентское разрешение mDNS включает CONFIG_MDNS_RESOLVER. Для платы с Ethernet-контроллером и для Wi-Fi-модулей из обзора беспроводных интерфейсов правила одинаковы: нужны поддержка группового приёма в стеке и UDP-сокет на порту 5353.

С чем не путать: mDNS отвечает на вопрос «какой адрес у имени», а перечень служб в сети («где здесь принтеры и веб-серверы») — задача DNS-SD, который работает поверх тех же пакетов. От link-local-адреса 169.254.x.x протокол не зависит: имена .local работают и с адресами от DHCP.

Частые вопросы

Почему esp32.local не открывается, хотя плата в сети?

Чаще всего спрашивающий и плата оказались в разных широковещательных доменах: mDNS работает только в пределах одного канала, запросы идут на групповой адрес 224.0.0.251 (IPv6 — FF02::FB) и маршрутизаторами не передаются. Вторая причина — на компьютере нет ответчика mDNS, либо он блокирован межсетевым экраном на порту UDP 5353. Третья — узел с IPv4 и узел только с IPv6 живут в разных зонах .local (RFC 6762, разд. 20).

Что происходит, когда два устройства выбрали одно имя?

Перед использованием имени узел его проверяет: после случайной задержки до 250 мс отправляет три запроса типа ANY через 250 мс и ждёт ещё 250 мс (разд. 8.1). Если за эти 750 мс владелец имени ответил, конфликт решается в его пользу, и новый узел обязан выбрать другое имя (разд. 8.1, 9). Только после успешной проверки узел объявляет имя двумя ответами с интервалом в секунду.

Сколько живут записи mDNS в кеше?

Рекомендованный TTL — 120 с для записей с именем хоста (A, AAAA, SRV) и 75 мин для остальных; запросчик обновляет запись, когда прошло 80 % срока (разд. 10). При корректном выключении узел шлёт «прощальный» ответ с TTL 0, и соседи удаляют запись через секунду (разд. 10.1); при обрыве питания имя исчезает из кешей лишь по истечении TTL.

Источники

  1. S. Cheshire, M. Krochmal. Multicast DNS. RFC 6762, February 2013 — разд. 1: заимствует структуру сообщений, синтаксис имён и типы записей DNS, новых кодов операций и ответов нет; разд. 3: имена вида single-dns-label.local., например MyComputer.local., протокол позволяет проверять и поддерживать уникальность имён; разд. 5.1: одноразовый запрос — обычный DNS-запрос на 224.0.0.251:5353 или [FF02::FB]:5353, таймаут обычно 2–3 с, исходный порт 5353 только у полноценного запросчика; разд. 5.2: непрерывные запросы для DNS-SD; разд. 5.4: старший бит класса в вопросе — бит QU, просьба ответить одноадресно; разд. 6: отвечающий отдаёт только свои записи, не из кеша, на Ethernet задержка ответа до 500 мс; разд. 8.1: проверка (probing) запросом типа ANY после случайной задержки 0–250 мс, три запроса через 250 мс, ещё 250 мс ожидания, у защитника имени 750 мс, проверочные запросы — с битом QU, при конфликтном ответе до истечения 250 мс после третьего запроса узел уступает существующему хозяину и выбирает новое имя; разд. 8.3: объявление — не менее двух незапрошенных ответов с интервалом 1 с, до восьми с удвоением интервала, периодических объявлений нет; разд. 8.4: при изменении данных записи объявление повторяется; разд. 9: конфликтующая запись возвращается в состояние проверки, проигравший обязан перестать использовать имя; разд. 10: TTL 120 с для записей с именем хоста (A, AAAA, SRV), 75 мин для остальных, повторный запрос при 80 % срока; разд. 10.1: прощальные пакеты с TTL 0; разд. 17: сообщение до MTU интерфейса минус заголовки IP и UDP, с фрагментами не более 9000 байт, лучше держать под 1500; разд. 20: у IPv4- и IPv6-узлов две независимые зоны .local., двухстековый узел регистрируется в обеих; разд. 22: порт UDP 5353, адрес 224.0.0.251, набор FF0X::FB, из которого используется FF02::FB, .local. — домен специального назначения
  2. Espressif. ESP-Protocols documentation, latest: mDNS Service (ESP32) — mdns_init(), mdns_hostname_set("my-esp32") даёт имя my-esp32.local, mdns_instance_name_set — дружественное имя; mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0) и mdns_service_txt_set — объявление службы с записями TXT; mdns_query_a(host, 2000, &addr) — поиск адреса с таймаутом в мс, mdns_query_ptr("_http", "_tcp", 3000, 20, &results) — поиск служб; задание своего имени хоста обязательно перед объявлением служб, запросы собственных имён не поддерживаются; задача mDNS с приоритетом CONFIG_MDNS_TASK_PRIORITY (по умолчанию 1) и стеком CONFIG_MDNS_TASK_STACK_SIZE
  3. Zephyr Project. Zephyr Project Documentation, latest: Networking APIs — DNS Resolve — клиентское разрешение имён mDNS по RFC 6762 включается опцией CONFIG_MDNS_RESOLVER, LLMNR по RFC 4795 — CONFIG_LLMNR_RESOLVER
Страница помогла?

Нашли ошибку? ·