глава 14 dns: система имен доменов система имен доменов (dns - domain name system) это распределенная база данных, которая используется приложениями tcp/ip, для установления соответствия между именами хостов и ip адресами. dns также используется для маршрутизации электронной почты. мы используем термин распределенная, потому что на одном узле internet не хранится вся необходимая информация. каждый узел (университет, университетский городок, компания или отдел внутри компании) поддерживает собственую информационную базу данных и запускает программу сервер, которая может отправить запрос по internet к другим системам. dns предоставляет протокол, который позволяет клиентам и серверам общаться друг с другом. с точки зрения приложения, доступ к dns осуществляется посредством разборщика (resolver) (разборщик (resolver) - подпрограммы, которые используются для создания, отправки и интерпретации пакетов, используемых серверами имен internet). в unix системах, к разборщику можно получить доступ через две библиотечные функции, gethostbyname(3) и gethostbyaddr(3), которые линкуются с приложением, когда оно строится. первая воспринимает в качестве аргумента имя хоста и возвращает ip адрес, а вторая воспринимает в качестве аргумента ip адрес и возвращает имя хоста. разборщик устанавливает контакты с одним или несколькими серверами dns (name servers), чтобы установить это соответствие. на рисунке 4.2 показано, что разборщик - это часть приложения. он не является частью ядра операционной системы как протоколы tcp/ip. приложение должно конвертировать имя хоста в ip адрес, перед тем как оно попросит tcp открыть соединение или послать датаграмму с использованием udp. протоколы tcp/ip внутри ядра ничего не знают о dns. в этой главе мы рассмотрим, как разборщики общаются с dns серверами с использованием протоколов tcp/ip (в основном udp). однако мы не будем рассматривать установку и администрирование dns серверов или все опции, существующие у разборщиков и серверов. это может составить еще одну книгу. (в публикации [albitz and liu 1992] приведены подробности функционирования стандартных unix разборщиков и серверов dns.) rfc 1034 [mockapetris 1987a] описывает концепции, лежащие в основе dns, а rfc 1035 [mockapetris 1987b] содержит подробности разработки и спецификации dns. наиболее широкоиспользуемая реализация dns, как разборщика, так и сервера - bind (berkeley internet name domain). процесс сервера называется named. анализ траффика, генерируемого dns в глобальных сетях, приводится в [danzig, obraczka, and kumar 1992]. пространство имен dns имеет иерархическую структуру, которая внешне напоминает файловую систему unix. на рисунке 14.1 показана иерархическая организация dns. рисунок 14.1 иерархическая организация dns.
каждый узел (кружочки на рисунке 14.1) имеет метку длиной до 63 символов. корень дерева это специальный узел без метки. метки могут содержать заглавные буквы или маленькие. имя домена (domain name) для любого узла в дереве - это последовательность меток, которая начинается с узла выступающего в роли корня, при этом метки разделяются точками. (здесь видно отличие от файловой системы unix, где полный путь всегда начинается с вершины (корня) и опускается вниз по дереву.) каждый узел дерева должен иметь уникальное имя домена, однако одинаковые метки могут быть использованы в различных точках дерева. имя домена, которое заканчивается точкой, называется абсолютным именем домена (absolute domain name) или полным именем домена (fqdn - fully qualified domain name). например, sun.tuc.noao.edu.. если имя домена не заканчивается на точку, подразумевается, что имя должно быть завершено. как будет закончено имя, зависит от используемого программного обеспечения dns. если незаконченное имя состоит из двух или более меток, его можно воспринимать как законченное или полное; иначе справа от имени должен быть добавлен локальный суффикс. например, имя sun может быть завершено локальным суффиксом .tuc.noao.edu.. домены верхнего уровня поделены на три зоны:
на рисунке 14.2 приведен список обычной классификации семи основных доменов.
рисунок 14.2 3-символьные общие домены.
иногда считается, что 3-символьные общие домены используются только организациями соединенных штатов, а 2-символьные домены стран всеми остальными, однако это не так. существуют неамериканские организации в основных доменах, и множество организаций в соединенных штатах находятся в домене страны .us. (rfc 1480 [cooper and postel 1993] описывает домен .us более подробно.) единственные общие домены, которые закреплены за соединенными штатами, это .gov и .mil. многие 2-символьные домены стран второго уровня, очень похожи на основные домены: .ac.uk, например, принадлежит академическим институтам, а .co.uk коммерческим организациям великобритании. одна важная характеристика dns, не показанная на рисунке 14.1, это передача ответственности внутри dns. не существует организации, которая бы управляла и обслуживала все дерево в целом и каждую метку в отдельности. вместо этого, одна организация (nic) обслуживает только часть дерева (домены верхнего уровня), а ответственность за определенные зоны передает другим организациям. зона (zone) это отдельно администрируемая часть дерева dns. например, домен второго уровня noao.edu это отдельная зона. многие домены второго уровня поделены на меньшие зоны. например, университет может поделить свою зону на подзоны по факультетам, а компания может поделить себя на зоны по принципу деления на филиалы или отделы. если вы знакомы с файловой системой unix, то обратите внимание, что деление дерева dns на зоны очень напоминает деление на логические файловые системы физических дисковых разделов. однако мы не можем сказать, основываясь на рисунке 14.1, под чьим руководством находятся зоны, также как мы не можем по подобному рисунку сказать, какие директории в файловой системе находятся в определенном дисковом разделе.
с того момента, как выбрана организация или персона, которая несет ответственность за управление зоной, эта организация или персона должна организовать несколько серверов dns (name servers) для этой зоны. как только в зоне появляется новая система, администратор этой зоны помещает имя и ip адрес нового хоста в базу данных сервера dns. в небольших университетах, например, один человек может делать это каждый раз при появлении новой системы, однако в больших университетах ответственность должна быть распределена (например, по департаментам), так как один человек не может осуществлять эту работу в целом. сервер dns, скажем, обслуживает одну зону или несколько зон. человек, который несет ответственность за зону, администрирует основной сервер dns (primary name server) для этой зоны и один или несколько вторичных серверов dns (secondary name servers). первичный и вторичный сервера должны быть независимы и избыточны таким образом, чтобы система dns не вышла из строя при отказе одного из серверов. основное отличие между первичными и вторичными серверами заключается в том, что первичные загружают всю необходимую информацию из дисковых файлов, тогда как вторичные получают информацию от первичного. процесс передачи информации от первичного сервера вторичному называется передачей зоны (zone transfer). когда в зоне появляется новый хост, администратор добавляет соответствующую информацию (минимум, имя и ip адрес) в дисковый файл на первичном сервере. после чего первичный сервер dns уведомляется о необходимости повторно считать свои конфигурационные файлы. вторичные сервера регулярно опрашивают первичные (обычно каждые 3 часа), и если первичные содержат новую информацию, вторичный получает ее с использованием передачи зоны. что произойдет, если сервер dns не содержит необходимой информации? он должен установить контакт с другим сервером dns. (в этом заключается распределенная природа dns.) однако не каждый сервер dns знает, как обратиться к другому серверу. вместо этого каждый сервер dns должен знать, как установить контакт с корневыми серверами dns (root name servers). в апреле 1993 года существовало восемь корневых серверов, все первичные сервера должны знать ip адреса каждого корневого сервера. (эти ip адреса находятся в конфигурационных файлах первичного сервера. первичные сервера должны знать именно ip адреса корневых серверов, а не их dns имена.) корневой сервер, в свою очередь, знает имена и положения (ip адрес) каждого официального сервера dns для всех доменов второго уровня. при этом возникает последовательный процесс: запрашивающий сервер должен установить контакт с корневым сервером. корневой сервер сообщает запрашивающему серверу о необходимости обратиться к другому серверу и так далее. мы рассмотрим эту процедуру и соответствующие примеры позже в этой главе. вы можете получить текущий список корневых серверов, воспользовавшись анонимным (anonymous) ftp. получите файл netinfo/root-servers.txt с ftp.rs.internic.net или nic.ddn.mil.
фундаментальная характеристика dns - это кэширование (caching). когда dns сервер получает информацию о соответствии (скажем, ip адресов именам хостов), он кэширует эту информацию таким образом, что в случае следующего запроса может быть использована информация из кэша, дополнительный запрос на другие сервера не делается. в разделе "кэширование" этой главы мы рассмотрим кэширование более подробно. для dns запроса и для dns отклика используется одинаковый формат. на рисунке 14.3 показан общий формат dns сообщения. рисунок 14.3 общий формат dns запроса и ответа.
сообщение содержит фиксированный 12-байтный заголовок, за которым следуют четыре поля переменной длины. значение в поле идентификации (identification) устанавливается клиентом и возвращается сервером. это поле позволяет клиенту определить, на какой запрос пришел отклик. 16-битовое поле флагов (flags) поделено на несколько частей, как показано на рисунке 14.4. рисунок 14.4 поле флагов (flags) в заголовке dns.
описание каждого поля мы начнем с крайне левых битов.
следующие четыре 16-битных поля указывают на количество пунктов в четырех полях переменной длины, которые завершают запись. в запросе количество вопросов (number of questions) обычно равно 1, а остальные три счетчика равны 0. в отклике количество ответов (number of answers) по меньшей мере равно 1, а оставшиеся два счетчика могут быть как нулевыми, так и ненулевыми. раздел вопросов в dns запросе формат каждого вопроса в разделе вопросов (question) показан на рисунке 14.5. обычно присутствует только один вопрос. имя запроса (query name) это искомое имя. оно выглядит как последовательность из одной или нескольких меток. каждая метка начинается с 1-байтового счетчика, который содержит количество следующих за ним байт. имя заканчивается байтом равным 0, который является меткой с нулевой длиной. и является, в свою очередь, меткой корня. каждый счетчик байтов должен быть в диапазоне от 0 до 63, так как длина метки ограничена 63 байтами. рисунок 14.5 формат раздела вопроса (question) в запросе dns.
(дальше в этом разделе мы увидим, что байт счетчик с двумя старшими битами, установленными в 1, значения от 192 до 255, используется в схеме со сжатием.) в отличие от многих других форматов сообщений, которые мы рассмотрели, этому полю разрешено заканчиваться на ограничителе не равном 32 битам. заполнение не используется. на рисунке 14.6 показано, как хранится имя домена gemini.tuc.noao.edu. рисунок 14.6 представление имени домена gemini.tuc.noao.edu.
у каждого вопроса есть тип запроса (query type), а каждый отклик (называемый записью ресурса, о чем мы поговорим ниже) имеет тип (type). существует около 20 различных значений, некоторые из которых в настоящее время уже устарели. на рисунке 14.7 показаны некоторые из этих значений. тип запроса это надмножество (множество, подмножеством которого является данное множество) типов: два из показанных значений, могут быть использованы только в вопросах.
рисунок 14.7 значения type и query type для dns вопросов и ответов.
наиболее распространенный тип запроса - тип a, который обозначает, что необходим ip адрес для запрашиваемого имени (query name). ptr запрос требует имена, соответствующие ip адресу. это запрос указателя, который мы опишем в разделе "запросы указателя" этой главы. другие типы запросов мы опишем в разделе "записи ресурсов" этой главы. класс запроса (query class) обычно равен 1, что указывает на адреса internet. (в некоторых случаях поддерживаются не-ip значения.) часть записи ресурса в отклике dns последние три поля в dns сообщении это ответы (answers), полномочия (authority) и дополнительная информация (additional information), общий формат называется записью ресурса (rr - resource record). на рисунке 14.8 показан формат записи ресурса. рисунок 14.8 формат записи ресурса dns.
имя домена (domain name) это имя, которому соответствуют следующие данные ресурса. формат имени домена тот же, что мы описали ранее для поля имени запроса (query name) (рисунок 14.6). тип (type) указывает на один из типов кодов rr. это то же самое, что и значения типа запроса (query type), которые мы описали раньше. для данных internet класс (class) обычно установлен в 1. поле время жизни (time-to-live) это количество секунд, в течение которых rr может быть кэширована клиентом. обычно ttl rr равно 2 дням. длина записи ресурса (resource data length) указывает на количество данных ресурса (resource data). формат этих данных зависит от типа (type). для типа равного 1 (запись a) данные ресурса - это 4-байтный ip адрес. сейчас мы описали основной формат dns запросов и откликов. теперь посмотрим с использованием tcpdump, как они упаковываются в пакеты и как происходит обмен. давайте посмотрим, как происходит общение между разборщиком и сервером dns. мы запустили клиента telnet с хоста sun на хост gemini, подключившись к серверу времени:
в этом примере мы указали разборщику на хосте sun (где запущен клиент telnet) использовать сервер dns на хосте noao.edu (140.252.1.54). на рисунке 14.9 показано взаимное расположение этих трех систем. рисунок 14.9 системы, используемые в примере работы dns.
как мы уже упомянули ранее, разборщик является частью клиента. он устанавливает контакт с сервером dns, чтобы получить ip адрес, перед тем как будет установлено tcp соединение между telnet и сервером времени. на этом рисунке мы опустили подробности, описывающие, как происходит общение между sun и ethernet сетью 140.252.1, которое в действительности осуществляется по slip каналу, потому что это не относится к нашим рассуждениям. мы запустим tcpdump на slip канале, чтобы посмотреть, как происходит обмен пакетами между разборщиком и сервером dns. файл /etc/resolv.conf на хосте sun сообщает разборщику о необходимости сделать следующее: sun % cat /etc/resolv.conf nameserver 140.252.1.54 domain tuc.noao.edu
первая строка сообщает ip адрес dns сервера - хоста noao.edu. может быть указано до трех строк nameserver, таким образом, будет обеспечен запасной сервер на случай, если один из них выключен или недоступен. строка domain содержит домен по умолчанию. если искомое имя не является полным именем домена (не заканчивается точкой), к имени добавляется имя домена по умолчанию .tuc.noao.edu. именно поэтому мы можем ввести telnet gemini вместо telnet gemini.tuc.noao.edu. на рисунке 14.10 показан обмен пакетами между разборщиком и сервером dns.
рисунок 14.10 вывод команды tcpdump для запроса на сервер dns на хосте gemini.tuc.noao.edu.
мы проинструктировали tcpdump не печатать имена доменов для ip адресов источника и назначения каждой ip датаграммы. вместо этого он печатает 140.252.1.29 для клиента (разборщик) и 140.252.1.54 для сервера dns. порт 1447, используемый клиентом, это порт, назначаемый динамически, а 53 это заранее известный порт dns сервера. если tcpdump постарается напечатать имена вместо ip адресов, ему придется обратиться к тому же dns серверу (осуществляя запрос указателя), что может привести к нежелательному выводу. начиная со строки 1, поле после двоеточия (1+) означает, что поле идентификации равно 1, а знак плюс обозначает, что установлен флаг rd (требуется рекурсия). мы видим, что по умолчанию разборщик требует рекурсию. следующее поле, a?, означает, что тип запроса - a (мы хотим получить ip адрес), а маркировка вопроса обозначает, что это запрос (не ответ). затем печатается имя запроса: gemini.tuc.noao.edu.. разборщик добавляет последнюю точку к имени запроса, указывая на то, что это абсолютное имя домена. длина пользовательских данных в udp датаграмме составляет 37 байт: 12 байт - заголовок фиксированного размера (рисунок 14.3), 21 байт - имя запроса (рисунок 14.6) и 4 байта - тип запроса и класс запроса. то что udp датаграмма имеет нечетную длину напоминает нам, что в dns сообщениях не используются биты заполнения. строка 2 в выводе команды tcpdump это ответ от dns сервера, где 1* в поле идентификации со звездочкой обозначает, что установлен флаг aa (авторитетный ответ). (мы ожидали от сервера именно этого, так как первичный сервер для домена noao.edu имеет полное представление об именах внутри этого домена.) вывод 2/0/0 показывает количество записей ресурсов в трех последних полях с переменной длиной отклика: 2 ответ rr, 0 полномочия rr и 0 дополнительные rr. команда tcpdump печатает только первый ответ, который в данном случае имеет тип a (ip адрес) со значением 140.252.1.11. почему мы получили два ответа на наш запрос? потому что хост gemini имеет несколько интерфейсов. поэтому возвращено два ip адреса. другое полезное средство, использующее dns, - это программа host. она позволяет нам отправить запрос на dns сервер и посмотреть что вернется. если мы запустим эту программу, то увидим два ip адреса для хоста gemini: sun % host gemini gemini.tuc.noao.edu a 140.252.1.11 gemini.tuc.noao.edu a 140.252.3.54
первый ответ на рисунке 14.10 и первая строка вывода команды host - ip адрес, принадлежащий той же подсети (140.252.1), что и запрашивающий хост. в этом нет ничего странного. если сервер dns и хост, отправляющий запрос, находятся в той же самой сети (или подсети), bind сортирует результаты таким образом, чтобы адреса, принадлежащие общей сети, появлялись в первую очередь. мы также можем получить доступ к хосту gemini с использованием другого адреса, однако это будет не так эффективно. с использованием traceroute в этом примере можно увидеть, что обычный путь от подсети 140.252.1 к 140.252.3 не проходит через хост gemini, а проходит через другой маршрутизатор, который подключен к обеим сетям. в данном случае, если мы получим доступ к gemini через другой ip адрес (140.252.3.54), все пакеты потребуют еще одной дополнительной пересылки. мы вернемся к этому примеру и рассмотрим более подробно причины, по которым используется альтернативный маршрут, в разделе "дополнительные примеры" главы 25, где мы сможем использовать snmp, чтобы посмотреть таблицу маршрутизации маршрутизатора. существуют и другие программы, предоставляющие простой интерактивный доступ к dns. программа nslookup поставляется с большинством реализаций dns. глава 10 [albitz and liu 1992] подробно описывает эту программу. программа dig (domain internet groper) это еще одна общедоступная программа, с помощью которой можно отправить запросы на dns сервера. программа doc (domain obscenity control) - shellовский скрипт, который использует dig и диагностирует поведение доменов, отправляя запросы на соответствующие dns сервера и осуществляя простой анализ откликов. в приложении f подробно рассказано, как можно получить эти программы. и последняя деталь, на которую необходимо обратить внимание в этом примере, это размер udp данных в отклике: 69 байт. чтобы объяснить эту величину, надо знать две вещи.
на рисунке 14.11 показан формат dns отклика, что соответствует строке 2 на рисунке 14.10. здесь показаны ip и udp заголовки, чтобы напомнить о том, что dns сообщения обычно инкапсулируются в udp датаграммы. мы специально показали байты счетчики в метках имен доменов в вопросе. два возвращенных ответа одинаковы, за исключением различных ip адресов. в этом примере каждый указатель в ответе имеет значение 12, что является смещением от начала dns заголовка полного имени домена. и последнее, на что необходимо обратить внимание, это вторая строка из вывода команды telnet, которая повторена здесь:
рисунок 14.11 формат dns отклика, соответствующий строке 2 на рисунке 14.10.
мы указали только имя хоста (gemini), а не полное имя домена (fqdn) , однако клиент telnet вывел именно полное имя домена. в данном случае клиент telnet ищет имя, которое мы ввели, вызвав разборщик (gethostbyname), который возвращает ip адрес и fqdn. затем telnet выводит ip адрес, с которым он старается установить tcp соединение, и когда соединение установлено, печатает fqdn. пауза между вводом команды telnet и печатью ip адреса, вызвана тем, что разборщик устанавливает контакт с dns сервером, чтобы преобразовать имя в ip адрес. пауза между выводом trying и connected to, вызвана установлением tcp соединения между клиентом и сервером, а не dns. для понимания работы dns важно знать, как обрабатываются запросы указателя - задан ip адрес, возвращается имя (или имена), соответствующее этому адресу. во-первых, вернемся к рисунку 14.1 и рассмотрим домен верхнего уровня arpa, а также домен in-addr, находящийся ниже. когда организация вступает в internet и получает часть простраства имен dns, как, например, noao.edu, она также получает право на часть пространства имен in-addr.arpa, соответствующее ее ip адресам в internet. в данном случае noao.edu - это сеть класса b с идентификатором 140.252. уровень дерева dns ниже in-addr.arpa должен быть первым байтом ip адреса (140 в данном примере), следующий уровень это следующий байт ip адреса (252), и так далее. однако помните, что имена пишутся, снизу-вверх по дереву dns. это означает, что dns имя хоста sun с ip адресом 140.252.13.33 будет 33.13.252.140.in-addr.arpa. мы должны написать 4 байта ip адреса задом наперед, потому что полномочия делегируются на основе идентификаторов сетей: первый байт адрес класса a, первый и второй байты адреса класса b, а первый, второй и третий байты это адреса класса c. первый байт ip адреса должен быть непосредственно под меткой in-addr, однако полные имена доменов (fqdn) пишутся снизу вверх по дереву. если бы fqdn писались сверху вниз, dns имя для ip адреса было бы arpa.in-addr.140.252.13.33, однако в этом случае fqdn для хоста должно быть edu.noao.tuc.sun. без отдельных ветвей дерева dns осуществить преобразования адрес - имя, (обратное преобразование) можно было бы только начиная от корня дерева и просматривая каждый домен верхнего уровня. при сегодняшнем размере internet это могло бы занять дни или даже недели. использование же in-addr.arpa приемлемый вариант, несмотря на переставленные местами байты в ip адресе и специальные домены, иногда вносящие определенную путаницу. однако встретиться с доменом in-addr.arpa и переставленными байтами в ip адресе можно только тогда, когда мы общаемся с dns непосредственно, используя, такие программы как host или просматривая пакеты с использованием tcpdump. при работе приложения, разборщик (gethostbyaddr) обычно воспринимает ip адрес и возвращает информацию о хосте. перестановка байтов и добавление домена in-addr.arpa осуществляется разборщиком автоматически. пример давайте воспользуемся программой host, чтобы осуществить поиск указателя, и при этом просмотрим с использованием tcpdump как происходит обмен пакетами. мы используем те же начальные установки как на рисунке 14.9, запустив программу host на хосте sun с тем же самым сервером dns noao.edu. мы указали ip адрес нашего хоста svr4: sun % host 140.252.13.34 name: svr4.tuc.noao.edu address: 140.252.13.34
так как единственный аргумент в командной строке это ip адрес, программа host автоматически генерирует запрос указателя. на рисунке 14.12 показан вывод команды tcpdump.
рисунок 14.12 вывод tcpdump для запроса указателя.
из строки 1 видно, что идентификатор равен 1, установлен флаг требования рекурсии (знак плюс), и тип запроса это ptr. (вспомним, что марка вопроса обозначает, что это запрос, а не отклик.) размер данных составляет 44 байта, из которых 12 байт - dns заголовок, 28 байт - 7 меток в имени домена, и 4 байта это тип запроса и класс запроса. в отклике установлен бит авторитетного ответа (звездочка) и содержится одна запись ресурса (rr) ответа. тип rr это ptr, а данные ресурса содержат имя домена. от разборщика к серверу dns в качестве запроса указателя передается не 32-битный ip адрес, а имя домена 34.13.252.140.in-addr.arpa. проверка неправильного имени хоста когда ip датаграмма прибывает на хост сервера, будь то udp датаграмма или tcp сегмент с требованием установить соединение, все что доступно процессу сервера это ip адрес клиента и номер порта (udp или tcp). некоторые сервера требуют, чтобы ip адрес клиента имел запись указателя в dns. в разделе "примеры ftp" главы 27 мы рассмотрим пример, иллюстрирующий это, используя анонимный ftp с неизвестного ip адреса. другие серверы, как, например, сервер rlogin (глава 26), требуют не только то, чтобы ip адрес клиента имел запись указателя, но и еще спрашивают dns об ip адресе, соответствующем имени, возвращенном в ptr отклике, и требуют, чтобы один из возвращенных адресов совпадал с ip адресом в принятой датаграмме. эта проверка осуществляется потому, что пункты в файле .rhosts (глава 26, раздел "протокол rlogin") содержат имя хоста, а не ip адрес; таким образом, сервер хочет убедиться, что имя хоста действительно соответствует входящему ip адресу. некоторые производители автоматически помещают эту проверку в программы разборщика, конкретно в функцию gethostbyaddr. при этом подобная проверка становится доступной для любой программы, использующей разборщик. отпадает необходимость помещать эту проверку в каждое приложение. мы можем увидеть, как это происходит, с помощью библиотеки разборщика sunos 4.1.3. мы написали простую программу, которая осуществляет запрос указателя путем вызова функции gethostbyaddr. также мы поместили записи в файл /etc/resolv.conf таким образом, чтобы использовать в качестве dns сервера хост noao.edu, получить доступ к которому можно через slip канал с хоста sun. на рисунке 14.13 показан вывод команды tcpdump, полученный от slip канала, при вызове функции gethostbyaddr, в случае, когда получается имя, соответствующее ip адресу 140.252.1.29 (хост sun).
рисунок 14.13 вызов функции разборщика, которая осуществляет запрос указателя.
в строке 1 запрос указателя, в строке 2 отклик. однако, функция разборщика автоматически посылает запрос об ip адресе в строке 3 на имя, возвращенное в строке 2. отклик в строке 4 содержит две записи ответа, так как хост sun имеет два ip адреса. если ни один из адресов не совпал с аргументом gethostbyaddr, отправляется сообщение системе, которая фиксирует событие, а функция возвращает ошибку приложению. мы видели несколько различных типов записей ресурса (rr), а именно: ip адрес имеет тип a, а ptr обозначает запрос указателя. также мы видели rr, которые возвращает dns сервер: rr ответа, rr полномочий и rr дополнительной информации. всего существует около 20 различных типов записей ресурсов, некоторые из которых мы сейчас опишем.
а ptr cname
здесь мы использовали опцию -t, чтобы указать на один конкретный тип запроса. hinfo
mx многие хосты, которые не подключены к internet, имеют uucp каналы к хостам, подключеным к internet, как, например, uunet. с помощью записи mx обеспечивается передача электронной почты с использованием стандартного обращения user@host (пользователь@хост). например, фиктивный домен foo.com может иметь следующую mx запись:
mx записи используются программами доставки почты на хостах, подключенных к internet. в этом примере программа доставки почты говорит "если у тебя есть почта, которую необходимо послать на user@foo.com, пошли почту на relay1.uu.net или на relay2.uu.net". в каждой записи mx есть 16-битное целое значение, которое называется значением предпочтительности. если для одного пункта назначения существует несколько mx записей, они будут использованы по порядку, начиная с той записи, у которой наименьшее значение предпочтительности. записи mx используются, когда хост выключен или недоступен. в этом случае программа доставки почты использует mx записи только в том случае, если не может подсоединиться к пункту назначения с использованием tcp. для объединенных сетей, с которыми экспериментировал автор, его основная система подключена к internet через slip канал, и если она не работает, мы получим:
опцию -v позволяет посмотреть значения предпочтительности. (благодаря этой опции в выводе появятся и все другие поля.) второе поле, 86400, - это время жизни в секундах. время жизни равно 24 часам (24х60х60). третья колонка, in, это класс (internet). мы видим, что непосредственная доставка на хост (первая запись mx) имеет наименьшее значение предпочтительности равное 0. если это не работает (slip канал выключен), используется следующее более высокое значение предпочтительности (10), и делается попытка доставить почту на хост noao.edu. если и это не сработает, отправитель отработает тайм-аут и повторит попытки позже. в разделе "примеры smtp" главы 28 мы покажем примеры доставки почты smtp с использованием записей mx. ns
это общие типы rr. в следующих примерах мы увидим еще некоторые типы. чтобы уменьшить траффик dns в internet, все сервера dns используют кэширование. в стандартных unix реализациях кэш поддерживается сервером, а не разборщиком. так как разборщик является частью каждого приложения, а приложения приходят и уходят, оставляя кэш в программах, которые живут все время, пока система работает (сервер dns), имеет смысл поддерживать кэш именно на сервере. при этом кэш доступен любому приложению, которое использует сервер. любые другие хосты в узле, которые используют этот сервер dns, также пользуются кэшем сервера. в примерах (рисунок 14.9), мы запускали клиентов на хосте sun, и обращались к dns серверу на хост noao.edu через slip канал. сейчас попробуем запустить dns сервер на хосте sun. в этом случае, если просмотреть с использованием tcpdump траффик dns в slip канале, мы увидим только запросы, которые не могут быть обработаны сервером в своем собственном кэше. по умолчанию разборщик ищет сервер dns на локальном хосте (udp порт 53 или tcp порт 53). мы удалили запись nameserver из файла разборщика, оставив только запись domain: sun % cat /etc/resolv.conf domain tuc.noao.edu
отсутствие записи nameserver в этом файле приводит к тому, что разборщик пользуется сервером dns на локальном хосте. затем мы запустили команду host следующим образом:
на рисунке 14.14 показан вывод команды tcpdump для этого запроса.
рисунок 14.14 вывод tcpdump для: host ftp.uu.net. появилась новая опция программы tcpdump. мы получаем все данные, направляющиеся к или от udp или tcp портов 53, с помощью опции -w. в этом случае весь символьный вывод сохраняется в файле для дальнейшей обработки. при этом tcpdump не пытается вызвать свой собственный разборщик, чтобы напечатать все имена, соответствующие ip адресам. после того как запущены все запросы, мы перезапустили tcpdump с опцией -r. в этом случае программа читает выходной файл и генерирует обычный вывод (который показан на рисунке 14.14). это занимает несколько секунд, так как tcpdump вызывает свой разборщик.
первое на что необходимо обратить внимание в выводе tcpdump, это то, что идентификаторы представляют собой небольшие целые числа (2 и 3). это потому, что мы выключили сервер dns и затем перестартовали его, чтобы очистить кэш. когда сервер dns стартует, он устанавливает идентификатор в 1. затем мы ввели запрос, в котором требуется получить ip адрес для хоста ftp.uu.net, dns сервер установил соединение с одним из восьми корневых серверов, ns.nic.ddn.mil (строка 1). это обычный запрос типа a, который мы уже видели ранее, однако обратите внимание, что флаг требования рекурсии не установлен. (если флаг установлен, после идентификатора 2 должен быть напечатан знак плюс.) в наших предыдущих примерах говорилось, что разборщик устанавливает флаг необходимости рекурсии, однако здесь мы видим, что наш сервер dns не установил флаг, когда он обратился к одному из корневых серверов. это произошло потому, что от корневых серверов нельзя требовать рекурсивных ответов - они должны быть использованы только для того, чтобы найти адреса к другим полномочным серверам. из строки 2 видно, что отклик пришел назад без записи ресурса (rr) ответа, с пятью rr полномочий и пятью rr дополнительной информации. знак минус, следующий за идентификатором 2, означает, что флаг "рекурсия возможна" (ra) не установлен - этот корневой сервер не ответит на рекурсивный запрос, даже если мы его об этом попросим. несмотря на то, что tcpdump не напечатал 10 записей ресурсов, которые были возвращены, мы можем исполнить команду host, чтобы посмотреть, что находится в кэше:
в этот раз мы указали опцию -v, чтобы увидеть не только записи a. вывод показывает, что в домене uu.net присутствует пять полномочных dns серверов. пять rr с дополнительной информацией, которые были возвращены корневым серверам, содержат ip адреса этих пяти dns серверов. поэтому у нас нет необходимости снова устанавливать контакт с корневым сервером, чтобы найти адрес одного из этих серверов. это еще одно из расширений реализации, сделанное в dns. команда host определяет, что ответ не авторитетный. это произошло из-за того, что ответ был получен из кэша нашего dns сервера, а не в результате контакта с полномочным сервером. вернемся к строке 3 на рисунке 14.14; сервер dns установил контакт с первым полномочным сервером (ns.uu.net) с тем же самым вопросом: какой ip адрес ftp.uu.net? на этот раз наш сервер установил флаг "рекурсия необходима". ответ, возвращенный в строке 4 - это отклик с одним ответом rr. затем мы снова исполнили команду host, спрашивая о том же самом имени:
это как раз то, что мы и ожидали, потому что ответ на команду host был получен из кэша сервера. мы исполнили команду host снова в поисках адреса для ftp.ee.lbl.gov:
на рисунке 14.15 показан вывод команды tcpdump.
рисунок 14.15 вывод tcpdump для: host ftp.ee.lbl.gov. из строки 1 видно, что теперь наш сервер установил контакт с другим корневым сервером (c.nyser.net). сервер dns обычно циклически опрашивает различные серверы для зоны, при этом накапливается информация о времени отклика от того или иного сервера. и, в конце концов, будет использован тот сервер, время возврата от которого минимально.
так как наш сервер установил контакт с корневым сервером, флаг "рекурсия необходима" не установлен. корневой сервер не сбросил флаг "рекурсия возможна", как мы видели в строке 2 на рисунке 14.14. (даже если так, dns сервер все равно не должен запрашивать корневой сервер с помощью рекурсивного запроса.) в строке 2 отклик приходит назад без ответа, однако с четырьмя rr полномочий и четырьмя rr дополнительной информации. как мы можем догадаться, четыре rr полномочий это имена dns серверов для ftp.ee.lbl.gov, а другие четыре rr содержат ip адреса этих четырех серверов. строка 3 - это запрос на сервер ns1.lbl.gov (первый из четырех dns серверов, полученных в строке 2). флаг "рекурсия необходима" установлен. отклик в строке 4 отличается от предыдущих откликов. возвращено два rr ответа, и tcpdump сообщает, что первый - это rr cname. каноническое имя для ftp.ee.lbl.gov - это ee.lbl.gov. это общепринятое использование записи cname. ftp узел для lbl всегда имеет имя, начинающееся с ftp, однако время от времени он может перемещаться с одного хоста на другой. пользователям достаточно знать только имя ftp.ee.lbl.gov, а dns сама установит соответствие с тем или иным хостом.
вспомните, что когда мы запускали host, он печатал и cname и ip адрес, соответствующий каноническому имени. это потому, что отклик (строка 4 на рисунке 14.15) содержит два rr ответа. первый это cname, второй это запись a. если запись a не была возвращена вместе с cname, наш сервер пошлет еще один запрос, спрашивая ip адрес ee.lbl.gov. это еще одна оптимизация реализации: cname и запись a канонического имени возвращается в одном отклике. мы уже упоминали, что заранее известные номера портов для dns серверов - udp порт 53 и tcp порт 53. это означает, что dns поддерживает как udp, так и tcp. однако все примеры, которые мы просмотрели с использованием tcpdump, использовали udp. когда используется тот или иной протокол и почему? когда разборщик выдает запрос и возвращается отклик с установленным битом tc (обрезано - truncated), это означает, что размер отклика превысил 512 байт, только первые 512 байт были возвращены серверу. разборщик обычно отправляет запрос снова, но уже с использованием tcp. при этом возвращается больше, чем 512 байт. (вспомните описание максимального размера udp датаграммы в разделе "максимальный размер udp датаграммы" главы 11.) так как tcp делит поток данных на части, которые называются сегментами, он может передать любое количество пользовательских данных с использованием нескольких сегментов. также, когда в домене включается вторичный сервер dns, он осуществляет передачу зоны с первичного сервера домена. мы также говорили, что вторичный сервер регулярно запрашивает первичный (обычно каждые три часа). при этом определяется, не обновил ли первичный сервер свою таблицу, и если да, то осуществляется передача зоны. передача зоны осуществляется с использованием tcp, так как в этом случае передается значительно больше данных, чем в случае одного запроса или отклика. так как dns в основном использует udp, и разборщик, и сервер dns должны отработать свой собственный тайм-аут и осуществить повторную передачу. в отличие от других приложений internet, которые используют udp (tftp, bootp и snmp) и которые функционируют обычно в локальных сетях, dns отправляет запросы и получает отклики обычно по глобальным сетям. процент потерянных пакетов и разница в значениях времен возврата обычно значительно выше в глобальных сетях, нежели в локальных, при этом повышается важность надежной передачи и четкости работы алгоритма расчета тайм-аутов для клиентов dns. давайте рассмотрим еще один пример, который описывает несколько функций dns, о которых мы рассказали раньше. мы запустили клиента rlogin, подсоединившись к rlogin серверу в каком-то удаленном домене. на рисунке 14.16 показан обмен пакетами. рисунок 14.16 обмен пакетами при старте rlogin клиента и сервера.
было осуществлено 11 шагов, при этом заранее никакой информации на клиенте или сервере кэшировано не было:
кэширование может уменьшить количество пакетов, которыми произошел обмен в этом примере. dns это одна из важнейших частей любого хоста, подключенного к internet, эта система также широко используется в частных объединенных сетях. основа организации - иерархическое дерево, которое формирует пространство имен dns. приложения обращаются к разборщикам, чтобы конвертировать имя хоста в ip адрес и наоборот. разборщики обращаются к локальным серверам dns, а они, свою очередь, могут обратиться к одному из корневых серверов или к другим серверам, чтобы получить ответ на запрос. все dns запросы и отклики имеют один и тот же формат. эти сообщения содержат записи ресурсов (rr) вопросов и, возможно, ответов, rr полномочий и rr дополнительной информации. мы рассмотрели множество примеров, в которых показана конфигурация разборщика и некоторые принципы организации dns: указатели на имена доменов (чтобы уменьшить размер сообщений), кэширование, домен in-addr.arpa (поиск имени по заданному ip адресу) и возвращаемые дополнительные rr (для того чтобы запрашивающий не выдавал повторный запрос).
упражнения
|