Всем нам нравится писать в строке бровсера https://habr.com/. Никому не захотелось бы писать там https://178.248.237.68/. К тому же, IP-адрес может измениться, если Хабр решит перейти на другой хостинг.

Служба Интернета, которая превращает удобные всем имена в IP-адреса, называется DNS, Domain Name System, "система доменных имен".

Я планирую написать несколько статей, посвященных устройству Интернета, пройдясь по всему стеку - эта статья первая в серии.

В этой статье я собираюсь описать работу DNS с разных аспектов, как с технических, так и с организационно-административных.

Эта статья не является введением в DNS для начинающих. Скорее, моя предполагаемая аудитория - это ИТ-профессионалы разной специализации, которые хотят получше разобраться в анатомии сети Интернет.

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

Нормативные документы

Сначала я думал перечислить здесь все относящиеся к DNS документы, но получилось как-то много.

Поэтому поступим так. Базовые RFC, это:

  • RFC 1034 - основные концепции и возможности

  • RFC 1035 - реализация и спецификация

Остальные ссылки приведу в соответствующих разделах статьи.

Домены и доменные имена

Философия DNS заключается в том, что "все есть домен". А с доменом связан некоторый набор информации, описывающий его свойства.

Доменное имя состоит из меток (labels), разделенных точками. Домен www.example.com состоит из трех меток: www, example и com.

Доменное имя может быть абсолютным и относительным - это напоминает файловые пути. Находясь "внутри" домена example.com, к локальным адресам удобнее обращаться по коротким именам. Например, www вместо www.example.com, printer вместо printer.example.com и т.д.

Устроено это так. В настройках каждого компьютера имеется опциональный параметр, список доменов, в которых он ищет относительные имена прежде, чем попытаться поискать их глобально. В UNIX это параметр search в /etc/resolv.conf

Причем этот поиск в локальных доменах относится не ко всем именам, а только к тем, которые "выглядят", как локальные. Критерием является наличие точек в имени. По умолчанию, имя, которое содержит хотя бы одну точку, локальным не считается, но это тоже регулируется параметром (в UNIX это ndots в /etc/resolv.conf).

Эта конструкция вносит в жизнь администратора некоторое здоровое разнообразие и непредсказуемость. Если из-за какого-то временного сбоя относительное имя не получилось найти в первом из перечисленных доменов, может выйти так, что оно случайно найдется во втором, третьем, и далее - глобально. Временные сбои могут влиять на смысл имени. Шанс, конечно, невелик, но иногда всякое случается.

Чтобы дать знать системе DNS, что имя совершенно точно является абсолютным, и локально его искать не надо, в конце имени ставится точка. www.example.com. (с точкой на конце) - точно совершенно глобальное имя, в локальных доменах его искать не надо.

Полные доменные имена называются FQDN, Fully Qualified Domain Name, "полностью определенное имя домена" или просто "полное имя".

Как и в случае файловых путей, любое доменное имя можно превратить в FQDN - например, чтобы их корректно сравнивать между собой.

Доменные имена иерархичны и читается справа налево. Т.е., сначала 'com, потом example.com, потом - www.example.com`. Именно в таком порядке рекурсивный резолвер будет опрашивать DNS-сервера, пытаясь превратить имя в адрес.

Говорят так же, что домен example.com является поддоменом домена com, а www.example.com - поддомен домена example.com.

Таким образом, структура доменов иерархична и древовидна.

Термины "домен" и "доменное имя" часто употребляют, как синонимы, но строго говоря, "домен" - это ветвь глобального дерева доменов с корнем в некотором узле, "доменное имя" - имя этого узла, в виде пути от корня.

На метки накладываются определенные ограничения. Метка должна начинаться с латинской буквы, заканчиваться буквой или цифрой и содержать в промежутке только буквы, цифры и символ минус ('-'). Буквы могут быть прописными и строчными, система DNS не чувствительна к регистру. Длина метки не может превышать 63 символа. Общая же длина имени не должна превышать 255 символов.

Заметим, что на базовом уровне в DNS нет никаких локализованных доменных имен. Локализация (возможность использовать в метках нелатинские буквы) реализована, как надстройка над базовым протоколом, и я расскажу о ней чуть позже.

Зоны

Зона - это набор информации, связанный с определенным узлом в глобальном дереве доменов. Часть этой информации относится к самому узлу, часть - к его непосредственным потомкам.

Информация об имени www.example.com иерархически разделена по трем зонам:

  • корневая зона содержит информацию о том, где искать информацию о зоне .com

  • аналогично, зона .com содержит информацию о зоне .example.com

  • зона .example.com содержит информацию об имени www.example.com

Содержимое зоны описывается текстовым файлом, который называется зонным файлом (zone file).

Как ни удивительно, многие сервера с этой информацией так и работают, в виде текстовых файлов, а не какой-нибудь базы данных.

Каждой зоной кто-то заведует, организация или человек, и без его согласия и содействия зоны следующего уровня существовать не могут.

