Когда kill switch роняет туннель, он уносит с собой и путь DNS, а оставшийся резолвер редко оказывается тем, которого вы ждёте. Два подхода обращаются с этим моментом очень по-разному: блокировать каждый пакет DNS, который не находится внутри туннеля, или оставить один резолвер как исключение. Оба варианта защитимы. Из вкладки браузера симптомы выглядят почти одинаково, поэтому первая задача — понять, какой подход вы на самом деле развернули.

Я держу это различие перед глазами, потому что исправление в каждом случае противоположное. Одному подходу нужна более широкая поблажка, другому — более узкая. Догадки стоят вам либо приватности, либо половины дня.

Два подхода к DNS для одной и той же аварии

Подход A относится к резолверу как к обычной службе за туннелем. Правила межсетевого экрана разрешают UDP и TCP 53 только на интерфейсе туннеля, и адрес, выдаваемый клиенту, — это резолвер внутри туннеля. Когда туннель падает, поиск прекращается, и это задуманный результат, а не неисправность.

Подход B держит резолвер доступным в локальной сети, обычно это маршрутизатор на 192.168.1.1 или заглушка операционной системы на 127.0.0.53, исходя из того, что разрешение имён не должно умирать вместе с туннелем. Это удобно в домашней сети, где маршрутизатор разрешает имена для всего дома. В Wi-Fi отеля или аэропорта та же поблажка указывает на чужой сервер, и каждое введённое имя раскрывается, даже если ваш веб-трафик остаётся заблокированным.

Граница в том, кому принадлежит резолвер. Если вы доверяете локальному, исключение — маленькая и честная дыра. Если нет, подход только через туннель — единственный, который держится, и цена в том, что упавший туннель забирает все имена.

Почему поиск самого VPN-клиента всё ещё работает

Клиент должен разрешить имя хоста шлюза до того, как появится туннель, поэтому строгая блокировка не должна закрывать путь начальной загрузки клиента. Большинство клиентов либо кэшируют адрес конечной точки, либо поставляют документированное исключение для этого единственного хоста. Если ваш набор правил блокирует этот поиск, туннель никогда не вернётся, а журналы покажут клиента, который не может достучаться до собственного сервера; это дефект политики, а не DNS.

Раздельный DNS — второе место, где это проявляется. Клиент направляет внутреннюю зону в частный резолвер, а всё остальное оставляет системному резолверу. После падения публичные имена могут ещё разрешаться, пока внутренние истекают по тайм-ауту, потому что у частной зоны больше нет маршрута. Для пользователя это «VPN сломал интернет»; для журнала резолвера это запрос, который так и не пришёл.

При systemd-resolved разделение видно напрямую. resolvectl status перечисляет DNS-серверы по каждому каналу и домены маршрутизации, и после падения туннеля внутренний домен продолжает указывать на сервер на канале, которого больше нет. Заглушка на 127.0.0.53 всё ещё принимает запрос, затем ждёт вышестоящий сервер, который не ответит, и именно поэтому сбой длится секунды, а не возвращается сразу.

Зашифрованный DNS не обходит фильтр пакетов

DNS over HTTPS и DNS over TLS идут по 443 и 853, поэтому правило, блокирующее порт 53, ничего о них не сказало. Блокировать «DNS» по порту — это политика о порте, а не о разрешении имён. Если ваш kill switch блокирует весь трафик вне туннеля, DoH попадает под запрет случайно. Если вы выделили разрешение для captive portal или публичного резолвера, то нет.

Клиентские средства управления — более дешёвый рычаг. Firefox отказывается от своего резолвера DoH, когда канареечное имя use-application-dns.net не разрешается, и поэтому управляемые сети публикуют этот домен как NXDOMAIN; корпоративная политика может ещё и закрепить его выключенным. Android Private DNS и безопасный DNS в Chrome имеют собственные переключатели и собственные значения по умолчанию. Выключить их надёжнее, чем гоняться за адресами резолверов, потому что список адресов меняется, а ваш набор правил — нет.

Есть версия этого, которая вовсе не про утечки. Приложению с закреплённым резолвером всё равно нужен сетевой путь, чтобы до него добраться. Шифрование меняет то, кто может прочитать запрос, а не то, может ли пакет покинуть машину, поэтому блокировка всего устройства побеждает настройку, не касаясь её.

Соотнесите симптом со слоем

Большинство обращений приходит одной фразой, и эта фраза обычно уже называет слой. Таблица ниже — то, что я прохожу перед тем, как тронуть правило; смысл в том, чтобы решить, был ли запрос заблокирован, направлен не туда или вообще не отправлен.

SymptomLikely layerFirst check
Every name fails at once, instantlyResolver answering with a refusalQuery the resolver by address, not by name
Lookups hang for seconds, then time outPackets dropped with no responseWatch port 53 on the physical link
Public names resolve, internal ones do notSplit-DNS routing domainPer-link DNS servers on the tunnel
Names resolve, the page still failsNot DNS: routing or MTUConnect to the IP directly
Only one application failsPinned resolver or cached answerCheck that app's DNS setting

Первые две строки — те, что люди диагностируют неправильно. Тихий сброс и отказ в браузере выглядят одинаково как «DNS сломался», но только один из них означает, что ваш kill switch делает свою работу. Отказ означает, что что-то ответило, значит блокировка не там, где вы думаете.

Восстановите политику резолвера, а затем докажите её

Исправляйте подход, а не симптом. Для разрешения только через туннель разрешите 53 на интерфейсе туннеля, протяните внутренний резолвер вместе с конфигурацией туннеля и оставьте физический канал без всякого разрешения DNS. В wg-quick именно строка DNS = записывает резолвер в конфигурацию интерфейса, поэтому туннель, который её пропускает, оставляет старый резолвер на месте, и каждый запрос уходит не туда. руководство wg-quick документирует такое поведение для каждой платформы.

Затем проверьте в этом порядке. В Linux resolvectl status показывает активный канал, dig +short example.com проверяет публичное имя, dig @10.8.0.1 internal.example.com проверяет частное, а sudo tcpdump -ni any port 53 показывает, какой интерфейс используют пакеты, пока вы запускаете и то, и другое. В Windows Get-DnsClientServerAddress -AddressFamily IPv4 и Resolve-DnsName example.com дают те же два факта: кто настроен и кто отвечает.

Закончите отрицательным тестом. Отключите туннель, убедитесь, что свежее публичное имя не разрешается, убедитесь, что частное имя не разрешается, и убедитесь, что ни один пакет порта 53 не покинул физический адаптер. Блокировка, которая держится только для кэшированных ответов, не держится вовсе.

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

  • Резолвер, использованный во время аварии, — тот, который предусматривает политика.
  • Собственный поиск конечной точки клиентом по-прежнему разрешён, через кэш или исключение.
  • DoH и DoT либо покрыты блокировкой, либо отключены политикой.
  • Частные зоны отказывают закрыто, а не открыто, как только туннель исчезает.

Похожие статьи