Когда адрес отвечает, а имя нет

В прошлом уроке мы прошли путь от собственного интерфейса до удалённого сервиса. Кульминацией была команда curl -I https://example.com, которая показала, что цепочка «имя → адрес → соединение → ответ» работает целиком. Но что делать, если цепочка рвётся на первом же звене? Пользователь набирает в браузере example.com, а браузер говорит, что не может найти сервер. При этом известный числовой адрес нужной машины отвечает на ping.

Это очень показательная ситуация. Числовой IP-адрес отвечает — значит, сетевой интерфейс работает, маршрут до машины есть, сама машина доступна. Но имя не преобразуется в адрес — значит, нужно проверить разрешение имён. В нём участвуют и локальные настройки, и DNS; соединение с самим DNS-сервером тоже может оказаться недоступным.

DNS — это распределённая система, которая переводит имена вроде example.com в IP-адреса. Она не проверяет, работает ли сервер по этому адресу. Она только отвечает на вопрос «какой адрес у этого имени?». Поэтому, когда имя не резолвится, а числовой адрес доступен, мы можем сразу сузить круг поиска: проверим путь получения адреса по имени, не считая всю сеть уже исправной.

Как система разрешает имена: getent ahosts

Прежде чем лезть в команды самого DNS, посмотрим, как наша система в целом превращает имя в адрес. Для этого есть команда getent ahosts:

getent ahosts example.com

Она выводит IP-адреса, связанные с именем, в виде, похожем на записи из системной базы данных. Условный пример структуры вывода (адреса не предназначены для подключения):

203.0.113.20   STREAM example.com
203.0.113.20   DGRAM
203.0.113.20   RAW
2606:2800:220:1:248:1893:25c8:1946 STREAM

Здесь мы видим и IPv4, и IPv6-адреса. Слова STREAM, DGRAM и RAW означают типы сокетов, для которых эти адреса применимы. Для наших целей важны сами адреса: система смогла по имени найти числовые эквиваленты.

Но getent ahosts — это не DNS-запрос в чистом виде. Система разрешает имена через механизм, который называется NSS — Name Service Switch. NSS определяет, в каком порядке и какие источники использовать. Обычно сначала смотрится файл /etc/hosts, где могут быть прописаны локальные соответствия имён и адресов, а затем, если там ничего не нашлось, запрашивается DNS по настройкам из /etc/resolv.conf. Поэтому, если имя найдено в /etc/hosts, DNS может вообще не понадобиться. Если же его там нет, в дело вступают DNS-серверы.

У такого подхода есть практическое следствие. Если getent ahosts example.com не выводит ничего или завершается с ошибкой, а числовой адрес доступен, мы знаем: сбой на этапе преобразования имени. Но где именно — в локальном файле, в настройках или в самом DNS — ещё предстоит выяснить. getent показывает результат всей цепочки, не указывая, какой источник сработал.

Спрашиваем DNS напрямую: dig

Теперь нам нужен инструмент, который говорит не с системой разрешения имён, а напрямую с DNS-сервером. Это команда dig. В Ubuntu её устанавливает пакет dnsutils; если команды нет, выполните sudo apt update, затем sudo apt install dnsutils.

Начнём с запроса A-записи, то есть IPv4-адреса:

dig example.com A

Вывод у dig довольно длинный, и мы разберём его по частям. Первая секция показывает детали запроса — какой сервер опрашивался, какой статус получен. Нас особенно интересует строка status:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345

Статус NOERROR означает, что запрос прошёл успешно: DNS-сервер не сообщил об ошибке обработки. Наличие нужной записи проверяем отдельно в ANSWER SECTION. Например:

;; ANSWER SECTION:
example.com.    3600    IN    A    203.0.113.20

Здесь example.com. — это имя, 3600 — TTL в секундах, IN — класс, A — тип записи, и в конце сам IPv4-адрес.

Теперь запросим AAAA-запись, то есть IPv6:

dig example.com AAAA

Структура ответа та же, но в конце будут адреса IPv6, записанные в шестнадцатеричном виде с двоеточиями. Для нашей учебной диагностики A-записи обычно важнее, но AAAA помогает увидеть, что у имени может быть несколько адресов разных типов.

Три статуса, которые нужно различать

