DNS в Linux: резолвинг, /etc/hosts, resolv.conf

Каждый запрос к сайту начинается с превращения имени в IP-адрес. Разберём, как именно Linux резолвит имена и где это чинить, когда «DNS сломался».

DNS-резолвинг — процесс преобразования доменного имени (example.com) в IP-адрес. В Linux за него отвечает цепочка: локальный файл /etc/hosts, настройки /etc/resolv.conf и (на современных системах) служба systemd-resolved.

Зачем это на практике

«Сайт не открывается» в половине случаев — это проблема не сети, а DNS: пинг по IP идёт, а по имени нет. Уметь руками проверить резолвинг, прописать тестовую запись в /etc/hosts и понять, какой резолвер реально используется, — навык, который экономит часы. Особенно это важно при разработке: подменить домен на локальный сервер, отладить балансировщик, проверить новую запись DNS до того, как она «разъедется» по миру.

Как резолвится имя: порядок источников

Когда программа хочет узнать IP для example.com, она спрашивает не сразу DNS-сервер. Порядок источников задаёт строка hosts: в файле /etc/nsswitch.conf:

grep ^hosts /etc/nsswitch.conf
hosts: files dns

Здесь files означает «сначала загляни в /etc/hosts», и только потом dns — «спроси DNS-сервер». Поэтому запись в /etc/hosts всегда побеждает настоящий DNS — это и инструмент отладки, и источник коварных багов.

Файл /etc/hosts: ручные записи

Простой текстовый файл «IP — имена». Добавим запись, чтобы myapp.local вёл на локальную машину:

cat /etc/hosts
127.0.0.1   localhost
127.0.1.1   my-laptop
127.0.0.1   myapp.local api.myapp.local

Теперь любой запрос к myapp.local пойдёт на 127.0.0.1, минуя интернет. Это удобно для локальной разработки и для временной блокировки домена (направить его на 0.0.0.0). Изменения в /etc/hosts вступают в силу мгновенно, без перезапуска служб.

Файл /etc/resolv.conf: какие DNS-серверы спрашивать

Если в /etc/hosts имени нет, система идёт к DNS-серверам из /etc/resolv.conf:

cat /etc/resolv.conf
nameserver 127.0.0.53
search lan
options edns0 trust-ad

Строки nameserver перечисляют DNS-серверы (их спрашивают по порядку), search lan добавляет суффикс к коротким именам (server1server1.lan). Важная деталь современных систем: nameserver 127.0.0.53 — это не настоящий внешний сервер, а локальная заглушка systemd-resolved.

systemd-resolved: локальный кэширующий резолвер

systemd-resolved — служба, которая принимает DNS-запросы на 127.0.0.53, кэширует ответы и сама ходит к настоящим upstream-серверам, прописанным отдельно.

Поэтому на Ubuntu редактировать /etc/resolv.conf руками обычно бесполезно — его перезаписывает служба. Реальные настройки и кэш смотрят так:

resolvectl status            # какие upstream-DNS и для каких интерфейсов
resolvectl query example.com # резолв через systemd-resolved
resolvectl statistics        # размер и попадания кэша
sudo resolvectl flush-caches # сбросить DNS-кэш

Команда resolvectl flush-caches — частый ответ на «изменил DNS-запись, а старый IP всё ещё подставляется»: помог сбросить локальный кэш.

Инструменты диагностики: dig, host, nslookup

Чтобы спросить DNS напрямую, минуя кэш системы, есть три инструмента. Самый информативный — dig:

dig example.com                 # A-запись (IPv4)
dig +short example.com          # только сам IP, без шума
dig example.com MX              # почтовые серверы домена
dig @8.8.8.8 example.com        # спросить конкретный сервер (Google)
host example.com                # коротко и человекочитаемо
nslookup example.com            # классика, есть почти везде

В выводе dig ключевая секция — ANSWER SECTION; там же поле TTL (сколько секунд запись можно кэшировать). Приём dig @8.8.8.8 отвечает на вопрос «это мой локальный резолвер врёт или запись действительно такая» — вы спрашиваете публичный сервер напрямую и сравниваете.

Типы записей и обратный резолвинг

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

ЗаписьЧто означает
AIPv4-адрес имени
AAAAIPv6-адрес имени
CNAMEпсевдоним, ссылка на другое имя
MXпочтовые серверы домена
TXTпроизвольный текст (SPF, верификация)
PTRобратная запись: IP в имя

Обратный резолвинг (по IP узнать имя) делают так:

dig -x 93.184.216.34       # обратный резолв: IP в имя (PTR-запись)
host 93.184.216.34         # коротко, то же самое
dig example.com AAAA +short   # IPv6-адрес, если он есть

Обратные записи важны для почты: многие почтовые серверы отвергают письма с хостов без корректного PTR. А CNAME объясняет, почему dig www.site.com иногда показывает сначала псевдоним, а потом уже реальный IP той записи, на которую он указывает.

Как это работает под капотом

Резолвинг имени для большинства программ делает функция getaddrinfo() из библиотеки glibc. Она читает /etc/nsswitch.conf, идёт по источникам (files, затем dns) и на этапе dns отправляет UDP-запрос на порт 53 ближайшему nameserver. Сам DNS устроен иерархически: корневые серверы знают, кто отвечает за .com, те — кто за example.com, и так до конкретной A-записи. systemd-resolved встаёт посередине как кэш: первый запрос идёт наружу, последующие отдаются мгновенно из памяти, пока не истечёт TTL. Важно: dig и nslookup ходят к DNS-серверу напрямую и НЕ читают /etc/hosts — поэтому их ответ может отличаться от того, что видят обычные программы.

Частые ошибки

  • Правят /etc/resolv.conf на Ubuntu и удивляются, что настройки откатились. Файлом управляет systemd-resolved; меняйте через resolvectl или конфиг службы.
  • Забыли про кэш. Поменяли DNS-запись, а подставляется старый IP — нужен resolvectl flush-caches (или просто ждать истечения TTL).
  • Думают, что dig покажет результат как у браузера. dig игнорирует /etc/hosts; если там есть запись, программы пойдут по ней, а dig — мимо.
  • Тестовая строка в /etc/hosts осталась навсегда. Классический баг: домен в проде «не туда ходит», потому что год назад вписали его в hosts для отладки.

Итоги

  • Порядок резолвинга задаёт /etc/nsswitch.conf: обычно сначала /etc/hosts, потом DNS.
  • /etc/hosts побеждает настоящий DNS и работает мгновенно — удобно для отладки, опасно как забытая запись.
  • На современных системах резолвер — systemd-resolved на 127.0.0.53; смотреть через resolvectl status, кэш сбрасывать resolvectl flush-caches.
  • dig +short, host, nslookup спрашивают DNS напрямую (мимо /etc/hosts); dig @сервер проверяет конкретный DNS-сервер.
Проверьте себя
1. В /etc/hosts добавили строку '203.0.113.5 example.com', но при этом dig example.com показывает другой IP. Какой IP увидит обычный браузер?
A203.0.113.5 — потому что /etc/hosts проверяется раньше DNS (files перед dns в nsswitch.conf)
BТот, что показал dig — браузер всегда верит DNS
CОба сразу, по очереди
DНикакой, будет ошибка из-за конфликта
2. На Ubuntu в /etc/resolv.conf стоит 'nameserver 127.0.0.53'. Что это за адрес?
AПубличный DNS-сервер провайдера
BЛокальная заглушка службы systemd-resolved, которая кэширует ответы и сама ходит к upstream-серверам
CАдрес роутера по умолчанию
DОшибка конфигурации, так быть не должно