Корневой зоной заведует американская организация по имени ICANN (Internet Corporation for Assigned Names and Numbers, https://www.icann.org/). Она же и устанавливает обязательные для всех правила в отношении использования DNS-имен.

У каждой зоны есть первичный (primary, он же master) DNS-server, именно на нём хранится главная копия зонного файла. Без первичного сервера зона просто не может физически существовать.

Кроме, правила требуют, чтобы у каждой зоны был хотя бы один вторичный (secondary, slave) сервер, для надежности. Иногда, ставят больше, для распределения нагрузки и для надежности. Вторичные сервера автоматически подсасывают обновления зонного файла с первичного сервера.

Вместе эти сервера называются авторитетными (authoritative) серверами для данной зоны.

Передача полномочий на управление DNS-зоной называется делегированием зоны (или делегированием домена), а обратная операция называется разделегированием.

При делегировании, в родительскую зону добавляются ссылки на авторитетные сервера дочерней зоны.

Когда вы регистрируете ("покупаете") домен, он, вместе со всеми поддоменами, вам делегируется, и вы можете делать с ним, что хотите, в пределах правил, установленных ICANN и национальными законами. При этом вы в праве выбирать по своему усмотрению, будет ли ваша зона размещена на ваших собственных серверах, или на серверах регистратора - организации, продавшей вам домен (обычно возможность использовать таким образом сервера регистратора является бесплатным приложением к домену, но регистратор не обязан этого делать).

Как я уже говорил, корневой зоной заведует ICANN. Зоны первого уровня (они называются top-level domain, сокращенно TLD) до недавних пор были национальными, за исключением зон .com, .edu, .gov, .mil, .net и .org, которые были "всехними", и не национальными, а тематическими.

Однако с относительно недавних пор (в 2015 году) ICANN решила наплодить 100500 top-level domain-ов на все случаи жизни. И теперь если вы торгуете собачьей едой и неожиданно обнаруживаете, что домен dogfoodsales.com занят, вы можете попытать счастья в зонах .name, .coop, .biz и т.п., есть из чего выбирать.

Дело дошло до того, что TLD может зарегистрировать для себя даже частная корпорация. Например, Google зарегистрировал для себя домен .google. По слухам, стоимость регистрации своего TLD составляет в районе нескольких десятков тысяч долларов в год. Немного подороже, чем ездить на автомобиле с номером o999oo999, но в целом, цифра сравнимая.

За каждым top-level domain-ом стоит какая-то организация. Например, зоной .com сейчас распоряжается VeriSign (а раньше распоряжалось Министерство Обороны США - Интернет, вообще, дело военное), доменом .ru заведует "Координационный центр доменов .RU/.РФ" и т.п.

И тут важно подчеркнуть, что организация, которая заведует top-level domain-ом это не та же самая, в среднем, организация, которая продает домены в розницу. Вы покупаете домен у name.com, godaddy.com или reg.ru, но они только розничные продавцы. Если ваш домен находится в зоне .com, записи о нём попадут в базу, которой управляет VeriSign, с которым вы взаимодействуете через посредника.

Несколько top-level domain-ов зарезервированы для специальных применений. Например, .example зарезервирован, чтобы писать в книжках и статьях примеры выдуманных доменов, .test зарезервирован для тестирования и т.п.

Реверсная зона

Иногда возникает потребность произвести обратное преобразование: по IP-адресу узнать доменное имя хоста. Раньше это считалось как-то прям даже обязательным, но сейчас народ несколько подрасслабился и перестал за этим следить.

Это делается с помощью так называемых реверсных зон: записей DNS, в которых ключом поиска является IP-адрес, а ответом является имя.

Но поскольку в философии DNS все есть домен, то IP-адреса приходится записывать в виде псевдодоменов:

  • 44.33.22.11.in-addr.arpa - для IPv4, адрес был 11.22.33.44

  • 4.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.3.3.0.0.2.2.0.0.1.1.0.0.ip6.arpa - для IPv6, адрес был 11:22:33::44

Обратите внимание на запись адреса задом наперед и на использование специальных служебных псевдодоменов in-addr.arpa и ip6.arpa.

Реверсной зоной распоряжается та же организация, которая распоряжается соответствующим диапазоном IP адресов.

Ресурсные записи (resource records)

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

База состоит из записей, и каждая запись состоит из следующих полей:

  1. Имя - именно по этому имени осуществляется поиск в базе

  2. Класс - в основном используется IN от слова internet. Другие классы бывают, но попадаются не часто

  3. Тип - тут есть разнообразие, подробности чуть ниже

  4. TTL, Time To Live - время жизни (в кеше)

  5. Значение, текстовая строка, интерпретация которой зависит от класса и типа

Ключом поиска в базе является сочетание имя+класс+тип.

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

По такому сочетанию в базе может лежать несколько записей (с одинаковым именем классом и типом, но разными значениями). Это нормально и часто используется на практике. Например, если у какого-то хоста есть несколько IP-адресов, в DNS будет храниться несколько записей соответствующего типа, а не одна запись с несколькими адресами.

Такой набор записей, с одинаковым именем, классом и типом, называется RRset, Resource Record Set, как сказать по-русски, не знаю.

Сама по себе база - распределенная, разбита по доменам (вернее, по зонам).

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

Например, для домена example.com в родительской базе будут храниться ссылки на DNS-сервера, которые его обслуживают, а вот адреса в этом домене будут храниться в нем самом (как раз на этих самых серверах).

Обычно ресурсные записи записываются вот как-то так:

google.com.       296   IN      A       216.58.210.174
google.com.       164   IN      AAAA    2a00:1450:4026:805::200e
google.com.       300   IN      MX      10 smtp.google.com.
    ^              ^     ^       ^      ^
    |              |     |       |      |
    |              |     |       |      `-- значение
    |              |     |       `--------- тип
    `-- имя   TTL--'     `----------------- класс

В этом примере есть три ресурсные записи для домена google.com: адреса IPv4 и IPv6, и указание, куда (на какой сервер) слать почту для user@google.com

Сам по себе формат записей - это то, в каком виде печатает их полезная утилита dig, и он совпадает с форматом зонных файлов DNS-сервера BIND (за исключением TTL, который в зонных файлах указывается централизованно, а не для каждой записи), исторически первого DNS-сервера, получившего широкое распространение.

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

Однако, заметим, в протоколе эти данные ходят не в таком виде, и ничто не заставляет их локально в таком виде хранить. Использование такого формата - это просто историческая традиция.

Сервера

DNS-сервер - это программа, которая умеет отвечать на DNS-запросы.

DNS-сервер может работать в одном из четырех основных режимов:

  1. В режиме первичного сервера для некоей зоны

  2. В режиме вторичного сервера

  3. В режиме рекурсивного резолвера, который самостоятельно прокручивает весь сценарий по резолвингу имен, начиная от рутовых зон

  4. В режиме форвардера, который переадресует запросы рекурсивному резолверу

Режим задается конфигурацией, и может быть разным, в зависимости от зоны (т.е., сервер может одновременно работать первичным/вторичным для "своих" зон, и резолвером для остальных).

Серверное программное обеспечение исторически было представлено единственным сервером BIND, который и до сих пор является эталонной реализацией, но сейчас есть и другие варианты.

Типы записей

О типах следует поговорить чуть подробнее.

Наиболее частые типы, с актуальными примерами из настоящих доменов:

  • A и AAAA - эти записи хранят IP-адреса, для IPv4 и IPv6, соответственно:

google.com.   300     IN  A     216.58.211.14
google.com.   300     IN  AAAA  2a00:1450:400f:80d::200e
  • PTR - эти записи работают в обратную сторону, чем записи A и AAAA. Они содержат отображение IP-адресов на доменные имена и содержатся в реверсной зоне. В отличии от A/AAAA, тут один тип записи и для IPv4 и для IPv6:

33.233.248.178.in-addr.arpa. 3590 IN  PTR  habr.com.
  • MX (Mail Exchanger). Ссылается на почтовый сервер, принимающий почту для данного домена:

google.com.   300     IN  MX     10 smtp.google.com.

Число перед именем сервера - приоритет. Серверов может быть несколько, чем меньше приоритет, тем сервер приоритетнее. В ответе - имя сервера, а не IP-адрес. Если в домене отсутствует MX-запись, будут использоваться адреса из записей A и AAAA. Если и они отсутствуют, письмо не дойдет.

  • CNAME (Canonical Name) - позволяет создавать псевдонимы:

www.habr.com. 3549    IN  CNAME  habr.com.

www.habr.com - это псевдоним, "настоящее" (каноническое) имя - habr.com.

  • NS (Name Server) - указывает на DNS-сервер для зоны. Хранится в родительской зоне

habr.com.     20828   IN  NS     ns1.habradns.net.
habr.com.     20828   IN  NS     ns2.habradns.net.
habr.com.     20828   IN  NS     ns3.habradns.net.
  • TXT - содержит всякую разную дополнительную информацию про домен, в текстовом виде и используется очень много где.

habr.com.     21600   IN  TXT    "facebook-domain-verification=wn33ltti5u48gaz376839iraw1dv7z"
habr.com.     21600   IN  TXT    "yandex-verification: 1e51f5cca32f0c89"
habr.com.     21600   IN  TXT    "google-site-verification=X_DZKoxpMnuFOucP02kuOFpop5XYQ2m58J3N4Wipcwo"
habr.com.     21600   IN  TXT    "google-site-verification=wnTVZaUpGF0fewsqyAHJdnydlS9JNe3nopL5oAfztig"
habr.com.     21600   IN  TXT    "google-site-verification=Xsd_r0HhhDfwJqk1LDNs7yvg44kOSQ4SJNbjcpEpQR4"
habr.com.     21600   IN  TXT    "google-site-verification=00jRIg3_Bhl9KhcXwWp65LkUul5CIrYkIE-IyshR8h0"
habr.com.     21600   IN  TXT    "mailru-verification: b0ee4a5d690021d1"
habr.com.     21600   IN  TXT    "google-site-verification=XFULBM_wEq97-MNl8j--Pb07rVk_fy7e981d_6AEMjg"
habr.com.     21600   IN  TXT    "yandex-verification: e86d27babf23ffa3"
habr.com.     21600   IN  TXT    "v=spf1 include:spf.habramail.net ~all"
  • SOA - содержит мета-информацию о зоне (первичный DNS-сервер зоны, e-mail администратора и т.п.)

habr.com.     3600    IN  SOA	 ns1.habradns.net. nsmaster.habralab.ru. 2023081001 3600 900 1209600 3600

Протокол

DNS использует бинарный сетевой протокол, построенный по принципу запрос/ответ. Формат запросов и ответов одинаковый, но в ответе присутствует больше полей - собственно, запрошенная информация.

В качестве транспорта может использоваться как UDP, так и TCP. В любом случае, стандартный нормер порта - 53.

С учетом того, что чтобы разрезолвить одно имя, может потребоваться полтора десятка запросов, да еще и в разные места, UDP может выглядеть предпочтительнее. Он хоть на установление соединения время не тратит.

Однако ответы могут быть довольно большими, и не влезать в UDP-пакет. Спецификация протокола не позволяет использовать UDP-пакеты размером больше 512 байт. Если ответ сервера не влезает в этот лимит, сервер обязан обрезать сообщение и поставить в заголовке ответа соответствующий флаг, побуждая клиента повторить запрос, используя TCP. Кроме того, клиент может перейти на TCP, если после серии попыток по UDP он так и не получил ответа.

Если не слишком углубляться в технические детали, запрос состоит из одного или нескольких "вопросов", каждых из которых состоит из доменного имени, класса и типа. Ответ повторяет информацию из запроса и содержит три группы RR-ов (каждая из которых может быть пустой):

  • ANSWER SECTION - собственно, информация, которую запросили. Если просили IP адрес, он попадет сюда. Если просили MX-record, сюда попадут имена почтовых серверов домена

  • AUTHORITY SECTION - вместо ответа (или части ответа) могут вернуть список DNS-серверов, которые знают ответ. Он попадет сюда

  • ADDITIONAL SECTION - дополнительная информация, полезная в контексте вопроса. Например, если ответ содержит имя почтового сервера или DNS-сервера, сюда могут положить его IP-адреса. Ну, чтобы два раза не вставать. А могут и не положить.

Тулинг

Классическим инструментом для отладки проблем, связанных с DNS, является программа dig.

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

Немного устаревшим инструментом для отладки и изучения работы DNS является программа nslookup. Она не такая всемогущая, как dig, но зато простенькая и поэтому до сих пор используется.

Программа delv похожа на dig но дополнительно к получению ресурсных записей умеет делать их криптографическую валидацию с помощью DNSSEC (о котором чуть позже).

К сожалению, dig не очень-то работает с Multicast DNS, поэтому специально для этой статьи пришлось написать программку mcdig - это такой упрощенный dig для mDNS.

Как работает резолвер

Резолвер, который встроен в libc (т.е., в "обычную" программу) просто передает запрос внешнему DNS-серверу, и рассчитывает получить от него финальный ответ. Например, указав адрес www.google.com, он рассчитывает просто получить список адресов.

Так работает простой, нерекурсивный резолвер.

DNS-сервер же, работая в качестве резолвера, делает более хитрые штуки. Он бежит по цепочке, начиная от корневых серверов, на каждом промежуточном шаге выясняет (с помощью NS-записи) кто является сервером для следующего уровня, попутно обрабатывает записи типа CNAME, которые работают, как символические ссылки, и, в конечном итоге, получает ответ (или не получает) и отдает его запрашивающему клиенту.

Такой резолвер называется рекурсивным.

Воспользуемся dig-ом и проделаем работу рекурсивного резолвера вручную, это занимательно и поучительно. dig мы используем с флагом +norecurse, потому, что не рассчитываем, что промежуточные сервера будут делать нашу работу за нас (они не будут).

К примеру, нам хочется получить IP-адрес для имени habr.com. Итак, поехали:

  1. Получим список корневых серверов. У резолвера он содержится в конфигурации, а мы получим его dig-ом:

$ dig . ns
;; ANSWER SECTION:
.			4935	IN	NS	a.root-servers.net.
.			4935	IN	NS	b.root-servers.net.
  . . .

;; ADDITIONAL SECTION:
a.root-servers.net.	4468	IN	A	198.41.0.4
b.root-servers.net.	4468	IN	A	199.9.14.201
  . . .

Нам повезло, и IP-адреса рутовых серверов приехали сразу, в ADDITIONAL SECTION. Значит, хоть их нам резолвить не придется.

  1. Начнем спрашивать их по-очереди про домен habr.com:

$ dig @198.41.0.4 +norecurse habr.com
;; AUTHORITY SECTION:
com.			172800	IN	NS	a.gtld-servers.net.
com.			172800	IN	NS	b.gtld-servers.net.
  . . .


;; ADDITIONAL SECTION:
a.gtld-servers.net.	172800	IN	A	192.5.6.30
b.gtld-servers.net.	172800	IN	A	192.33.14.30
  . . .

Рутовый сервер ничего не знает про habr.com - он послал резолвер к серверам зоны .com, и позаботился заодно выдать нам их IP-адреса.

  1. Теперь пообщаемся с этими серверами:

$ dig @192.5.6.30 +norecurse habr.com
;; AUTHORITY SECTION:
habr.com.		172800	IN	NS	ns1.habradns.net.
habr.com.		172800	IN	NS	ns2.habradns.net.
habr.com.		172800	IN	NS	ns3.habradns.net.

Сервер зоны .com тоже не знает IP-адреса habr.com, но он вернул список серверов, которые уже знают. На этот раз ADDITIONAL SECTION не содержит адресов, и резолверу придется отдельно потрудиться их разрезолвить - эту часть я опущу, чтобы не раздувать статью совсем уж до неприличного размера.

  1. И наконец, один из серверов зоны habr.com возвращает вожделенный IP-адрес:

$ dig @ns1.habradns.net +norecurse habr.com
;; ANSWER SECTION:
habr.com.		3600	IN	A	178.248.237.68

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

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

Если это время слишком большое, то изменения в зонном файле будут слишком медленно доходить до окружающего мира. Если слишком маленькое, то клиентам часто придется переспрашивать - это влияет и на производительность клиентов и на загрузку авторитетного сервера (особенно, если он обслуживает популярный домен или кучу разных
доменов).

Интернационализация

Интернационализация DNS называется IDNA (International Domain Support for Applications) и описана сразу в нескольких RFC:

  • RFC 5890 - основные понятия

  • RFC 5891 - изменения в протоколе и процедуре регистрации имен

  • RFC 5892 - разрешенные в IDNA символы Unicode

  • RFC 8753 - обновления к предыдущему RFC, с учетом обновлений в мире Unicode

  • RFC 3492 - Punycode, алгоритм, использующийся для преобразования интернациональных имен в ASCII и обратно

Уже по количеству вовлеченных RFC видно, что ребята подошли к делу серьезно.

Как уже говорилось, базовый протокол ничего не знает про русские (китайские, армянские, еврейские...) буквы и оперирует только латиницей. Однако домены, типа яндекс.рф на удивление работают.

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

Так работает Punycode, хитроумный алгоритм, преобразующий метки на человеческих языках, отличных от английского, в неприятные глазу метки, использующие только ASCII-символы.

RFC 5890 вводит понятия A-labels - непроизносимые метки в ASCII и U-label - они же в человекочитаемом виде, в Unicode.

Процедура кодирования люто сложная, и описана она в RFC 3492. Сначала по строке проходятся первый раз, выковыривают из нее все ASCII-совместимые символы, и размещают их по порядку в начале результата. Потом кодируются оставшиеся не-ASCII символы. Поскольку они теперь идут не по порядку, то оставшиеся символы приходится кодировать вместе с их позицией в исходной строке. Всё это настолько сложно и запутанно, что в RFC занимает несколько страниц текста, причем кодирование описывается в терминах работы машины состояния декодера, потому, что енкодер понять нельзя и в терминах кодирования описать ничего невозможно (так написано в самом RFC, я не шучу).

После всего этого издевательства к получившейся строке приделывают префикс "xn--", чтобы ее нельзя было спутать с нормальной строкой, это называется ACE prefix (ASCII Compatible Encoding).

Таким образом, домен bücher.tld превратится в xn--bcher-kva.tld (пример взят из Википедии). Обратите внимание на латинские буквы, которые оказались впереди и на то, что чисто латинская метка .tld осталась нетронутой. И на -kva, в которое превратилась буква ü.

Как и в случае оригинального синтаксиса меток, метки IDNA не чувствительны к регистру символов. Только теперь это надо учитывать в двух местах: U-labels нечувствительны к регистру нелатинских символов (т.е., чтобы с ними правильно работать, нужны полные юникодные таблицы), A-labels нечувствительны к регистру латинских букв.

При всей своей невообразимой сложности, IDNA лишь добавил возможность использовать (в U-labels) буквы разных алфавитов там, где раньше допускались латинские, не сняв остальных ограничений. Произвольную UNICODE строку закодировать в IDNA по-прежнему нельзя.

Более того, IDNA добавил определенных ограничений. Во-первых, по размеру, A-labels по-прежнему обязаны умещаться в 63 символа, а процедура кодирования U-labels отнюдь не сокращает их размер.

Во-вторых, не всякую строку дадут зарегистрировать. Например, по новым правилам нельзя, чтобы метка содержала два знака минуса подряд в третей и четвертой позиции, чтобы не было путаницы с ACE prefix-ом.

Достаточно много правил относительно того, какие части Unicode разрешается использовать. Ну и т.д. В целом, тема IDNA столь сложна, что при детальном ее раскрытии, материала хватит на отдельную статью.

Регистрация доменов и смена регистратора

Чтобы зарегистрировать новый домен, кто-то должен внести его в зонный файл соответствующего top-level domain-а. Но владелец TLD напрямую с розничным покупателем разговаривать не будет, для этого существуют регистраторы.

Регистраторы - это, фактически, розничные продавцы доменов. Регистратор берет у вас 10-20 долларов в год, отдает из них центов 20 владельцу top-level domain-а (я не шучу), договаривается с ним о внесении вашего домена в его базу, и, как правило, предоставляет вам услугу DNS-хостинга (т.е., позволяет использовать свои DNS-сервера в качестве авторитетных для вашего домена).

Не важно, в какой стране работает ваш регистратор, реальные записи о вашем домене в любом случае хранятся на сервере владельца top-level domain-а.

Если вы вовремя забудете за свой домен заплатить, то из базы его выкинут сразу, но в течении месяца-двух оставят вам возможность все починить, просто оплатив стандартную цену за продление. Потом у вас еще будет пара-тройка месяцев, когда можно будет восстановить домен, оплатив дополнительно к цене продления штраф, долларов 50. Потом, если домен красивый, возможно, регистратор перепишет его на себя и выставит на аукцион. А если, провисев там какое-то время, домен не найдет себе нового хозяина, регистратор окончательно его закроет, после чего он станет доступным для покупки всеми желающими. На все про все уйдет где-то полгода-год, в зависимости от регистратора. Так что не теряйте домены, которые вам дороги :-)

