Правка resolv.conf не исправляет DNS после отключения VPN
Мёртвый резолвер туннеля в начале списка стоит одного тайм-аута на каждый запрос. Проверьте, кому принадлежит файл, сбросьте состояние линии и прекратите править сгенерированный вывод.
Вы отключаете VPN, ping 1.1.1.1 всё ещё отвечает, и каждый запрос имени зависает, пока страница наконец не сдаётся. Потом cat /etc/resolv.conf показывает сервер имён, который когда-либо существовал только внутри туннеля, обычно первым в списке. Удаление этой строки как будто чинит дело минут на десять, пока приостановка, роуминг Wi-Fi или перезагрузка не вернут её на место. Файл, который вы правили, — не настройка; это отображение состояния линии, которым владеет другой компонент.
Почему одна устаревшая запись стоит секунд на каждый запрос
Резолвер glibc проходит список серверов имён по порядку и выжидает тайм-аут, прежде чем попробовать следующий, а resolv.conf(5) ограничивает этот список тремя записями. Поставьте резолвер со стороны туннеля, например 10.8.0.1, в начало после того, как туннель исчез, и каждый запрос заплатит тайм-аутом, прежде чем перейти к серверу, который отвечает. Поэтому симптом выглядит как мёртвое соединение, а не как ошибка DNS: браузеры блокируются, выходят по времени и иногда отдают кэшированный адрес, который потом устаревает.
Это же объясняет, почему жалоба приходит как «интернет сломался». Ping по IP-адресу доказывает, что линия в порядке, и из-за этого сбой выглядит как проблема приложения. Список резолверов — первое, что нужно прочитать, и последнее, что нужно править.
Миф: resolv.conf — это файл настроек
Спросите, чем на самом деле является этот путь, прежде чем его менять:
ls -l /etc/resolv.conf
readlink -f /etc/resolv.conf
На хосте с systemd-resolved это символическая ссылка на stub-файл, указывающий на 127.0.0.53, а настоящие серверы живут в состоянии по каждой линии, которое печатает resolvectl. На хосте с NetworkManager это может быть файл, который NetworkManager пишет из активного соединения. У некоторых клиентов производителей это обычный файл, перезаписываемый на месте при подключении и, если вам не повезло, никогда не восстанавливаемый при отключении. Это три разных владельца, и правка первых двух вручную либо ничего не делает, либо держится до следующего сетевого события.
resolvectl status — это представление, которое говорит правду: DNS-серверы по каждой линии, домены маршрутизации и существует ли ещё линия туннеля. resolvectl query example.com идёт дальше и показывает, какой интерфейс ответил. Используйте оба, прежде чем трогать файл, и помните, что браузер с собственным защищённым DNS всё это игнорирует.
Найдите владельца, прежде чем что-то править
Обычно три компонента соревнуются за одну и ту же настройку: systemd-resolved, NetworkManager и то, что установил клиент VPN. Сначала определите живого:
systemctl is-active systemd-resolved
nmcli connection show --active
ps aux | grep -E "openvpn|wg-quick|vpn"
Если resolved активен и символическая ссылка указывает на его stub, глобальный файл — это сгенерированный вывод, и ваша правка косметическая. Если соединением владеет NetworkManager, серверы принадлежат профилю соединения, поэтому исправление — это изменение свойства через nmcli, а не правка файла. Если работает демон производителя, следующее подключение переживёт только его собственный путь восстановления.
Уберите состояние линии, оставленное клиентом
Убитый клиент не может выполнить свой хук очистки. SIGKILL вообще невозможно перехватить, а SIGINT и SIGTERM можно, поэтому туннель, который «просто остановился» после принудительного убийства, часто оставляет на месте и регистрацию интерфейса, и запись резолвера. Найдите конкретный PID и пошлите сигнал только ему:
ps aux | grep -E "openvpn|wg-quick"
sudo kill <pid>
resolvectl revert tun0
Не хватайтесь за pkill -f vpn или killall vpn, пока не прочитали полный список совпадений. -f сопоставляет всю командную строку, поэтому может завершить скрипт-обёртку, сеанс редактора или посторонний процесс, в пути которого есть эта строка. Завершение не того процесса посреди работы — это способ, которым проблема резолвера превращается в потерянный файл.
resolvectl revert сбрасывает конфигурацию DNS времени выполнения этой линии, что уже, чем перезапуск резолвера, и намного уже, чем правка глобального файла. Если линия туннеля исчезла полностью, systemctl restart NetworkManager перестраивает состояние соединения, и это тот шаг, к которому постоянно возвращаются исходные ветки. Следите за менеджером служб с Restart=always: он может вернуть убитый клиент и его настройки DNS прямо на место.
Другое направление: протолкнутый DNS, который так и не пришёл
Зеркальное отражение устаревшей записи — туннель вообще без пригодного резолвера. Опция DNS в профиле — это запрос; компонент, управляющий соединением, должен передать её резолверу. Если журнал показывает, что сервер получен, но линия туннеля не несёт никаких настроек DNS, отсутствует интеграция, а не сервер.
Проверьте передачу, выполнив её вручную; это отделяет «сервер неверный» от «никто его не применил»:
resolvectl dns tun0 10.10.10.10
resolvectl domain tun0 ~.
Домен маршрутизации, перехватывающий всё, отправляет каждое имя на эту линию, чего хочет клиент полного туннеля и что не должен использовать раздельный DNS. Эти настройки исчезают при следующем подключении. Чтобы сделать их постоянными в NetworkManager, отключите автоматический DNS, задайте сервер на соединении и добавьте домен:
nmcli connection modify office ipv4.ignore-auto-dns yes
nmcli connection modify office ipv4.dns 10.10.10.10
nmcli connection modify office ipv4.dns-search "~."
Для корпоративного туннеля, который должен отвечать только на внутренние имена, перечислите эти зоны с ведущей тильдой вместо перехвата всего, чтобы публичные имена продолжали использовать локальный резолвер.
Обходные пути, которые становятся следующей аварией
Копировать resolv.conf перед подключением и восстанавливать после — законная строка в runbook, и это обходной путь, а не ремонт. Он отказывает ровно тогда, когда это важно, потому что падение или принудительная перезагрузка пропускают восстановление. Запишите это как обходной путь, чтобы следующий человек не строил на нём.
Отключение systemd-resolved и жёстко прописанные публичные серверы — второй популярный ход. Он делает подключение и отключение предсказуемыми и убирает DNS по каждой линии для всех остальных сетей, что ломает раздельный DNS для внутренних имён и сводит на нет смысл туннеля, предназначенного держать запросы внутри. Установка resolvconf и закрепление публичных серверов стоит того же с дополнительным слоем. Считайте любой из них диагностикой: если он возвращает просмотр, вы узнали, что виновата интеграция резолвера, а не то, что публичные серверы правильны.
Долговечное исправление — один владелец на слой: решите, какой компонент владеет DNS линии туннеля, а какой — глобальным значением по умолчанию, запишите это и уберите остальных с пути. Затем проверьте после отключения именем, которое разрешает только VPN. Если приватное имя всё ещё отвечает, регистрация не была удалена; если ничего не разрешается, файл указывает на сервер, которого больше нет. И то и другое видно в resolvectl, прежде чем вы откроете браузер.