Строка status в выводе dig — это первый и самый важный ориентир. Разберём три типичных случая.

NOERROR — запрос выполнен, имя существует. Но нужно быть внимательным: NOERROR с пустой ANSWER SECTION не означает, что имя не существует. Это означает, что у имени нет записей запрошенного типа. Например, если у example.com есть только A-запись, а мы спросили AAAA, DNS-сервер может вернуть NOERROR с пустым ответом, потому что сам запрос был корректен и имя существует, просто IPv6-адреса у него нет. Такое бывает часто.

NXDOMAIN — домен не существует. Опрошенный DNS-сервер сообщает, что запрошенного имени нет; это может быть ответ из кеша или ответ в своей области видимости DNS. Это принципиально другой результат. Если у имени нет A-записи, но сам домен существует, мы получим NOERROR с пустым ответом. Если домена нет вовсе — NXDOMAIN.

SERVFAIL — DNS-сервер не смог выполнить запрос по внутренним причинам: не сумел связаться с вышестоящим сервером, столкнулся с таймаутом, получил некорректные данные. Это не значит, что домен не существует. Это значит, что наша попытка узнать ответ не удалась, и стоит либо повторить запрос, либо проверить, какой DNS-сервер используется.

Различать эти три статуса важно, потому что они указывают на разные причины проблемы. При NXDOMAIN проверяем написание имени и правильность выбранного DNS-сервера: внутренние имена организации могут быть неизвестны внешнему серверу. NOERROR с пустым ответом — это корректный ответ на корректный вопрос, просто данных запрошенного типа нет. SERVFAIL — это сбой инфраструктуры, а не свойство имени.

CNAME и TTL

Иногда в ответе DNS вместо прямого адреса появляется другая запись. Например, имя www.example.com может быть не обычным адресом, а ссылкой на другое имя. Тогда в ответе будет CNAME, а следом — A-запись для целевого имени:

www.example.com.    3600    IN    CNAME   example.com.
example.com.        3600    IN    A       203.0.113.20

CNAME — это каноническое имя, alias. Он говорит: на самом деле это имя указывает на другое имя, и адрес нужно искать для того, другого. В выводе dig обе записи обычно идут вместе, но важно понимать, что CNAME сам по себе не является адресом. Это переадресация внутри DNS.

TTL — time to live — число секунд, в течение которых запись можно считать действительной и хранить в кеше. В наших примерах TTL равен 3600, то есть часу. Когда система или промежуточный сервер уже запрашивал это имя, он может не ходить в DNS снова, а отдать закешированный ответ, пока TTL не истечёт. Для диагностики это означает: после изменения DNS-записей старые ответы могут жить ещё какое-то время, и повторный запрос не сразу покажет новое значение.

DNS отвечает — но сервис недоступен

И наоборот: если dig возвращает SERVFAIL или NXDOMAIN, сервис может быть абсолютно доступен по числовому адресу, но пользователь всё равно не достучится по имени, потому что система не может превратить имя в адрес. Это разные уровни проверки, и их нельзя подменять друг другом.

Та же логика действует и для getent ahosts: команда показала, что система разрешила имя. Но дальше вступают в дело сетевые проверки из прошлого урока — маршрут, соединение, порт. DNS — первый этап, после которого всё остальное только начинается.

Смотрим настройки системы: /etc/resolv.conf

Часть настроек DNS-клиента можно увидеть в /etc/resolv.conf; это не полный перечень всех механизмов разрешения имён. Мы можем посмотреть на него, не редактируя:

ls -l /etc/resolv.conf
cat /etc/resolv.conf

Первая команда показывает, что это за файл. В некоторых системах это обычный файл, в других — символическая ссылка на файл, которым управляет служба. Вторая команда выводит его содержимое. Примерный вид:

nameserver 192.168.50.1
nameserver 10.0.0.1
search lan

Строки nameserver указывают DNS-серверы, которые система будет опрашивать. Порядок и условия обращения зависят от резолвера и его настроек. Несколько строк не означают, что клиент обязательно будет спрашивать всех серверов, пока не получит желаемый адрес. Строка search добавляет домен по умолчанию при запросе коротких имён.

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