При регистрации домена вы указываете довольно много персональной информации. Например, телефон для связи, гражданство, адрес проживания. И вся эта информация по-умолчанию становится публичной (ее можно посмотреть, например, через whois). Это все не выдомка регистраторов, а правила ICANN.

Для организаций это, наверное, нормально, а для частных лиц - ну, не очень. Поэтому у регистраторов есть платная (как правило) услуга, которая заключается в том, что вместо вашей персональной информации регистратор подставляет свою (но если за вашим доменом придут из ФБР, то выложит, конечно, вашу).

Кстати, если ваш домен сгорает за неуплату, то и услуга по сокрытию ваших персональных данных тоже сгорает. И ваши данные долго-долго висят в публичном доступе, пока домен не освободится окончательно.

Регистратор может перехотеть с вами работать. При этом вы не теряете свой домен, но у вас возникает неожиданная потребность перевести домена на другого регистратора. Кроме того, такая потребность может возникнуть у вас по каким-то вашим собственным причинам.

Перенос домена (domain transfer) делается довольно просто. Вы идете к новому регистратору и выражаете свое желание перенести к нему существующий домен (обычно через автоматическую веб-форму). Новый регистратор чего-то там проверяет, после чего требует у вас authenticode - секретный код, который вы получите у своего старого регистратора, и который подтверждает ваше владение доменом. Потом вводите authenticode в форму на сайте нового регистратора, платите какую-то денежку, проходит неделя, и ваш домен оказывается волшебным образом перенесен.

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

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

