
Как Linux разрешает имена: NSS, hosts, systemd-resolved и DNS
Разбираем путь имени в Linux через NSS, /etc/hosts, resolv.conf и systemd-resolved; диагностируем различия между getent, resolvectl и dig.
Содержание
Сервер может открывать сайт по IP-адресу и одновременно сообщать, что доменное имя не найдено. Значит, соединение с сетью есть, а сбой нужно искать в разрешении имён — преобразовании имени вроде example.com в IP-адрес.
Проверка одним dig не всегда объясняет поведение программы. Обычное Linux-приложение обращается к системным источникам имён, а dig отправляет запрос прямо DNS-серверу. Поэтому сначала выясним, какой ответ получает система, а затем разберём путь этого ответа.
Как программа получает IP-адрес
Типичный путь выглядит так:
- приложение вызывает системную функцию разрешения имени;
- NSS, системный переключатель источников имён, читает их порядок из
/etc/nsswitch.conf; - источник
filesпроверяет/etc/hosts; - источник DNS обращается к настроенному резолверу — службе, которая выполняет DNS-запрос;
- резолвер выбирает DNS-сервер с учётом сетевого интерфейса, VPN и домена поиска.
Это не универсальная схема для каждой программы. Браузер, контейнер, runtime или приложение с собственным DNS-кешем может вести себя иначе. Поэтому важно начать с того процесса, где наблюдается ошибка.
Посмотрите ответ глазами приложения
Команда getent обращается к системной базе hosts через NSS. Она полезна в начале диагностики, потому что повторяет обычный путь многих серверных программ:
getent ahosts example.com
getent hosts example.com
В результате ожидается одна или несколько строк с IP-адресом и именем. Если ответа нет, посмотрите, какие источники и в каком порядке опрашивает NSS:
grep '^hosts:' /etc/nsswitch.conf
В строке могут встречаться files для /etc/hosts, dns для обычных DNS-запросов, resolve для systemd-resolved и mdns для локальных имён. Условия в квадратных скобках управляют переходом к следующему источнику. Не заменяйте эту строку чужим примером: её состав зависит от системы.
Исключите забытый адрес в /etc/hosts
Файл /etc/hosts задаёт локальное соответствие между адресами и именами. Следующая команда скрывает комментарии и пустые строки, чтобы было легче заметить запись для проблемного домена:
grep -vE '^\s*(#|$)' /etc/hosts
Каждая строка содержит IP-адрес и одно или несколько имён. Такая запись удобна для временной проверки сайта до изменения публичного DNS, но действует только на этой машине и только в программах, использующих системный NSS.
Не подменяйте ею долгосрочное управление инфраструктурой. Забытый адрес в hosts создаёт особенно неприятную ошибку: сервер продолжает ходить на старый IP, хотя внешний DNS уже обновлён.
После удаления или исправления записи снова запросите адрес через системный механизм. Так вы проверите именно тот путь, на который повлиял файл:
getent ahosts app.example.com
Выясните, кто настраивает DNS-серверы
/etc/resolv.conf содержит настройки резолвера, но на современных системах часто генерируется автоматически. Сначала проверьте, является ли он символической ссылкой, куда она ведёт и что находится внутри файла:
ls -l /etc/resolv.conf
readlink -f /etc/resolv.conf
cat /etc/resolv.conf
Файлом может управлять systemd-resolved, NetworkManager, DHCP-клиент или облачная конфигурация. Комментарий в начале нередко прямо называет программу-владельца. Ручная правка такого файла исчезнет после перезапуска сети или нарушит штатную схему.
Если используется systemd-resolved, сначала убедитесь, что служба запущена. Затем посмотрите настройки всех интерфейсов и отдельно запросите проблемное имя:
systemctl is-active systemd-resolved
resolvectl status
resolvectl query example.com
В выводе resolvectl status обратите внимание на DNS-серверы каждого интерфейса, текущий сервер и домены маршрутизации. При включённом VPN внутренние имена могут уходить в туннель, а публичные — через основной интерфейс. Один лишь список из resolv.conf такую схему не показывает.
Сравните прямой DNS-запрос
Теперь сравните системный результат с прямым DNS-запросом. Первая команда использует сервер из текущей конфигурации, вторая явно обращается к публичному серверу Cloudflare, третья запрашивает IPv6-адрес:
dig example.com A
dig @1.1.1.1 example.com A
dig example.com AAAA
Адрес 1.1.1.1 здесь нужен только для сравнения. Это не рекомендация менять настройку сервера: публичный резолвер закономерно не знает имён из частной сети организации.
Разница между dig и getent может объясняться /etc/hosts, порядком NSS, локальным кешем, разными серверами или типом записи. Разница между приложениями — собственным кешем, контейнерным DNS или использованием только IPv4/IPv6.
Диагностика по симптомам
Ни одна проверка не возвращает адрес
Сначала убедитесь, что имя набрано верно. Затем отправьте запрос через systemd-resolved и посмотрите его сообщения за последние 15 минут:
resolvectl query example.com
sudo journalctl -u systemd-resolved --since "15 minutes ago"
Если запрос завершается тайм-аутом, проверьте маршрут и правила для DNS к конкретному серверу. Отключение всего firewall не показывает точную причину и оставляет узел без защиты.
Только сервер получает старый адрес
Сравните getent, resolvectl query, dig и запись в /etc/hosts. TTL указывает, как долго DNS-ответ разрешено хранить в кеше, но отдельная программа может иметь собственный кеш. Перезапускайте её только после того, как нашли источник старого значения.
Работает на узле, но не в контейнере
Контейнер имеет собственный /etc/resolv.conf и отдельное сетевое пространство имён. Выполните getent и просмотр конфигурации внутри контейнера. Не копируйте туда настройки узла: Docker и другие платформы формируют DNS-конфигурацию по своим правилам.
Есть IPv6, но соединение зависает
Сравните A и AAAA, маршруты и фактическое подключение. Удаление AAAA — не первый шаг: проблема может находиться в маршрутизации или firewall. Проверяйте соединение отдельно от разрешения имени.
Безопасное изменение и откат
Для постоянной настройки редактируйте программу, которая создаёт DNS-конфигурацию: профиль NetworkManager, systemd-networkd, netplan, VPN или параметры облачной сети. Универсальной команды нет, потому что выбор зависит от найденного владельца /etc/resolv.conf.
Перед изменением сохраните текущие настройки и копию редактируемого файла. После применения сравните системный ответ, ответ резолвера и настоящее HTTPS-соединение:
getent ahosts example.com
resolvectl query example.com
curl -I --connect-timeout 5 https://example.com/
Успешный curl должен вернуть строку состояния HTTP и заголовки сервера. Если после изменения имя перестало разрешаться, верните сохранённый профиль и повторите все три проверки. При потере SSH используйте консоль хостера. Основы сетевой диагностики разобраны в первом входе на VPS, а сетевые ограничения — в руководстве по firewall.
Первоисточники
- systemd-resolved — локальное разрешение имён, режимы resolv.conf и маршрутизация DNS.
- resolvectl — просмотр состояния и запросы через systemd-resolved.
- getent(1) — запрос системных баз, настроенных через NSS.
Самопроверка
Проверьте, что материал усвоен
Ответьте на все вопросы. Результат сохранится только в этом браузере и будет учтён в статистике прочитанных материалов.
Разбираем коротко
Частые вопросы
Почему dig и приложение возвращают разные IP-адреса?
dig напрямую отправляет DNS-запрос выбранному серверу, а приложение обычно использует системный NSS, который может учитывать /etc/hosts, mDNS и локальный resolver. Сравнивайте getent, resolvectl и dig как разные уровни.
Можно ли постоянно записать DNS-серверы прямо в /etc/resolv.conf?
Сначала проверьте, кем управляется файл. Он часто является ссылкой или генерируется systemd-resolved, NetworkManager либо облачной системой; ручная правка тогда будет потеряна или нарушит штатную конфигурацию.
Всегда ли /etc/hosts имеет приоритет над DNS?
Порядок источников задаёт строка hosts в /etc/nsswitch.conf. Во многих системах files расположен раньше dns, но полагаться на это без проверки конкретной машины нельзя.


