Learning Platform
Глоссарий Troubleshooting
Урок 10.03 · 20 мин
Средний
DNSResolutionRecursiveIterativedig

DNS-резолюция — путь от example.com до IP

В предыдущих уроках мы посмотрели на иерархию DNS и на типы записей. Теперь сложим всё вместе и проследим, что физически происходит, когда твой компьютер делает запрос на example.com. Это удивительная цепочка действий, происходящая обычно за 10-50 миллисекунд.

В этом уроке:

  1. Прохождение запроса через stub resolver.
  2. Recursive vs iterative в деталях.
  3. Полный пошаговый разбор резолва www.example.com.
  4. Анализ через dig +trace.
  5. Что такое «cold» vs «warm» резолв.
  6. Дебаг типичных DNS-проблем.

Stub resolver — твой первый шаг

Когда ты в Python пишешь socket.gethostbyname("example.com"), или браузер открывает URL, или curl example.com — за работу берётся stub resolver. Это библиотечный код в твоей ОС, который:

  1. Читает конфигурацию (какой DNS-сервер использовать).
  2. Делает запрос.
  3. Возвращает ответ программе.

На Linux/macOS конфигурация:

cat /etc/resolv.conf
# Что-то вроде:
# nameserver 192.168.1.1   # DNS вашего роутера
# nameserver 8.8.8.8       # fallback
# search local

nameserver — это IP recursive resolver’а. search — суффиксы, которые добавляются к коротким именам (server -> server.local).

На macOS дополнительно:

scutil --dns | head -30
# Покажет DNS-конфигурацию по каждому интерфейсу (Wi-Fi, VPN, etc.)

На Windows:

ipconfig /all | findstr "DNS"

Stub resolver — это «упрощённый» DNS-клиент. Он не делает рекурсию сам — он отправляет один UDP-запрос (или несколько при ретраях) recursive resolver’у и доверяет ему сделать работу.

# Простейший stub-эквивалент на Python:
import socket
ip = socket.gethostbyname("example.com")
print(ip)  # 93.184.216.34

# Это внутри идёт к настроенному в системе resolver'у и просит резолв

Кто делает работу: recursive resolver

Когда твой stub отправил запрос на 8.8.8.8 (или другой recursive resolver), он передал «горячую картошку». Recursive resolver теперь должен найти ответ.

Алгоритм:

1. Получить запрос: "www.example.com A?"
2. Проверить кэш:
   - Если есть валидная (TTL не истёк) запись -- вернуть её.
   - Если нет -- сделать рекурсивный обход иерархии.
3. Кэшировать ответ.
4. Вернуть клиенту.

Recursive resolver — основной игрок. Он:

  • Знает root-серверы (hardcoded в его конфиге).
  • Может ходить по иерархии.
  • Поддерживает большой кэш.
  • Обычно высокодоступен, низколатентен (geographically близок).

Популярные:

ResolverIPОсобенности
Google Public DNS8.8.8.8, 8.8.4.4Быстрый, geographically distributed
Cloudflare1.1.1.1, 1.0.0.1Privacy-focused (no logging)
Quad99.9.9.9Малware-фильтрация
OpenDNS208.67.222.222Cisco, parental control

И, конечно, resolver’ы провайдеров и корпоративных сетей.


Полный путь резолва www.example.com

Допустим, твой компьютер хочет узнать IP www.example.com, и нигде нет кэша (cold start). Что происходит:

Полный резолв www.example.com -- пошагово
App / OS stub
Recursive resolver (8.8.8.8)
Root server
.com TLD server
Authoritative example.com
QUERY www.example.com A, RD=1QUERY www.example.com A?Referral: NS for .com is a.gtld-servers.net (+ glue)QUERY www.example.com A?Referral: NS for example.com is ns1.example.com (+ glue)QUERY www.example.com A?ANSWER www.example.com A 93.184.216.34 (AA flag, TTL=3600)ANSWER 93.184.216.34 (TTL=3600)

Видно, что resolver сделал 3 iterative запроса (root, TLD, authoritative) для одного запроса от клиента. На каждый шаг — 1 RTT. Если RTT 30 мс — total ~100 мс.