В WSL настройки DNS могут формироваться иначе, чем в обычной Ubuntu. В некоторых конфигурациях используется промежуточный сервер, и файл resolv.conf может обновляться автоматически. Поэтому не нужно ожидать, что его содержимое будет одинаковым на всех машинах, и не нужно пытаться привести его к единому виду. Наша цель — прочитать и понять, а не исправить.

Если используется systemd-resolved: resolvectl

Во многих установках Ubuntu разрешением имён управляет служба systemd-resolved. Для работы с ней есть команда resolvectl. Она показывает текущее состояние и выполняет запросы через этот системный механизм.

Если служба доступна, посмотрим общий статус:

resolvectl status

Вывод покажет, какие DNS-серверы настроены для каждого сетевого интерфейса и какие домены поиска действуют. Это более современный взгляд на то же самое, что мы видели в /etc/resolv.conf, но с деталями по интерфейсам.

Конкретный запрос можно выполнить так:

resolvectl query example.com

Система выполнит разрешение имени через свой настроенный механизм и покажет адреса. По сути, это близко к getent ahosts, но с привязкой к systemd-resolved.

Здесь важна оговорка: resolvectl существует не во всех системах. В WSL он может быть недоступен, и тогда не нужно ничего специально включать или настраивать. Если команды нет, мы просто работаем с getent и dig и понимаем, что системный уровень и уровень DNS мы в такой системе смотрим разными способами. Отсутствие resolvectl — не поломка, а особенность конфигурации.

Почему curl по имени и по адресу — не одно и то же

Остался ещё один нюанс, который часто сбивает с толку. Допустим, мы нашли адрес через dig и хотим проверить сервис напрямую:

curl -I https://IP_АДРЕС

Это схема запроса, а не команда для копирования.

Будет ли это равнозначно запросу по имени? Даже HTTP-сервер может выбирать сайт по заголовку Host, поэтому запрос по адресу не обязательно попадёт на тот же сайт. Но для HTTPS всё сложнее. В HTTPS шифрование и проверка сертификата привязаны к имени. Когда мы открываем https://example.com, клиент на этапе установления TLS-соединения отправляет серверу специальное расширение SNI, в котором указывает имя example.com. Сервер по этому имени понимает, какой сертификат показать. Если мы подключились по голому IP-адресу, SNI не будет содержать ожидаемого имени, и сервер может ответить сертификатом по умолчанию или вовсе отказать в соединении.

Кроме того, curl проверяет сертификат на соответствие имени в URL. Если мы пришли по IP, сертификат выдан на имя example.com, и проверка не сойдётся. Curl сообщит об ошибке сертификата. Это не сетевой сбой и не ошибка DNS — это различие в том, как работают HTTP и HTTPS по именам и по числовым адресам.

Мы не будем учиться обходить проверку сертификата. Это путь к небезопасным привычкам. Достаточно понимать, что успешный dig и даже успешное TCP-соединение по адресу не означают, что HTTPS-запрос по этому адресу сработает так же, как по имени. Имя в HTTPS — часть протокола, а не просто человекочитаемая замена адреса.

Цепочка диагностики DNS

Соберём всё в одну последовательность. Пользователь говорит: «Имя не открывается». Мы сначала спрашиваем систему: getent ahosts example.com. Если система вернула адрес, значит, разрешение имён работает, и проблему нужно искать дальше по сети — в соединении, порту, сервисе. Если система адреса не вернула, переходим к DNS.

Проверяем напрямую: dig example.com A. Смотрим статус. Если dig получил ожидаемый адрес, а getent его не вернул, сравниваем источники и настройки системного разрешения имён. NXDOMAIN — опрошенный сервер сообщил об отсутствии имени; проверяем опечатку и то, тот ли сервер опрошен. NOERROR с пустым ответом — нужно уточнить, какой тип записи мы спрашивали и есть ли он вообще. SERVFAIL — сбой на стороне DNS, возможно, стоит повторить или посмотреть, какой сервер используется через /etc/resolv.conf или resolvectl status.

Параллельно помним, что DNS — только первый этап. Он не проверяет связь и не проверяет сервис. Даже когда имя разрешается идеально, остаются маршруты, порты, протоколы и приложение. Но именно DNS часто оказывается тем самым невидимым звеном, из-за которого всё остальное не может начаться.