Кроме переноса домена, есть еще процедура смены администратора домена (что равносильно передаче домена в другие руки), в принципе, она выполняется аналогично.

Если кто-то посторонний доберется до вашего аккаунта у регистратора и уведет ваш домен, починить это будет очень нелегко. Регистратор реально знает что про вас очень мало, и проверить, вы или не вы являетесь подлинным владельцам домена, для него очень сложно (и ему не очень хочется со всем этим возиться).

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

Кроме того, правила ICANN запрещают переносить домен или менять администратора чаще, чем раз в 60 дней.

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

Безопасность DNS

Существует целый отдельный RFC 3833, содержащий систематизированный перечень возможных угроз, которым подвержена система DNS.

Безопасность, это, как известно, история про:

  • конфиденциальность пользовательских данных

  • целостность (достоверность, подлинность) данных - в случае DNS, это данные, которые поступают извне

  • отказоустойчивость перед лицом возможных атак

Здесь мы коротко пройдемся по слабым местам в системе DNS. На полноту охвата я не претендую, тема безопасности - темя необъятная.

Подглядывание в запросы

DNS-запросы не шифруются. Ваш провайдер, ваш корпоративный системный администратор, ваши соседи по локальной сети (к WiFi с WPA это не относится - так у каждого клиента свой ключ шифрования) легко может подглядеть, какими сайтами вы интересуетесь.

Подмена ответов

Если ответы криптографические не подписаны, их можно подменять. Изначально в DNS не было никакой криптографии. Сейчас она появилась, и ей посвящена следующая статья, но увы и ой, внедрение ее идет очень медленными темпами.

Удобнее всего это делать с позиции IP-провайдера или корпоративного админа, но и с позиции соседа по локалке тоже делать можно, пользуясь тем, что оригинальные ответы часто приходят с большой задержкой, и можно успеть их обогнать.

Автор этих строк принимал участие в создании кеширующего Bittorrent-proxy. Сам по себе proxy представлял собой гигантский Bittorrent-клиент, работающий в локальной сети провайдера. Предполагалось, что он будет среди первых выкачивать популярные торренты, а потом раздавать локальным клиентам, привлекая их своей скоростью ответа, тем самым экономя внешний трафик провайдера.

Оставалось только ответить на вопрос, как локальные клиенты узнают о нашем proxy. Мы подменяли в ответах на DNS-запросы, резолвящие имя Bittorrent-tracker-а (сервер в инфраструктуре Bittorrent, который возвращает списки адресов пиров) адрес настоящего трекера адресом нашего сервера, а он выкачивал списки пиров с уже с "настоящего" трекера, подмешивал туда адреса нашего proxy и в таком виде возвращал клиентам. Клиенты велись, как миленькие.

Другой вариант использования этой уязвимости - блокировка сайтов на уровне DNS.

DNS cache poisoning

Эта остроумная атака позволяет "отравить" кеш рекурсивного резолвера, заставляя его перенаправлять клиентов на совершенно посторонние адреса.

Эта атака направлена не на конкретных пользователей, а на DNS-сервер, которые они используют в качестве рекурсивного резолвера. Т.е., это атака против провайдера Интернет или против корпоративной сети.

Допустим, атакующий хочет, чтобы пользователи некоего провайдера вместо сайтов *.example.com попадали на его сервера.

Атакующий заранее выясняет, что DNS-серверами для .example.com являются ns1.name.com и ns2.name.com (домен name.com принадлежит регистратору, через которого зарегистрирован example.com, и в нем же расположены сервера, обеспечивающие для домена example.com DNS-хостинг).

