Компьютерные сети. 6-е изд. - Эндрю Таненбаум
Шрифт:
Интервал:
Закладка:
7.1.4. DNS-запросы и DNS-ответы
Теперь рассмотрим структуру, формат и назначение DNS-запросов, а также разберемся с тем, каким образом DNS-серверы выдают ответы на них.
DNS-запросы
Как было сказано выше, DNS-клиент обычно направляет запрос локальному рекурсивному распознавателю, который выполняет итеративные операции поиска, чтобы в конечном итоге выполнить запрос. Наиболее распространенный тип запроса — запрос А-записи, позволяющей сопоставить доменное имя с IP-адресом соответствующей конечной точки интернета. В DNS есть разные записи ресурсов (с другими запросами); мы обсудим их в следующем разделе, посвященном записям ресурсов (то есть ответам).
Хотя DNS почти всегда использовалась в основном для сопоставления удобочитаемых имен с IP-адресами, за прошедшие годы DNS-запросы использовались для множества других задач. Еще один популярный вид DNS-запроса — проверка на наличие домена в черном списке DNS (Domain Name Service Black List, DNSBL). Этот список используется для отслеживания IP-адресов, связанных с распространением спама и вредоносных программ. Для поиска доменного имени в DNSBL клиент может направить DNS-запрос А-записи специальному DNS-серверу, например pbl.spamhaus.org. Он производит сопоставление со списком IP-адресов, которые не должны соединяться с почтовыми серверами. Чтобы проверить конкретный IP-адрес, нужно просто изменить порядок октетов в IP-адресе на обратный и поставить полученный результат перед именем сервера pbl.spamhaus.org.
Так, например, чтобы проверить адрес 127.0.0.2, нужно сделать запрос для 2.0.0.127.pbl.spamhaus.org. При наличии этого IP-адреса в списке DNS-запрос возвращает IP-адрес, в котором, как правило, закодирована дополнительная информация (например, сведения о том, как данная запись попала в список). Если данного IP-адреса в списке нет, DNS-сервер сообщает об этом с помощью соответствующего ответа NXDOMAIN, означающего «такого домена нет» («no such domain»).
Расширения и улучшения DNS-запросов
Со временем DNS-запросы стали более изощренными и сложными, поскольку клиенты нуждались во все более конкретизированной и актуальной информации и вместе с тем возрастали требования безопасности. Существенным расширением DNS-запросов за последние годы стало использование клиентской подсети EDNS (EDNS0 CS Extended DNS Client Subnet, или просто EDNS Client Subnet), что позволяет локальному рекурсивному распознавателю клиента передавать авторитетному серверу имен IP-адрес подсети оконечного распознавателя.
Благодаря механизму клиентской подсети EDNS авторитетный сервер имен для доменного имени может узнать IP-адрес клиента, направившего исходный запрос. Обычно это позволяет ему произвести более эффективное сопоставление с ближайшей копией реплицируемого сервиса. Например, если клиент выдаст запрос для домена google.com, авторитетный сервер имен для Google в большинстве случаев вернет имя, соответствующее ближайшему к клиенту интерфейсному серверу. Конечно, сделать это можно, лишь зная, в какой части сети (а в идеале и в какой части мира) находится клиент. Обычно авторитетный сервер имен видит только IP-адрес локального рекурсивного распознавателя.
Если клиент, инициировавший запрос, находится рядом с соответствующим локальным распознавателем, то авторитетный сервер этого домена может сопоставить клиента, просто руководствуясь местоположением локального рекурсивного DNS-распознавателя. Но клиенты все чаще используют локальные рекурсивные распознаватели, IP-адрес которых не позволяет определить местоположение клиента. Например, компании Google и CloudFlare используют общие DNS-распознаватели (с адресами 8.8.8.8 и 1.1.1.1 соответственно). Если клиент настроен на использование одного из таких распознавателей, авторитетный сервер не сможет извлечь полезную информацию из сведений об IP-адресе этого распознавателя. Механизм клиентской подсети EDNS решает эту проблему, включая IP-адрес подсети в запрос от локального рекурсивного распознавателя, чтобы авторитетный сервер видел IP-адрес подсети клиента, который инициировал запрос.
Как отмечалось ранее, имена в DNS-запросах нечувствительны к регистру. Это позволило современным DNS-распознавателям включить в запрос дополнительные биты идентификатора транзакции, установив символы в поле QNAME в произвольный регистр. 16-битный идентификатор уязвим к различным видам атаки отравления кэша, включая атаку Каминского, о которой пойдет речь в главе 8. Отчасти эта уязвимость обусловлена тем, что длина DNS-идентификатора транзакции составляет лишь 16 бит. Увеличение длины потребовало бы изменений в спецификации протокола DNS, а это непростая задача.
В итоге было разработано альтернативное решение — метод 0x20-кодирования, который сводится к следующему. Локальный рекурсивный распознаватель переключает регистр в каждом поле QNAME («uchicago.edu» может превратиться в «uCHicaGO.EDu» и т.п.), что позволяет использовать каждый символ доменного имени в качестве дополнительного бита DNS-идентификатора транзакции. Конечно, важно, чтобы никакой другой распознаватель не менял регистр поля QNAME в последующих итеративных запросах или ответах. При сохранении регистра соответствующий ответ содержит поле QNAME с тем регистром, который ему присвоил локальный рекурсивный распознаватель, и в результате эти биты добавляются в идентификатор транзакции. Конечно, все это выглядит как лишенные какой-либо элегантности костыли, но именно так происходит внесение изменений в широко используемое программное обеспечение с сохранением обратной совместимости.
DNS-ответы и записи ресурсов DNS
У каждого домена, независимо от того, является ли он единственным хостом или доменом верхнего уровня, может быть набор ассоциированных с ним записей ресурсов (resource records). Эти записи являются базой данных DNS. Для одного хоста запись ресурсов чаще всего представляет собой просто его IP-адрес, но существует еще много других записей. Когда распознаватель передает имя домена DNS-серверу, то, что он получает обратно, представляет собой записи ресурсов, ассоциированные с этим именем. Таким образом, основная функция системы DNS заключается в преобразовании доменных имен в записи ресурсов.
Записи ресурса состоят из пяти частей. Хотя для эффективности они часто перекодируются в двоичную форму, в большинстве описаний они представлены в виде ASCII-текста, по одной строке на каждую запись:
Domain_name Time_to_live Class Type Value
Поле Domain_name (Имя домена) сообщает, к какому домену относится текущая запись. Обычно для каждого домена имеется несколько записей ресурсов, и каждая копия базы данных хранит информацию о множестве доменов. Поле имени домена используется в качестве первичного ключа поиска при выполнении запросов. Порядок записей в базе данных значения не имеет.
Поле Time_to_live указывает, насколько стабильно состояние записи. Редко меняющимся данным присваивается высокое значение этого поля, например 86 400 (число секунд в сутках). Если же информация непостоянна (как, например, курсы акций) или ее вынуждены часто менять операторы сетей (например, для балансировки нагрузки при использовании одного имени для нескольких IP-адресов), то ей может быть присвоено небольшое значение, такое как 60 с (1 мин). Мы вернемся к этому вопросу, когда будем обсуждать кэширование.
Третье поле в записи ресурсов — Class (Класс). Для интернет-информации это всегда IN. Для прочей информации применяются другие коды, но на практике они встречаются редко.
Поле Type сообщает тип записи. Существует много типов DNS-записей. Наиболее важные из них