Редактирането на 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 това е символна връзка към заглушаващ файл, сочещ към 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 е активен и символната връзка сочи към неговия заглушаващ файл, глобалният файл е генериран изход и редакцията ви е козметична. Ако 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, преди да отворите браузър.