Атакующему понадобится завести свой собственный домен с целью получить в нём контроль над авторитетными серверами. Допустим, атакующий контролирует домен badguys.com.

Дальше атакующему потребуется уговорить какого-нибудь пользователя атакуемой сети сделать DNS-запрос к домену badguys.com. Это можно сделать, например, с помощью спамовой рассылки или каким-нибудь еще социальноинженеринговым методом. Достаточно уговорить пользователя открыть HTML-страничку или письмо в HTML-формате, которое содержит невидимую картинку, ссылка на которую ведет на нужный домен.

Когда DNS-сервер провайдера начинает резолвить домен badguys.com, он в какой-то приходит с запросом к серверу, контролируемому атакующим. И в ответ получает следующую информацию:

  1. ANSWER SECTION: DNS-серверами для badguys.com являются ns1.name.com и ns2.name.com (ну, случайно совпало с целевым example.com, да?)

  2. ADDITIONAL SECTION: а, кстати, IP-адресами ns1.name.com и ns2.name.com являются 145.12.13.14 и 145.12.13.15 (которые, на самом деле, никакого отношения к name.com не имеют, и принадлежат атакующему).

Резолвер провайдера запомнит эту ценную информацию в своих кешах, и в следующий раз, когда ему что-то понадобится от ns1.name.com или ns2.name.com, не будет пытаться резолвить эти имена, а сразу пойдет по запомненным адресам.

Теперь, когда кто-то из пользователей атакованного провайдера (или корпоративной сети) захочет посетить сайт www.example.com, резолвер провайдера пойдет за адресом туда, что он считает сервером name.com, т.е. по IP-адресу, принадлежащему атакующему. И там получит "правильный" (с точки зрения атакующего) ответ.

Кстати, поскольку name.com является популярным регистратором, то заодно атакующий получит контроль над кучей других доменов. При этом, заметим, ему не пришлось проникать ни в компьютеры атакуемых пользователей, ни в компьютеры провайдера. Чистый, аккуратный взлом.

А поскольку популярных регистраторов не так уж и много, то атакующему легко расширить свой успех, взяв под контроль много разных доменов. Существуют и другие варианты этой атаки, детали можно найти по ключевым словам DNS cache poisoning или DNS spoofing.

DNS-tunneling

Корпоративные сети любят очень ограничивать исходящий траффик, чтобы закрыть каналы несанкционированной утечки данных наружу.

DNS-запросы могут нести в себе произвольную информацию. Вредоносная программа может этим пользоваться, передавая информацию на внешний сервер (принадлежащий злоумышленнику) под видом потока запросов. И админы редко это учитывают, считая DNS-трафик безопасным.

Подделка имен с помощью IDNA

Домен "google.com" ничем не отличается от домена "gооgle.com" кроме того, что во втором случае обе буквы "о" - русские. Невнимательный пользователь запросто может туда сходить, ввести логин-пароль и потом долго расстраиваться от полученного результата.

Да, бровсер отобразит домен в строке URL в "красивом" IDNA-ном виде, но этого можно легко и не заметить. А почтовая программа может и вовсе оказаться не такой умной, и насчет таких имен просто не заморачиваться.

DNSSEC: попытка исправить ситуацию с безопасностью

DNSSEC - тема не простая, и ей посвящена целая стопка RFC:

  • RFC 4033 - Введение и требования

  • RFC 4034 - Новые ресурсные записи

  • RFC 4035 - Изменения в протоколе

  • RFC 6840 - Разъяснения замечания по реализации

  • RFC 5155 - Целый отдельный большой RFC про то, как доказательно сказать, что имени не существует

  • RFC 9364 - Наилучшие практики

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

DNSSEC использует криптографию с открытым ключом (ассиметричную криптографию) и, в отличии от TLS, работает с чистыми ключами, а не с TLS-сертификатами. Ключи для DNSSEC никак вообще не связаны с TLS-сертификатами для этого же домена, и это следует понимать.

Из трех основных задач информационной безопасности (конфиденциальность, целостность данных, отказоустойчивость), DNSSEC решает полторы: он обеспечивает целостность данных и защищает от отказов, связанных с отравлением кеша.

DNSSEC подписывает не ответные сообщения DNS-сервера, и не отдельные ресурсные записи, а RRset-ы. Это разумно, поскольку позволяет промежуточному кеширующему серверу сохранять записи и отвечать из своего кеша - мы хотим проверить подлинность самих данных, а не коммуникацию с кеширующим сервером, и хотим получить полный RRset целиком, без пропущенных записей в нем.

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

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

Публичный ключ для зоны хранится в самой зоне, в записи DNSKEY, но вот его сигнатура для каждой зоны хранится в ее родительской зоне, в записи DS. Таким образом, строится цепочка доверия от корневой зоны и далее, через промежуточные зоны, до нужного уровня.

Реальная конструкция чуть более сложная. В родительской зоне хранится публичная часть KSK, key signing key, которым подписан ZSK, zone signing key, которым уже подписывается зона. Такая двухуровнеяая конструкция обладает следующими преимуществами:

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

  • ZSK проще подобрать потому, что он чаще используется. Поэтому есть смысл почаще его обновлять.

Отдельная большая часть DNSSEC - это как доказательно сказать "нет", не раскрывая лищней информации (как сказать, что такого-то имени не существует, не раскрывая всех, которые существуют). Вопрос этот неожиданно сложный, и ему посвящен целый большой RFC 5155.

DNSSEC обратно совместим со старыми клиентами и серверами, его не поддерживающими. Если клиент или сервер не поддерживают DNSSEC, базовая функциональность DNS все равно будет работать, но без криптропроверки.

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

Желающим углубиться в эту тему советую почитать другую статью на Хабре: https://habr.com/ru/articles/120620/

DNS и борьба с e-mail спамом и фишингом

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

Это дает возможность нехорошим людям рассылать спам от чужого имени и подделывать сообщения от банков (которые выглядят, как настоящие, и ссылки в них ведут на сайт с логином/паролем, который выглядит, как настоящий, но только таковым не является).

Чтобы прикрыть всю эту вольницу, в DNS появились механизмы, позволяющие убедиться, что фактический отправитель письма действительно имеет отношение к домену, указанному в поле отправителя.

Письма, которые не проходят эту проверку не то, чтобы совсем не дойдут, но любой вменяемый e-mail провайдер не думая отправит их в папку Spam.

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

Reverse lookup

Простая и наивная проверка заключается в том, что принимающий почтовый сервер делает reverse lookup на IP-адрес, с которого к нему постучался сервер, присылающий письмо. Потом домен, указанный в поле отправителя в письме, сравнивается с тем, который получился в результате reverse lookup.

У этого метода есть свои недостатки. Он недостаточно гибок. В частности, он плохо работает в ситуации, когда отправляющий сервер является посредником. Например, сервера почтовых провайдеров, таких, как gmail.com или mail.ru могут обслуживать не только пользователей с адресами на домене провайдера, но и целые домены.

SPF

SPF позволяет получателю убедиться, что почта от имени какого-то домена пришла с IP-адреса, который имеет право присылать письма от имени этого домена. Тем самым, владелец домена берет на себя определенную ответственность за эти письма, что повышает к ним доверие получателя.

SPF record добавляется в домен, и позволяет задать множество IP-адресов компьютеров, с которых может приходить почта для данного домена:

Технически, это TXT-запись в определенном формате:

$ dig habr.com txt | grep spf
habr.com.                  244   IN  TXT   "v=spf1 include:spf.habramail.net ~all"

$ dig spf.habramail.net txt | grep spf
spf.habramail.net.         5735  IN  TXT   "v=spf1 include:_mxservers.habramail.net ~all"