На «cold start» (ничего в кэше) — это типичные цифры. На «warm start» (что-то в кэше) — быстрее.


Что такое glue records

Заметь шаг 5: «NS для example.com — ns1.example.com, IP такой-то». Здесь есть тонкость. Если NS-серверы для example.com называются ns1.example.com и ns2.example.com, то resolver не может их резолвить отдельно — это chicken-and-egg: чтобы узнать IP ns1.example.com, нужно сначала найти example.com NS-серверы, которыми и являются… ns1.example.com.

Glue records решают это. На уровне родительской зоны (.com) хранятся не только NS-записи, но и A-записи самих NS-серверов:

example.com.    NS  ns1.example.com.
example.com.    NS  ns2.example.com.
ns1.example.com. A  1.2.3.4    <- glue
ns2.example.com. A  1.2.3.5    <- glue

Когда resolver получает referral от .com, он видит NS-имена + glue A-записи в additional section. Не нужно делать отдельный резолв.

# Посмотри glue records через trace:
dig +trace www.example.com 2>&1 | head -40
# В выводе для .com TLD ты увидишь NS-записи и параллельно A-записи NS-серверов

Recursive vs iterative — ещё раз, чтобы закрепить

Посмотри на диаграмму выше:

  • Запрос от App -> Recursive resolver — recursive: «сделай работу за меня».
  • Запросы от Recursive -> Root, TLD, Authoritative — iterative: «отвечай только тем, что у тебя есть».

Почему различие важно:

  1. Root и TLD-серверы не делают рекурсию. Это защита от перегрузки и неправильного использования. Если бы они делали — кто-то мог бы использовать root как «DNS-прокси».

  2. Recursive resolvers могут делать рекурсию. Это и есть их работа. Иногда они проверяют у клиента, разрешено ли (open vs closed resolver).

  3. Open vs closed resolver. Open resolver — отвечает всем (8.8.8.8 такой). Closed — только своим клиентам (DNS провайдера твоего интернета).

# Заставить resolver сделать iterative запрос (без рекурсии):
dig @8.8.8.8 +norecurse example.com
# Если у resolver'а нет ответа в кэше -- он откажет или вернёт пустой ответ
# Это полезно для дебага: «есть ли ответ в кэше прямо сейчас?»

Кэширование на каждом уровне

Кэш — критическая часть DNS. Каждая запись имеет TTL (Time-To-Live), и resolver хранит её в кэше на этот срок.