Когда нужный числовой адрес отвечает, а его имя не разрешается, следующий этап проверки — разрешение имён, включая доступ к DNS-серверу. Система разрешает имена через NSS, который может использовать сначала локальный файл /etc/hosts, а затем DNS по настройкам из /etc/resolv.conf. Команда getent ahosts показывает итог всей системной цепочки, но не указывает, какой источник дал ответ. Команда dig обращается к DNS напрямую и позволяет увидеть статус ответа: NOERROR означает успех, NXDOMAIN — что домен не существует, SERVFAIL — что DNS-сервер не смог выполнить запрос. NOERROR с пустой секцией ответа не равен NXDOMAIN: это корректный ответ, просто у имени нет записей запрошенного типа. CNAME перенаправляет на другое имя, а TTL указывает, сколько секунд запись может храниться в кеше.

Успешный DNS-ответ не доказывает доступность сервиса: DNS только переводит имя в адрес и ничего не знает о портах, соединениях и работе приложения. Просмотр /etc/resolv.conf показывает, какие DNS-серверы настроены, но мы его не редактируем; в WSL настройки могут управляться автоматически. Если systemd-resolved доступен, resolvectl status и resolvectl query показывают системное разрешение имён, но его отсутствие не является поломкой. Прямой curl по IP-адресу не равнозначен запросу по имени для HTTPS из-за TLS и SNI, и обход проверки сертификата мы не изучаем.

Практика: DNS и его диагностика

В теории мы разобрали, как система разрешает имена через NSS, чем `getent ahosts` отличается от `dig` и что означают статусы NOERROR, NXDOMAIN и SERVFAIL. Теперь посмотрим на несколько конкретных выводов и потренируемся выбирать подходящую проверку. Задания не требуют править настройки: достаточно прочитать то, что уже есть, и рассуждать по данным.

getent и dig расходятся

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

11

На машине 192.168.50.10 выполнены две команды. Их выводы:

$ getent ahosts internal.test
192.168.50.77   STREAM internal.test
192.168.50.77   DGRAM
192.168.50.77   RAW

$ dig internal.test A
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 42111
;; QUESTION SECTION:
;internal.test.          IN      A
;; ANSWER SECTION:
(пусто)
;; SERVER: 192.168.50.1#53(192.168.50.1)

Файл /etc/hosts содержит строку 192.168.50.77 internal.test. Как объяснить расхождение? В этой задаче hosts-строка NSS имеет вид hosts: files dns, подходящая запись files завершает поиск; кеш разрешения имён отсутствует.

NOERROR с пустым ответом или NXDOMAIN

Две разные ситуации с одним и тем же именем, но с разными серверами. Нужно понять, что именно сообщает каждый ответ.

11

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

Учебная машина использует локальный DNS-сервер 192.168.50.1. Известно, что:

  • у имени sample.example.test есть только A-запись, AAAA-записи нет;
  • имя service.internal.test заведено только в зоне внутреннего сервера 192.168.50.1, у внешнего DNS-сервера его нет.

Выполнены две проверки:

$ dig sample.example.test AAAA
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50121
;; ANSWER SECTION:
(пусто)

$ dig service.internal.test A @9.9.9.9
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 50122
;; ANSWER SECTION:
(пусто)

Какой вывод верен?

Проверить DNS, не меняя настройки

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

Данные ниже заданы для разбора; 203.0.113.20 — адрес из документационного диапазона, выполнять запросы к нему не требуется.

Ситуация: на учебной машине пользователь жалуется, что portal.example.org открывается в браузере через раз. Известно, что:

  • числовой адрес 203.0.113.20, который, по словам коллеги, принадлежит этому сервису, отвечает на ping;
  • вы не хотите менять ни /etc/resolv.conf, ни настройки сети, ни публичные DNS-серверы;
  • в вашем распоряжении есть getent, dig, resolvectl (если доступен), ss и curl.

Опишите словами порядок проверок, которые вы предложите выполнить. Что вы будете смотреть на каждом шаге и какие выводы сможете сделать? Ответ должен быть связным текстом, 5–7 предложений. Конкретные команды приводить не обязательно, но если приводите — то только читающие, ничего не меняющие.

Обсуждение урока

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

Пожаловаться на комментарий

Расскажите модераторам, что именно требует внимания.