$ dig _mxservers.habramail.net txt | grep spf
_mxservers.habramail.net.  3600  IN  TXT   "v=spf1 ip4:95.47.173.0/27 ip6:2001:678:5e0::/64 ip6:2001:678:5e0:1::/64 ip4:95.211.146.161 ip4:82.192.95.169 ip4:176.112.221.59 ip4:82.192.95.171 ip6:2001:1AF8:4010:A087:22::146:161 ip6:2001:1af8:4010:a087:22::169 ip6:2001:1af8:4010:a087:22:0:95:171 -all"

Обратите внимание, что SPF-record может ссылаться на записи в других доменах, что позволяет централизованно управлять политиками (в административно связанных доменах).

DKIM

DKIM описан в RFC 6376

DKIM добавляет в электронные письма цифровую подпись. Публичный ключ публикуется в зоне домена, сама подпись добавляется в заголовок письма.

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

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

DKIM не может служить заменой PGP-подписи, поскольку нет гарантий, что письмо подписано целиком, и в пользовательском интерфейсе получателя режим применения DKIM обычно не слишком-то виден. Кроме того, подпись осуществляет не сам отправитель, а его исходящий почтовый сервер (иначе отправителю пришлось бы предоставить доступ к приватному ключу домена).

Использование DKIM имеет побочный эффект, который заключается в том, что отправителю может быть трудно потом утверждать, что он такого письма не отправлял (вплоть до того, что подписанное письмо может быть предъявлено в качестве доказательства в суде).

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

DMARC

DMARC описан в RFC 7489.

DMARC удачно дополняет SPF и DKIM, позволяя владельцу домена сообщить получателям писем, приходящих от имени этого домена, как осуществлять проверку и что делать с письмами, ее не прошедшими.

Как водится, записи DMARC - это особым образом отформатированные TXT-записи, которые публикуются в зоне домена-отправителя.

В целом, смысл DMARC заключается в том, чтобы отделить method (SPF/DKIM) от policy.

Публичные сервера

Google предлагает всем желающим использовать их сервера с адресами 8.8.8.8 и 8.8.4.4 в качестве публичных DNS-серверов. Некоторые другие компании предлагают аналогичные услуги. Например, публичные адреса Cloudflare расположены по адресам 1.1.1.1 и 1.0.0.1

Публичные сервера работают в качестве рекурсивных резолверов, но принадлежат не вашему Интернет-провайдеру, а какой-то независимой от него организации.

Использование публичных серверов может быть удобным, но не следует забывать, что статистика DNS-запросов с большой выборкой представляет собой очень ценную информацию, а если источник запроса можно персонифицировать, ценность этой информации возрастает многократно (зная, какив адреса вы резолвите, можно понять, какие сайты вы посещаете, и насколько часто).

Автор этих строк имел доступ к суточной выборке DNS-запросов с одного крупного Интернет-провайдера из одного из больших российских городов. Узнал много нового о своих согражданах :)

DoT и DoH: DNS over TLS/HTTPS

DoT описан в RFC 7858.
DoH описан в RFC 8484.

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

DoT открывает TLS-сессию и обменивается с сервером запросами/ответами, примерно как это делает DNS over TCP, а DoH оборачивает их в HTTP-запросы.

По сути, это - аналог публичного DNS-сервера, но в качестве транспорта используется TLS или HTTPS.

DoT/DoH защищают ваши DNS-запросы от подглядывания провайдером и соседями а так же от подмены ими ответа, но зато централизованно отправляет их на DoT/DoH сервер (который тоже может подглядывать в запросы и подменять ответы - вопрос в том, кому вы больше доверяете).

Обычно он приходит встроенным в веб-бровсер, и все чаще и чаще оказывается там настроенным и включенным по умолчанию.

Если бровсер называется Chrome, угадайте, кому будет принадлежать настроенный по умолчанию DNS-сервер? :) (с другими бровсерами ситуация аналогичная).

Другие применения DNS

Балансировка загрузки серверов

Если у вас есть много взаимозаменяемых серверов, вы можете настроить свой DNS-сервер таким образом, чтобы разным клиентам отдавались разные адреса (с какой-то системой или случайно). Это позволит распределить нагрузку по серверам более-менее равномерно

Другой вариант использования этого подхода - распределять клиентов географически. Имя google.com в разных местах резолвится в разные адреса. И скорее всего, сервер стоит где-то по-близости. Таким образом, Гугль обслуживает клиентов локальными серверами, а не заставляет их ходить за поисковым ответом через полмира.

Поиск соседей в облаке

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

DNS дает хороший ответ на этот вопрос: части могут найти друг друга по имени, которое фиксируется, в зависимости от назначения части. Это гораздо лучше, чем фиксировать адреса:

  • адреса могут быть динамическими

  • адресами распоряжается владелец облака, а именами - вы

Облачная инфраструктура обычно предоставляет доступ к специализированному DNS-серверу, в котором сервисы могут динамически публиковать свое присутствие, а зависящие от них клиенты находить их, пользуясь обычными DNS-запросами.

Мультикастный DNS для локальных сетей (mDNS)

mDNS описан в RFC 6762

Техника Apple славилась тем, что ее можно собрать в одной комнате, свинтить сетью и, без всяких лишних настроек, все сразу начинает работать. Компьютеры видят друг друга и подключенные к сети принтеры. Не надо настраивать адреса и сервер имен, все работает само. У Apple был собственный сетевой стек, AppleTalk, и в его протоколы это заложено.

Однако победили сети TCP/IP, потому, что они были приспособлены для работы не только в локальной сети, но и в большом Интернете.

Теперь счастье постепенно приходит и к нам, простым пользователям TCP/IP.

Для поиска устройств в сети пригодился старый добрый DNS, но не в простом, а в мультикастном виде.

Чтобы узнать адрес какого-то устройства, соответствующие DNS-запросы не отправляются на сервер, а рассылаются мультикастами. Адрес мультикастной группы - 224.0.0.251 (ff02::fb для IPv6), номер порта - 5353, чтобы не было путаницы с обычным DNS.

Вот как это работает:

$ ./mcdig KM7B6A91.local. A

; QUESTION PSEUDOSECTION:
;KM7B6A91.local.   IN   A

;; ANSWER SECTION:
KM7B6A91.local.    120   IN   A     192.168.1.102

KM7B6A91 - это имя моего принтера, которое он сам себе придумал, а 192.168.1.102 - его IP-адрес, который он получил по DHCP.

Кстати, если бы DHCP не было, все устройства в локальной сети все равно получили бы адреса. Это - так называемые link-local адреса, для них выделен специальный диапазон. Особенно хорошо это работает в IPv6.

Все это вместе незывается у Apple словами Rendezvous и Bonjour, а в нейтральном мире - ZeroConf, mDNS, DNS-SD. Этой технологии посчастливилось иметь много названий.

Для имен, которые находятся таким образом, зарезервирован Top Level Domain .local. Но на самом деле, устройства с нормальными именами тоже откликаются в локалке на MDNS.

В отличии от классического DNS, мультикастный DNS не накладывает жестких ограничений на синтаксис меток. Метка может содержать пробелы, знаки препинания и т.п. - все, что разрешено в UTF-8. Поэтому "Kyocera ECOSYS M2040dn._printer._tcp.local." - это вполне нормальное доменное имя:

$ ./mcdig "Kyocera ECOSYS M2040dn._printer._tcp.local." SRV

;; QUESTION PSEUDOSECTION:
;Kyocera\ ECOSYS\ M2040dn._printer._tcp.local.	IN	 SRV

;; ANSWER SECTION:
Kyocera\ ECOSYS\ M2040dn._printer._tcp.local. 4500	IN  SRV	0 0 515 KM7B6A91.local.

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