Что и где кэшируется:

  1. Stub resolver в ОС часто имеет свой маленький кэш. На macOS — mDNSResponder, на systemd-linux — systemd-resolved. Это первый барьер.

  2. Browser cache. Chrome имеет свой DNS-кэш (chrome://net-internals/#dns). Firefox тоже. Обычно minutes.

  3. Application cache. Многие приложения (особенно с long-running connections) кэшируют DNS внутри себя. Например, в Java по дефолту кэш «навсегда» — это часто причина проблем при смене IP сервера.

  4. Recursive resolver cache (на 8.8.8.8 или у провайдера). Самый «большой» кэш, иногда минуты-часы.

  5. Authoritative сервер не нуждается в кэше своих записей — он их хранит. Но он может кэшировать результаты child-zone NS.

# Очисти DNS-кэш на macOS:
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

# На Linux с systemd-resolved:
sudo systemd-resolve --flush-caches

# Очисти браузерный кэш Chrome:
# chrome://net-internals/#dns -> Clear host cache

# Замерь время резолва -- cold vs warm:
sudo dscacheutil -flushcache
time dig +short example.com   # cold
time dig +short example.com   # warm -- должен быть мгновенным

Цифровая практика: dig +trace

dig +trace имитирует iterative resolution из вашего компьютера. Это лучший способ увидеть полный путь:

dig +trace www.github.com

Что покажет (упрощённо):

.   <- root section: 13 root-серверов
;; Received 525 bytes from 192.168.1.1#53 in 5 ms

com.  <- referral from root: NS .com
;; Received 1206 bytes from 198.41.0.4#53(a.root-servers.net) in 23 ms

github.com.   <- referral from .com: NS github.com
;; Received 690 bytes from 192.5.6.30#53(a.gtld-servers.net) in 25 ms

www.github.com.  <- final answer from authoritative
;; Received 79 bytes from 205.251.193.165#53(ns-421.awsdns-52.com) in 30 ms

Каждый блок — это один iterative шаг. Видны IP-адреса серверов, RTT, и какие ответы получены.

Часто используется для дебага:

  • Резолвится не там, где ожидалосьdig +trace покажет, где «свернул не туда».
  • Долгий резолв — какой шаг занимает много времени.
  • Не работает на одном из серверов — какой NS сейчас не отвечает.

Cold vs warm — почему первый запрос медленнее

Если ты не открывал example.com за последний час, твой recursive resolver не имеет ничего в кэше. Резолв займёт ~100 мс (3 RTT по 30 мс).

Если ты открывал something.com минуту назад, у resolver’а в кэше:

  • NS для .com (TTL 2 дня — почти всегда в кэше).
  • NS для something.com (TTL ~1 день).
  • A для something.com (TTL ~5 минут).

Поэтому если запрашиваешь снова something.com, ответ из кэша — мгновенный. Если запрашиваешь other.com (того же TLD .com), пропускаешь шаг к root, шаг к .com — нужен только шаг к authoritative other.com. Это ~30 мс.

# Замерь cold vs warm:
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder

# Cold (никаких .com доменов в кэше):
time dig +short cnn.com

# Warm (.com уже в кэше):
time dig +short bbc.com    # быстрее
time dig +short github.com  # ещё быстрее (если .com NS закэшированы)

# Очень warm (этот домен уже в кэше):
time dig +short github.com   # мгновенно

Что может пойти не так

Типичные DNS-проблемы:

1. NXDOMAIN — домен не существует

dig nonexistent-domain-xyz.com
# В выводе: ';; status: NXDOMAIN'
# = no such domain

Может означать:

  • Домен реально не зарегистрирован.
  • DNS-провайдер сломан и не отвечает.
  • Ты опечатался в имени.

2. SERVFAIL — что-то сломалось

;; status: SERVFAIL

Resolver не смог получить ответ. Причины:

  • Authoritative-сервер не ответил.
  • DNSSEC validation failed.
  • Сетевой timeout.

3. Refused

;; status: REFUSED

Сервер отказался отвечать. Обычно:

  • Ты обращаешься к closed resolver, который не обслуживает твой IP.
  • На authoritative-сервере спрашиваешь зону, за которую он не отвечает.

4. Stale cache

Сменил IP сервера, но клиенты всё ещё видят старый IP. Причина — кэш TTL ещё не истёк. Решение — подождать или очистить кэш на стороне клиента.

5. DNS hijacking

Кто-то на пути (часто провайдер или Wi-Fi сети) подменяет DNS-ответы. Защита — DoH/DoT (об этом в уроке 5).

dig, nslookup, ss — диагностика DNS и соединений на Linux

Попробуй сам

# 1. Полный trace одного домена:
dig +trace www.example.com 2>&1 | less

# 2. Замерь cold vs warm резолв:
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder  # macOS
# Linux: sudo systemd-resolve --flush-caches
time dig +short cnn.com    # cold
time dig +short cnn.com    # warm

# 3. Что в кэше у твоего стаб-resolver'а:
# macOS:
sudo killall -INFO mDNSResponder
sudo log show --info --predicate 'subsystem == "com.apple.mDNSResponder"' --last 1m | tail -30
# Linux systemd-resolved:
resolvectl statistics
resolvectl show-cache  # not always available

# 4. Дебаг через альтернативные resolvers:
dig @8.8.8.8 example.com
dig @1.1.1.1 example.com
dig @9.9.9.9 example.com
# Сравни ответы. Иногда они отличаются (CDN-оптимизация)

# 5. Дай stub resolver'у задачу:
python3 -c "import socket; print(socket.gethostbyname('example.com'))"
python3 -c "import socket; print(socket.getaddrinfo('example.com', 80))"
# Второй -- более подробно

# 6. Симулируй полный путь вручную:
# Спроси у root:
dig @a.root-servers.net example.com NS +noall +authority

# Возьми один из .com NS и спроси его:
dig @a.gtld-servers.net example.com NS +noall +authority

# Возьми один из example.com NS и спроси его:
dig @ns1.example.com example.com A

Проверка знанийKnowledge check
Junior спрашивает: 'Мы поменяли IP веб-сервера. Я обновил A-запись у DNS-провайдера, поставил TTL 60 секунд. Прошло полчаса, у меня всё работает, но некоторые пользователи всё ещё попадают на старый сервер. В чём дело?'
ОтветAnswer
Это классическая 'long tail' проблема DNS propagation. Несмотря на то что у тебя TTL 60 секунд, есть несколько слоёв кэша на пути от твоей записи до конечного пользователя, и каждый может задерживать обновление: 1. Application/client cache. Многие приложения кэшируют DNS внутри себя. Java по дефолту кэширует 'forever' (через -Dnetworkaddress.cache.ttl можно поправить). Python с requests/urllib обычно не кэширует. Браузер Chrome имеет свой DNS cache на минуты (chrome://net-internals/#dns). Если пользователь до твоего изменения уже зашёл на сайт, его браузер может ещё минуты помнить старый IP. 2. OS stub resolver cache. Системный DNS-кэш в ОС: - macOS: mDNSResponder - Linux: systemd-resolved или dnsmasq - Windows: DNS Client service Очищается командами типа 'dscacheutil -flushcache'. Большинство ОС соблюдает TTL, но не всегда -- на старых системах или с агрессивным кэшированием возможны задержки. 3. ISP recursive resolver. Провайдерский DNS-сервер. Тут начинаются 'веселости'. Некоторые провайдеры: - Игнорируют TTL и держат записи 'настолько долго, насколько хотят' (часы или сутки). Особенно мобильные операторы. - Игнорируют изменения 'для разгрузки' своих серверов. - Имеют bug в реализации, который сбрасывает TTL. 4. CDN / Anycast resolver. Если твои клиенты используют Cloudflare 1.1.1.1 или Google 8.8.8.8 -- обычно они соблюдают TTL хорошо. Но есть много 'своих' resolvers на корпоративных и провайдерских сетях. 5. Mobile carriers. Самый худший случай. Сотовые операторы часто кэшируют DNS на час+, потому что хотят минимизировать DNS-трафик через мобильную сеть. Поэтому 'мой мобильный интернет всё ещё идёт на старый IP'. 6. Корпоративные сети. Сами компании ставят DNS-серверы, которые могут иметь свой жёсткий кэш. Что делать на практике для смены IP: (1) ЗА ДЕНЬ-ДВА до смены -- поставь TTL low (60-300 сек). Это нужно сделать заранее, чтобы 'old TTL' (например, 3600) истёк во всех кэшах. Только после этого все клиенты будут видеть новый TTL. (2) В момент смены -- обнови A-запись. Большинство клиентов переключатся в течение TTL. (3) Период миграции -- держи и старый, и новый сервер работающими. Старый должен либо отвечать тем же контентом, либо делать HTTP redirect на новый IP. Это нужно держать минимум 24-48 часов, лучше неделю -- для long-tail клиентов. (4) Long tail -- некоторые клиенты могут ходить на старый IP неделями. Это не починить со стороны DNS -- нужно либо терпеть, либо насильно дисконнектить клиентов (например, ответ 410 Gone), чтобы они переподключились заново. (5) Не используй жёстко прибитые IP в приложениях. Если у тебя сервис использует другой сервис по IP (не имени), при смене IP всё развалится. Всегда подключайся по имени. (6) Используй CNAME для управляемой смены backend'а. Если у тебя 'mysite.com CNAME elb-12345.amazonaws.com', AWS может менять IP под именем сколько угодно, не трогая твой DNS. Итог: TTL 60 не значит 'все увидят изменение через 60 секунд'. Это значит 'идеальные клиенты обновятся через 60 секунд, реальные -- от минут до недель в зависимости от их кэшей'. Поэтому смены IP всегда планируются заранее.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 6. Когда твой stub resolver отправляет DNS-запрос на 8.8.8.8, что обычно происходит дальше?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5