DNS не резолвит в Linux: Temporary failure in name resolution, dig, resolv.conf и systemd-resolved
Команда KAI Lab · · 8 мин чтения
Если в Linux не резолвится имя, разделите проблему на две части: getent hosts имя проходит тот же путь, что и приложения, — через /etc/nsswitch.conf, /etc/hosts и /etc/resolv.conf, — а dig имя спрашивает DNS-сервер напрямую. Статус в ответе dig сразу подсказывает, где искать: NXDOMAIN — такой записи нет, SERVFAIL — сервер не смог получить ответ, таймаут — до DNS-сервера не достучаться.
Приложения сообщают об этом по-разному: curl: (6) Could not resolve host, ping: api.example.com: Temporary failure in name resolution или Name or service not known. Две последние строки — тексты ошибок glibc, и разница между ними полезна. «Temporary failure» обычно значит, что сервер недоступен или вернул ошибку. «Name or service not known» — что имя не нашлось.
Как Linux превращает имя в адрес
- Приложение вызывает
getaddrinfo()из glibc. - glibc смотрит строку
hosts:в/etc/nsswitch.conf: в каком порядке спрашивать источники. Обычно этоfiles dns— сначала/etc/hosts, потом DNS. - Для DNS берутся серверы из
/etc/resolv.conf. На Ubuntu и многих других дистрибутивах там стоит127.0.0.53— локальная заглушка systemd-resolved. - systemd-resolved пересылает запрос настоящим DNS-серверам, полученным от DHCP, netplan или NetworkManager, и кэширует ответ.
dig и nslookup ходят в обход шагов 1–2: они читают из /etc/resolv.conf только адрес сервера и не смотрят ни в /etc/hosts, ни в nsswitch.conf. Поэтому ситуация «dig резолвит, а приложение нет», и наоборот, — нормальная подсказка, а не мистика.
Симптом → команда → что смотреть
| Симптом | Команда | Что смотреть |
|---|---|---|
| Приложение не видит имя | getent hosts имя | что видит система с учётом /etc/hosts и nsswitch |
| Нужен ответ DNS-сервера | dig имя | status: — NOERROR, NXDOMAIN или SERVFAIL; секция ANSWER и TTL |
| Подозрение на свой DNS-сервер | dig @1.1.1.1 имя | совпадает ли ответ публичного резолвера с локальным |
| Запросы висят и падают по таймауту | dig имя | communications error ... timed out: сервер из resolv.conf недоступен |
| Непонятно, какие серверы используются | resolvectl status | Current DNS Server, DNS Servers, DNS Domain |
dig и getent отвечают по-разному | grep имя /etc/hosts | забытую статическую запись |
| После смены записи приходит старый IP | dig +noall +answer имя | сколько секунд TTL осталось у ответа в кэше |
| Короткое имя без домена не находится | cat /etc/resolv.conf | строки search и options ndots |
Шаг 1. Что видит система: getent
$ getent hosts api.example.com
10.0.0.15 api.example.com
$ dig +short api.example.com
203.0.113.10Система и DNS отвечают по-разному. Раз dig получает 203.0.113.10, а getent — 10.0.0.15, адрес берётся не из DNS. Первый подозреваемый — /etc/hosts:
$ grep api.example.com /etc/hosts
10.0.0.15 api.example.com
$ grep ^hosts /etc/nsswitch.conf
hosts: files dnsПри files dns запись в /etc/hosts побеждает DNS. Такие строки остаются после переездов и отладки: кто-то когда-то прописал адрес руками, сервис переехал, а запись осталась. Если getent ничего не вернул, код выхода будет 2 — имя не найдено ни в одном источнике, и пора идти к DNS.
Шаг 2. Что отвечает DNS: dig
Главное в выводе dig — строка со статусом:
$ dig api.example.com | grep status
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 30412
$ dig @1.1.1.1 api.example.com | grep status
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1734Что означают статусы:
- NOERROR — ответ есть. Если секция ANSWER при этом пустая, имя существует, но записи нужного типа нет: например, есть
A, а спрашивалиAAAA. - NXDOMAIN — такого имени нет. Проверьте опечатку, домен поиска и то, в той ли зоне вы ищете: внутреннее имя публичный резолвер не знает.
- SERVFAIL — резолвер не смог получить ответ: недоступны авторитетные серверы зоны, сломан DNSSEC или сам резолвер. Если публичный резолвер отвечает, а ваш — нет, как в примере выше, проблема в вашем резолвере или на пути к нему.
- REFUSED — сервер отказался отвечать: вас нет в его списке разрешённых клиентов.
Если сервер не отвечает вовсе, dig покажет:
$ dig @10.0.0.2 api.example.com
;; communications error to 10.0.0.2#53: timed out
;; communications error to 10.0.0.2#53: timed out
;; communications error to 10.0.0.2#53: timed out
; <<>> DiG 9.18.28-0ubuntu0.24.04.1-Ubuntu <<>> @10.0.0.2 api.example.com
; (1 server found)
;; global options: +cmd
;; no servers could be reachedЭто уже сетевая проблема: сервер выключен, не слушает порт 53 или трафик режет firewall. Когда проблема в зоне у провайдера, dig +trace имя пройдёт цепочку делегирования от корневых серверов и покажет, на каком шаге она рвётся.
nslookup делает похожую работу. Сервер для проверки указывается вторым аргументом: nslookup api.example.com 1.1.1.1, а отсутствие имени выглядит как ** server can't find ...: NXDOMAIN.
Шаг 3. Какие серверы на самом деле используются
$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Aug 12 10:02 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
$ grep -v '^#' /etc/resolv.conf
nameserver 127.0.0.53
options edns0 trust-ad
search corp.exampleЕсли /etc/resolv.conf — ссылка на stub-resolv.conf, всё идёт через systemd-resolved, а настоящие серверы надо смотреть у него:
$ resolvectl status
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (eth0)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 10.0.0.2
DNS Servers: 10.0.0.2
DNS Domain: corp.exampleПравить такой /etc/resolv.conf руками бесполезно: его перезапишут. Серверы меняют там, откуда они приходят, — в netplan, NetworkManager, DHCP или resolved.conf.
Если systemd-resolved не используется и в /etc/resolv.conf перечислены серверы напрямую, помните, как работает резолвер glibc. Он опрашивает серверы по порядку, ждёт ответа 5 секунд и делает 2 попытки. Если первый сервер в списке мёртв, каждое обращение к DNS тормозит на секунды, хотя второй сервер жив. Серверов в списке учитывается не больше трёх.
Шаг 4. Короткие имена: search и ndots
Строка search corp.example позволяет писать db вместо db.corp.example: резолвер сам допишет домен. Правило задаёт ndots: если в имени точек меньше этого числа (по умолчанию 1), сначала пробуются домены поиска.
Отсюда две ловушки. Первая — короткое имя не находится на машине, где search другой или пустой. Вторая — лишние запросы: в подах Kubernetes по умолчанию ndots:5 и несколько доменов поиска, поэтому обращение к внешнему api.example.com сначала перебирает кластерные домены. Если в конце имени поставить точку — api.example.com., — поиск не выполняется.
Шаг 5. TTL и кэш: почему старый адрес
Каждый ответ DNS живёт в кэше столько секунд, сколько указано в TTL. Сменили запись у DNS-провайдера — клиенты увидят новый адрес, только когда у них истечёт старый ответ:
$ dig +noall +answer api.example.com
api.example.com. 74018 IN A 198.51.100.20
$ dig +noall +answer @ns1.example.com api.example.com
api.example.com. 86400 IN A 203.0.113.10Авторитетный сервер уже отдаёт новый адрес, а резолвер помнит старый ещё 74 018 секунд — больше двадцати часов. Потому что TTL был сутки. Правило для переездов: снизить TTL до нескольких минут заранее, хотя бы за один старый TTL до смены записи.
Кэшей по дороге несколько, и сбросить можно только свой:
sudo resolvectl flush-cachesчистит кэш systemd-resolved на этой машине;- кэш корпоративного или провайдерского резолвера вы не сбросите — ждите TTL;
- приложения тоже кэшируют: JVM держит адреса у себя, а nginx резолвит имена из
proxy_passпри запуске и перечитывании конфигурации.
Отрицательные ответы тоже кэшируются. Если запросили имя до того, как запись создали, NXDOMAIN какое-то время будет возвращаться и после создания — срок задаёт SOA-запись зоны.
Что сломалось чаще всего
- Забытая строка в
/etc/hosts— выдаёт себя разницей междуgetentиdig. - Недоступный или мёртвый DNS-сервер в настройках сети — таймауты в
dig, долгие зависания у приложений. - Внутреннее имя спрашивают у публичного резолвера, например после ручной правки настроек на
8.8.8.8, —NXDOMAIN. - Запись поменяли, а TTL большой — у одних клиентов новый адрес, у других старый.
- В контейнере свой
resolv.conf: у Docker в пользовательских сетях встроенный DNS-сервер127.0.0.11, у подов Kubernetes — адрес кластерного DNS.
Когда имя резолвится верно, а подключиться всё равно не получается, дальше по пути запроса — порт и сертификат: разборы порт уже занят и истёк SSL-сертификат. А вопрос «что происходит, когда вы набираете адрес в браузере» почти всегда звучит на собеседовании по Linux — эта статья покрывает его DNS-часть.
В первом месяце симулятора DevOps KAI Lab есть тикет «Объясни продакту, как работает сайт»: с него удобно начать, если путь запроса от имени до ответа сервера пока не сложился в голове. Дальше те же шаги встречаются в тикетах и на дежурствах, а консоль отвечает реальными выводами команд.
Частые вопросы
Почему dig резолвит, а приложение — нет? dig спрашивает DNS-сервер напрямую и не смотрит в /etc/hosts и nsswitch.conf. Приложения идут через glibc и эти файлы. Сравните с getent hosts имя: если ответы разные, причина в /etc/hosts или в порядке источников в nsswitch.conf.
Чем NXDOMAIN отличается от SERVFAIL? NXDOMAIN — сервер уверен, что такого имени нет. SERVFAIL — сервер не смог получить ответ: недоступны авторитетные серверы, ошибка DNSSEC или проблема самого резолвера.
Как сбросить DNS-кэш в Linux? При systemd-resolved — sudo resolvectl flush-caches. Это чистит только локальный кэш: вышестоящие резолверы будут отдавать старый ответ, пока не истечёт TTL.
Можно ли редактировать /etc/resolv.conf? Если это ссылка на файл systemd-resolved или файл, которым управляет NetworkManager, — нет, изменения перезапишут. Меняйте настройки там, откуда приходят серверы: в netplan, NetworkManager, DHCP или resolved.conf.
Что значит Temporary failure in name resolution? Это текст ошибки glibc, когда DNS не дал окончательного ответа: сервер недоступен, ответил SERVFAIL или запрос истёк по таймауту. Проверьте dig имя и resolvectl status.
Источники
- man7.org: resolv.conf(5) —
nameserver(до трёх),search,ndots,timeout5 секунд,attempts2. - man7.org: nsswitch.conf(5), getent(1) — порядок источников и проверка разрешения имён.
- man7.org: systemd-resolved.service(8) — заглушка 127.0.0.53 и режимы
/etc/resolv.conf. - man7.org: resolvectl(1) —
status,query,statistics,flush-caches. - ISC. BIND 9 — dig — опции
+short,+trace,+noall,+answer. - IETF. RFC 2308 — кэширование отрицательных ответов DNS.
- Kubernetes. DNS for Services and Pods —
resolv.confпода иndots:5. - Docker. Networking overview: DNS services — встроенный DNS-сервер в пользовательских сетях.
- nginx. ngx_http_upstream_module: параметр resolve и proxy_pass — когда nginx заново резолвит имена.