Кроме того, мультикасты могут теряться, а слать их, как из пулемета, несколько невежливо. Поэтому mDNS работает лучше, если в системе есть локальный демон, постоянно отслеживающий соседей, и "поиск" в мультикастном DNS-е заключается в поиске в заранее разогретом кеше этого демона.

Кстати, ответы на запросы в mDNS тоже рекомендуется отправлять мультикастами - чтобы пассивные слушатели могли разогревать свой кеш пролетающей мимо полезной информацией.

mDNS - это система, основанная на доверии. Если в локальной сети кто-то врет (или добросовестно ошибается), не существует способа уличить его за этим занятием.

Еще одна проблема заключается в том, что если устройство подключено к нескольким несвязанным локальным сетям (например, WiFi и проводному Ethernet), хоть и с низкой вероятностью, но может получиться так, что одно и то же имя встречается в нескольких сетях, но относится к разным устройствам. Т.е., по-хорошему, если устройство найдено через mDNS, то connect к нему должен содержать информацию и об адресе и об сетевом
интерфейсе, через которое предполагается устанавливать соединение. Однако в реальной жизни это не доделано, и более-менее корректно работает только при использовании IPv6 link-local адфесов (в них предумотрено указание "зоны", которая, как раз, и является в адресе ссылкой на сетевой интерфейс).

DNS-SD: автоматический поиск принтеров, и не только

DNS-SD описан в RFC 6763

mDNS - это хорошо, но нормальному человеку неоткуда узнать, что его принтер называется KM7B6A91.local.? Нормальному человеку хотелось бы получить список устройств с человеческими именами, чтобы он мог выбрать из них нужное.

А программе, прежде, чем подключиться к какому-то устройству, хотелось бы знать, чем это устройство является (например, принтером, сканером и т.п.) и что, в целом, умеет.

Протокол, который решает эти проблемы, называется DNS-SD, и является надстройкой над mDNS.

DNS-SD расшифровывается, как DNS Service Discovery, и строго говоря, ищет не устройства, а "сервисы". Но если сервисом является сервис печати, то мы найдем, как раз, принтер (или анонсирующий себя через DNS-SD сервер печати).

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

В большой корпоративной сети это все работает не так хорошо. Если у вас в списке полсотни принтеров, и через этот список надо каждый раз продираться, то начинает появляться желание всю эту автоматику выключить куда подальше.

Работает DNS-SD следующим образом. Допустим, нам нужен принтер, работающий по протоколу IPP. Сначала мы поищем все принтеры в сети:

$ ./mcdig _ipp._tcp.local. PTR
;; QUESTION PSEUDOSECTION:
;_ipp._tcp.local.   IN   PTR

;; ANSWER SECTION:
_ipp._tcp.local.   4500   IN   PTR   Kyocera\ ECOSYS\ M2040dn._ipp._tcp.local.

Здесь запись PTR используется необычным (в сравнении с обычным DNS) образом: она указывает не на IP-адрес, а на доменное имя. Причем самая первая метка в имени использует человекочитаемый формат. В терминологии RFC 6763 это называется "Service Instance Name" - это не совсем то же самое, что host name, но тоже уникальное в пределах сети, хоть по виду и не скажешь.

Теперь мы хотим немного побольше узнать про это устройство, чтобы с ним можно было работать.

Запрос SRV-записи приносит нам host name и TCP-порт:

$ ./mcdig "Kyocera ECOSYS M2040dn._ipp._tcp.local." SRV
;; QUESTION PSEUDOSECTION:
;Kyocera\ ECOSYS\ M2040dn._ipp._tcp.local.  IN  SRV

;; ANSWER SECTION:
Kyocera\ ECOSYS\ M2040dn._ipp._tcp.local. 4500 IN  SRV  0 0 631 KM7B6A91.local.

TXT-запись содержит кучу полезной информации про принтер:

$ ./mcdig "Kyocera ECOSYS M2040dn._ipp._tcp.local." TXT
;; ANSWER SECTION:
Kyocera\ ECOSYS\ M2040dn._ipp._tcp.local.  4500  CLASS32769	TXT	"txtvers=1" "pdl=image/pwg-raster,application/octet-stream,application/pdf,image/tiff,image/jpeg,image/urf,application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL,application/vnd.xpsdocument" "product=(ECOSYS M2040dn)" "ty=Kyocera ECOSYS M2040dn" "qtotal=1" "usb_MFG=Kyocera" "usb_MDL=Kyocera ECOSYS M2040dn (KPDL)" "note=" "adminurl=https://KM7B6A91.local/airprint" "Duplex=T" "Fax=F" "Scan=T" "Color=F" "UUID=4509a320-00a0-008f-00b6-002507510eca" "URF=CP255,DM4,IFU0,IS19-20,OB1-10,PQ4,RS600,V1.4,W8" "PaperMax=legal-A4" "kind=document,envelope" "priority=48" "rp=ipp/print" "print_wfds=T" "mopria-certified=1.2" "air=none" "TLS=1.2"

Поиск локальных устройств (USB)

Сочетание DNS-SD для поиска устройств с прогибанием производителей в сторону использования стандартных, а не собственных, протоколов сделало возможным такую штуку, как "бездрайверная" печать и сканирование документов. Если устройство поддерживает эту технологию, то драйвера становятся не нужны, стандартный драйвер, входящий в операционную систему, работает с любым принтером, который поддерживает IPP и любым сканером, который поддерживает eSCL.

Однако USB-устройства, не имеющие сетевого подключения, остались неохваченными.

Чтобы как-то решить эту ситуацию, организация, занимающаяся стандартизацией USB, изобрела протокол IPP over USB, который вернее было бы назвать HTTP over USB, потому, что он именно этим и является. Пропихивая HTTP траффик через USB-порты, этот протокол сделал возможным бездрайверную печать сканирование через USB, и даже веб-консоль принтера через USB теперь тоже удивительным образом работает.

Эта конструкция превращает USB-устройство в псевдосетевое, и использует DNS-SD, чтобы анонсировать наличие таких адресов на localhost-е.

Тут следует заметить, что никто не шлет мультикастов через интерфейс 127.0.0.1, они там не предусмотрены. Коммуникация идет через локальный mDNS-демон (Avahi в случае Linux). Демон IPP over USB анонсирует устройства через Avahi, клиенты его находят, но все это делается в пределах одной машины, и сам с собой Avahi мультикастами не разговаривает.

Такая архитектура позволяет использовать демоны IPP over USB и сервер печати в изоляции, DNS-SD внутри машины используется в качестве сигнальной шины, а вся коммуникация идет через сетевые сокеты.

Заключение

Как говорил Козьма Прутков, "никто не обнимет необъятного". Но попытаться стоило :)

Если что-то важное упустил, добро пожаловать в комментарии!

