Ситуация, когда dig успешно возвращает IP-адрес, а приложение выдаёт ошибку Could not resolve host, может поставить в тупик. Кажется, что DNS работает, и проблема не в нём. Но это ловушка: dig обращается к DNS-серверу напрямую, а приложение использует системный резолвер (чаще всего glibc), который может вести себя иначе. В этой статье разберём учебный кейс, воспроизведённый в изолированном контейнере, и покажем, как одна строка в конфигурации ломает разрешение имён.

Почему dig и приложение видят разное

dig — это утилита для отправки DNS-запросов напрямую. Она читает /etc/resolv.conf, но не использует NSS (Name Service Switch) и не учитывает порядок источников разрешения имён. Приложение же, будь то curl, Python-скрипт или платёжный шлюз, вызывает getaddrinfo() из glibc, которая последовательно опрашивает источники, указанные в /etc/nsswitch.conf. Если в этом файле есть ошибка или нестандартная запись, приложение может не найти имя, хотя DNS-сервер отвечает корректно.

В нашем эксперименте использовались реальные dig, getent, curl и glibc. Стенд изолирован, поэтому результаты воспроизводимы. Цель — показать, как одна строка в /etc/nsswitch.conf приводит к расхождению между прямым DNS-запросом и системным разрешением.

Шаги воспроизведения и диагностики

Начните с проверки, что DNS действительно отвечает. Выполните dig example.com — если ответ есть, DNS-сервер доступен и возвращает адрес. Затем проверьте системное разрешение через getent hosts example.com. Если getent не возвращает адрес, проблема в NSS. Далее запустите curl -v http://example.com и убедитесь, что ошибка именно в разрешении имени, а не в соединении.

  • Шаг 1. Проверьте /etc/resolv.conf: указан ли корректный nameserver, нет ли опечаток.
  • Шаг 2. Изучите /etc/nsswitch.conf. Строка hosts: должна содержать files и dns в разумном порядке. Например, hosts: files dns — стандартный вариант. Если там что-то вроде hosts: files myhostname без dns, приложение не будет обращаться к DNS.
  • Шаг 3. Проверьте /etc/hosts на наличие ошибочных записей, которые могут перекрыть DNS-ответ.
  • Шаг 4. Убедитесь, что в системе не установлены дополнительные NSS-модули, влияющие на разрешение (например, libnss-mdns для .local).

В нашем кейсе достаточно было одной строки: в /etc/nsswitch.conf стояло hosts: files — без dns. При этом dig работал, потому что шёл напрямую к DNS-серверу. Приложение же искало имя только в /etc/hosts и, не найдя, выдавало ошибку.

Типичные ошибки и критерии выбора

Одна из самых частых ошибок — слепо доверять выводу dig и исключать DNS из подозреваемых. Другая — редактировать /etc/resolv.conf вручную в контейнере, забывая, что при перезапуске он может быть перезаписан. Также опасно добавлять в /etc/hosts временные записи, которые потом забывают удалить.

При выборе метода диагностики ориентируйтесь на воспроизводимость: getent ближе к тому, что видит приложение, чем dig. Если getent hosts не работает, а dig работает — почти наверняка проблема в NSS. Если не работает и dig — смотрите сеть и настройки DNS-сервера.

  • Критерий 1. Всегда проверяйте разрешение имени тем же способом, каким его выполняет приложение (через getent или curl).
  • Критерий 2. Сравнивайте поведение в разных утилитах: dig, host, nslookup, getent.
  • Критерий 3. В контейнерах учитывайте, что /etc/nsswitch.conf может быть унаследован из образа или смонтирован извне.

Пример из практики и выводы

В учебном кейсе «Платёжный шлюз недоступен» приложение не могло разрешить имя шлюза, хотя dig показывал правильный IP. После проверки getent hosts payment-gateway выяснилось, что имя не разрешается. Исправление одной строки в /etc/nsswitch.conf (добавление dns в список источников для hosts) решило проблему. Платежи пошли.

Вывод: не ограничивайтесь проверкой через dig. Если приложение не видит имя, а DNS отвечает, ищите расхождение в NSS. Всегда проверяйте /etc/nsswitch.conf и /etc/hosts. В контейнерах эти файлы могут быть нестандартными. И помните: dig — это инструмент для отладки DNS, а не для проверки системного разрешения имён.