Кратко

  • Истечение TTL завершает обычное повторное использование и требует снова обратиться к источнику. Serve-stale по RFC 8767 возможен лишь тогда, когда авторитетное обновление не удалось, а подходящий старый объект ещё сохранён.
  • Четыре времени отвечают за разные решения: ожидание клиента, полный budget resolution, повторная проверка сбоя и максимальный stale-возраст. Статус «включено» не доказывает их выполнение.
  • Старый RRset, свежий failure, время RRSIG, короткий ответный TTL, EDE, продолжающийся refresh и результат приложения нельзя записывать как один «успех DNS». Иначе локальная политика выдаётся за текущую речь зоны.

Старый маршрут к новому владельцу адреса

Онлайн-сервис меняет IP и оставляет прежний endpoint на время миграции. Через несколько часов старый адрес освобождается. У одного корпоративного resolver к этому моменту истёк TTL прежнего A, но все авторитетные серверы стали недоступны из-за сетевого отказа.

SERVFAIL явно останавливает приложение. Stale A может сохранить работу, если старый endpoint всё ещё под контролем сервиса. Если адрес уже передан, та же функция направит запросы к другому владельцу. Resolver не знает жизненный цикл адреса. Он знает только полученное ранее значение и то, что не смог проверить его сейчас.

Полномочие serve-stale поэтому основано не на уверенности в правильности, а на заранее принятой цене двух видов отказа. Его нельзя скрывать внутри cache-hit: это отдельное исполнительное решение.

TTL сначала требует консультации

RFC 1035 связывал TTL с повторным обращением к источнику и удалением RR. RFC 2181 называл его максимальным временем жизни. RFC 8767 обновил определение: после TTL источник должен быть снова опрошен; если авторитетный refresh невозможен, запись может использоваться как неистёкшая по правилам документа.

Исключение следует за попыткой, а не заменяет её. Немедленно отдавать старое и лишь затем спрашивать upstream — значит сделать прошлое обычным предпочтением и лишить publisher контроля коротким TTL.

TTL 0 остаётся только для текущей транзакции, не сохраняется и не становится stale. Рекомендуемый clamp входного TTL около семи дней также отличен от maximum stale. Первый ограничивает обычное кеширование, второй — местное продление после его конца.

Четыре таймера разделяют власть

Client response timer определяет, сколько ждать fresh-ответ до потери полезного окна клиента. Пример — около 1,8 секунды. Малое значение принимает медленную authority за недоступную; большое сохраняет freshness, но опаздывает.

Query resolution timer ограничивает всю работу, обычно десять–тридцать секунд в обсуждении RFC. Он продолжает действовать после отправки stale: ответ клиенту не прекращает repair.

Failure recheck timer не позволяет каждому клиенту повторять уже известный отказ. Недавний failure может дать немедленный stale до следующей проверки. В примере — не чаще раза в тридцать секунд и не дольше пяти минут. RFC 9520 требует cache resolution failures от одной секунды до пяти минут и рекомендует backoff.

Maximum stale timer ограничивает хранение после expiry. Предлагается один–три дня. Большой период помогает при долгом outage, но продлевает старый IP, делегирование, отрицание и потребление памяти.

Для аудита нужны начало и исход каждого времени. Новый refresh был начат или сработал cached failure? Fetch продолжился после ответа? Объект заменён, вытеснен либо пережил restart? Один флаг не отвечает ни на один вопрос.

Не всякий пакет обновляет прошлое

Authoritative response с AA и NOERROR или NXDOMAIN должен считаться refresh. Другие RCODE обычно означают failure и сохраняют прежнее состояние.

Так временный SERVFAIL не уничтожает последний полезный RRset. Но свежий авторитетный NXDOMAIN завершает старый positive, даже если оператор подозревает ошибочное удаление. Resolver не умеет читать намерение и не голосует против текущего отрицания.

REFUSED неоднозначен: намеренное снятие, ACL, неавторитетный сервер. Реализация может решить, запрещает ли REFUSED от всех authority stale. Это часть release semantics.

RFC 9520 требует отдельно cache сам failure. Он подавляет outgoing query, но не говорит, существует ли имя. Evidence должен содержать и expired answer, и failure entry, которое объясняет паузу upstream.

Короткий TTL принадлежит resolver

В stale response каждый expired RR получает TTL больше нуля; рекомендовано тридцать секунд. Это не новая жизнь от зоны. Resolver ограниченно распространяет собственную старую проекцию downstream.

Запись включает original TTL, insertion, ordinary expiry, stale age, reply TTL и причину. Один TTL=30 не различает свежий ответ и часы старого состояния.

RFC 8914 задаёт EDE 3 Stale Answer, EDE 19 Stale NXDOMAIN и EDE 7 Signature Expired. EDE добавляет контекст, но не меняет RCODE processing и не заставляет приложение отказаться. Forwarder может потерять option, поэтому её путь проверяется по hop.

Старое отсутствие исполняется так же, как адрес

Stale A сохраняет старую цель. Stale NXDOMAIN сохраняет отсутствие. NSEC/NSEC3 может скрыть новый DS, TLSA или emergency name. Быстрый отрицательный ответ выглядит лучше ошибки, но способен блокировать восстановление.

Eligibility разделяет content, certificate control, delegation, revocation и аварийные имена. Если продукт не даёт нужной точности, scope уменьшается. Общий счётчик stale не показывает, сохранена ли reachability или остановлена новая.

Особенно опасно читать NXDOMAIN как «authority всё ещё говорит, что имени нет». После expiry это уже resolver решил продолжить старое отрицание.

DNSSEC живёт по своему времени

RFC 4035 требует, чтобы current time validator находилось между inception и expiration RRSIG. Хранение RRset не двигает подпись. Данные могут быть stale и ещё valid, затем stale и signature-expired.

Нужны разные counters: stale-secure, stale-expired-signature, cached validation failure и local insecure exception. DNSSEC enabled скрывает результат.

Attacker может совместить недоступность authority с продлением старого binding. RFC 8767 отмечает abandoned address и риск domain-validated certificate. Функция не создаёт захват адреса, но выбирает окно его действия при отказе.

BIND и Unbound требуют разных тестов

BIND отдельно документирует retention, response, reply TTL, maximum age, refresh и runtime rndc serve-stale. Текущие значения документации: reply TTL тридцать секунд, maximum один день при включении. Client timeout default off, а описанная версия при включении поддерживает только ноль — immediate response.

Unbound через serve-expired-* разделяет age, reply TTL, wait и reset. Документация различает immediate и refresh-first mode. Слова общие, execution различно.

Canary включает быструю, медленную, unreachable authority, SERVFAIL, REFUSED, NXDOMAIN; positive/negative; valid/expired RRSIG; TTL 0; cache pressure; restart; runtime override. Проверяются cache, upstream, response, EDE, продолженный refresh, replacement и application packet.

Источники