Комментарии (25)


  1. mrtippler
    22.08.2023 08:59
    +6

    Бровсер - так себе словечко.. Но в целом статья хорошая, спасибо.


    1. apevzner Автор
      22.08.2023 08:59

      Спасибо на добром слове! Я старался.

      Слово браузер мне нравится еще меньше - очень уж не-русская у него фонетика.

      Может, "сетевое бродило?" ;)


      1. mrtippler
        22.08.2023 08:59
        +1

        Да тут почти вся фонетика нерусская, что поделать, так получилось..:) А если уж сильно не нравится, можно писать browser, как вариант.


        1. apevzner Автор
          22.08.2023 08:59
          +1

          Не, ну вот слово "сокет", например, хорошее. Звучит, как родное, хоть само и импортное. А бровсеру не повезло.


          1. mrtippler
            22.08.2023 08:59
            +1

            «Может собственных Платонов и быстрых разумом Невтонов российская земля рождать». М. Ломоносов.
            :)


            1. apevzner Автор
              22.08.2023 08:59

              Во! Невтонов, а не Неутонов!


          1. mrtippler
            22.08.2023 08:59
            +2

            Тогда уж логичнее - соцкет. :)


            1. Tarakanator
              22.08.2023 08:59
              +1

              Я только что понял откуда пошло кул хаЦкер


      1. victor_1212
        22.08.2023 08:59

        >Анатомия Интернета ...

        Александр, спасибо за статью хорошего уровня, imho не хуже первой, но хочу обратить Ваше внимание, что служба DNS это не совсем анатомия сети, потому что касается в основном разрешения имен в ip адреса, и только косвенно движения самих пакетов в сети, т.е. routing, и global connectivity,

        поэтому может быть стоит Вам именно про это тоже написать, типа как connectivity обеспечивается, в том числе на логическом уровне, потому что сеть это не просто hw соединенное волокном, а также иерархическая логическая структура фиксированная в конфигурации routers разного уровня, в свою очередь созданной на основе контрактов между isp, и разделения функций по уровням между isp tier 1, 2, 3,

        это вероятно имело бы практический интерес для читателей habr, типа лучшего понимания, что именно может происходить в сети при фильтрации vpn, dpi и пр.


        1. apevzner Автор
          22.08.2023 08:59

          поэтому может быть стоит Вам именно про это тоже написать

          Я так и планирую. Тема-то, как Вы понимаете, очень широкая. Пытаюсь найти то смысловое ядро, которое будет интересно и понятно многим, не скатываясь в банальности и не погрязая в чрезмерно низкоуровневых деталях.

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

          Спасибо вам за отзыв и за обратную связь!


          1. victor_1212
            22.08.2023 08:59

            > разработчик с большим сетевым опытом

            может напишете пару строк в личку, просто интересно


      1. GospodinKolhoznik
        22.08.2023 08:59

        Просто бро.


  1. Epic18
    22.08.2023 08:59

    Я делаю так: h + end + enter


  1. heos_spb
    22.08.2023 08:59
    +2

    Чисто перед именем сервера

    Чисто конкретно задвинул, брателло!

    ситуация аналогочная


    1. apevzner Автор
      22.08.2023 08:59

      Чисто конкретно поправил. Аналогочно и со второй опечаткой. Спасибо!


  1. ugenk
    22.08.2023 08:59

    А есть ли у вас, уважаемые коллеги, реальный опыт эксплуатации dnssec в больших проектах? На сколько я вижу, особо никто из гигантов его не использует, из-за проблем с реальной совместимостью


    1. apevzner Автор
      22.08.2023 08:59

      Не очень понятно, в чем могли бы заключаться эти проблемы с совместимостью.
      Вот habr.com, например, подписан DNSSEC-ом. Вроде никто не жалуется.

      Я вижу тут следующие соображения:

      1. Если доступ к сайту осуществляется только через TLS (и не только HTTPS, SMTP/TLS тоже считается), проверка домена в любом случае заложена в TLS, и DNSSEC ничего особо полезного не добавляет

      2. С DNSSEC много возни (хотя, казалось бы, Google мог бы справиться)

      3. DNSSEC не очень-то совместим с CDN. Если посмотреть, тот же google.com по-разному резолвится из разных мест - на выходе адрес их ближайшего к пользователю CDN-сервера.

      Наверное, об этом стоило упомянуть в статье. Но вот, упустил...


      1. censor2005
        22.08.2023 08:59

        Добавлю ещё несколько причин, почему его не используют:

        • Почти нет (либо они не на слуху) реальных кейсов эксплуатации подмены DNS запросов

        • Наличие или отсутствие DNSSEC не влияет на поисковый рейтинг веб-сайта (в отличие от наличия SSL)

        • Мало какие shared хостинг-площадки предоставляют функцию подписания зоны из коробки. У Plesk, например, это платное расширение, в CPanel для работы DNSSEC нужно использовать PowerDNS. Остальным нужно либо ставить ПО для подписания зоны, либо вручную подписывать через dnssec-signzone или другие инструменты, а также самостоятельно сделить за ротацией ключей. Приятное исключение - ISPConfig, из коробки предоставляет DNSSEC бесплатно и без регистрации.

        • При смене хостинга необходимо заранее подписать зону на новом хостинге и заранее публиковать новые DS-записи в родительской зоне. Если своевременно не обновить DS-записи при переносе хостинга, домен перестанет работать, и на возобновление работы могут понадобиться многие часы.

        • Не все регистраторы предоставляют услугу публикации DS-записей


        1. apevzner Автор
          22.08.2023 08:59

          Подмену DNS-ответов можно использовать, чтобы отравить кеш (крупного) DNS-резолвера. В эпоху повсеместного использования TLS на чужой сайт пользователей так не заведешь, но отказ в обслуживании устроить можно.

          Гугль активно двигает DoH. Причем в варианте, встроенном в Chrome и с терминацией на Гугловских серверах. Им, я бы даже сказал, не выгодно чинить проблемы в DNS.


      1. ugenk
        22.08.2023 08:59

        Разное пишут в интернете. Например такие ужастики: https://ianix.com/pub/dnssec-outages.html

        1. TLS сертификат можно подделать, если получается каким-то образом получить управление надо доменом

        2. Возможно, у гугла были какие-то еще соображения, и они шире, чему у админов хабра, по этому и спрашиваю мнения компетентных коллег


        1. apevzner Автор
          22.08.2023 08:59

          Вряд ли мы здесь встретим людей, принимающих техническое решение о использовании DNSSEC в доменах масштаба google.com или intel.com. Таких людей просто физически очень мало, не думаю, что они тут стаями ходят

          Но можем попробовать сами разобраться. Я потом обновлю статью.

          История по вашей ссылке интересная. Там говорится, что если сломать TLD, DNSSEC сломается у кучи поддоменов. И еще там говорится, что такие случаи 100500 раз были в истории.

          Мне, вообще, пока не очень понятно. Если сломается TLD, он и NS не будет возвращать и записи, относящиеся к DNSSEC тоже не будет. Вроде и просто домены сломаются, и криптоподпись сломается в них заодно. Но последствия первого сильно хуже последствий второго, и на фоне первого второе вроде как представляет только чисто академический интерес -- поправьте меня, если я не прав.

          TLS сертификат не зависит никак от домена. С точки зрения TLS, имя домена - это просто такая строка. Мы идем на google.com, запоминаем, куда шли, резолвим адрес, куда-то попадаем, там нам предъявляют TLS-сертификат, и мы сравниваем строку в сертификате с запомненным доменом.

          Единственное что, надо посмотреть, как это с CNAME сочетается. Я не знаю, бровсер сам резолвит CNAME и сразу обращается по каноническому адресу, или он идет по тому адресу, который дали, рассчитывает там найти TLS-сертификат, соответствующий имени, принимает оттуда redirect на каноническое имя, и потом, зайдя уже по каноническому имени, рассчитывает там найти другой TLS-сертификат, уже соответствующий новому имени. Я разберусь, мне любопытно.

          Но в общем и целом, похоже, DNSSEC - мёртвая технология (хотя ее агония может еще довольно долго продолжаться).


          1. censor2005
            22.08.2023 08:59
            +1

            Мы занимались внедрением DNSSEC на уровне TLD, и подготовка заняла действительно много времени. В зоне было порядка 100тыс.доменов, и риски были достаточно высокими. Если будут вопросы, постараемся ответить тут


            1. apevzner Автор
              22.08.2023 08:59

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

              Собственно, я хочу написать серию статей, которая восполняет этот пробел. Я много чего трогал собственными руками, но много чего и не трогал - жизнь, она не бесконечна :)

              Поэтому если вы поделитесь своим опытом, это может быть полезным другим людям. Буду рад вашему рассказу


              1. censor2005
                22.08.2023 08:59
                +1

                Если наш ИБ одобрит, напишу тут развёрнутый комментарий )


                1. apevzner Автор
                  22.08.2023 08:59

                  Спасибо!