Убитий openconnect: маршрути й DNS досі вказують у тунель
Мертвий процес openconnect може залишити встановлені маршрути й записи resolver. Пройдіть шлях вимкнення, надішліть сигнал, який документує ваша збірка, і приберіть.
Тунель вимкнено, але машина поводиться так, ніби він увімкнений: запит висить до завершення часу очікування, а маршрут вказує в інтерфейс, якого більше немає. Це підпис процесу openconnect, який помер, не запустивши свого помічника відключення. Мережевий стан, який він створив, досі встановлений, і більше ніщо в системі не знає, як його прибрати.
Пройдіть машину в тому порядку, у якому створювався стан: процес, канал, маршрут, resolver. Кожен крок каже, чи справді зник клієнт, чи просто від’єднався від вашого термінала, і ця різниця вирішує, чи взагалі щось лагодити.
Почніть із процесу, а не з конфігурації
Відкрийте термінал і запитайте, що ще працює, перш ніж торкатися маршруту. pgrep -a openconnect перелічує кожен екземпляр із його аргументами, що показує pid-файл і скрипт, який йому передали. Процес, якого ви не чекали, пояснює фантомний тунель швидше за будь-який журнал.
Якщо нічого не працює, подивіться на канал. ip link show tun0 повідомляє, чи вижив інтерфейс, і ip route show dev tun0 перелічує маршрути, які досі прив’язані до нього. Потім перевірте resolver за допомогою resolvectl status. Запишіть усі три виводи, перш ніж їх змінювати, бо саме цей запис і є способом згодом відрізнити застарілий запис від нового.
Інтерфейс, який зникає, зазвичай забирає свої маршрути з собою. Маршрути, що пережили канал, зазвичай означають, що процес ще живий або що пристроєм володіє другий клієнт.
Саме допоміжний скрипт скасовує зміни
openconnect сам не видаляє інтерфейс, маршрути чи записи resolver. Він викликає зовнішнього помічника, /etc/vpnc/vpnc-script в upstream-збірці та /usr/share/vpnc-scripts/vpnc-script у пакетах Debian і Ubuntu, обраний за допомогою -s. Той самий скрипт, який піднімає тунель, його й розбирає.
Якщо процес завершується, не викликавши цього помічника, стан залишається. Посібник OpenConnect прямо каже, що маршрутизація й служба імен не працюватимуть правильно без скрипта, і описує помічника як компонент, який під час виходу розбирає стан інтерфейсу. Тому шлях важливий, коли ви запускаєте клієнт за допомогою -s.
Який сигнал доходить до цього шляху, змінилося між версіями. Посібник 7.06 вважає SIGTERM негайним виходом, який пропускає скрипт. Поточні збірки документують INT і TERM як чисту зупинку, коли сеанс завершується, а помічник запускається. Читайте розділ SIGNALS того двійкового файлу, який у вас справді є, замість того щоб припускати одну з двох поведінок.
man openconnect | sed -n '/^SIGNALS/,/^LIMITATIONS/p'
Надішліть сигнал, який документує ваша збірка
Коли сигнал відомий, зупиніть процес за pid, а не за шаблоном.
pgrep -a openconnect
sudo kill -INT "$(cat /var/run/openconnect.pid)"
Потім повторіть три перевірки з першої частини замість того, щоб довіряти коду виходу. ip link show tun0 має завершитися невдачею, ip route show dev tun0 не має нічого друкувати, і resolvectl status більше не має перелічувати VPN-канал.
SIGHUP — не кнопка зупинки: він відключає, запускає скрипт і залишає сеанс відновлюваним за допомогою --cookie. SIGUSR2 примусово запускає негайне перепідключення. SIGKILL повністю пропускає очищення, і саме такий стан описує ця стаття.
Полагодьте resolver, не замінюючи resolv.conf
У більшості систем Ubuntu /etc/resolv.conf це символічне посилання на systemd-resolved, а не файл, який вам слід редагувати. Його заміна ламає розв’язання імен для всіх мереж, а не лише для VPN. Натомість видаліть реєстрацію тунелю:
resolvectl revert tun0
resolvectl query example.com
Якщо система використовує resolvconf, а не systemd-resolved, запис для інтерфейсу зберігається, доки йому не скажуть відпустити канал, і resolvconf -d tun0 це еквівалентна дія. Перевірте, який resolver використовується, перш ніж вибирати команду.
Запит, досі спрямований на сервер за мертвим каналом, висить до завершення часу очікування, і ця затримка виглядає як зламаний DNS-сервер, а не як залишковий маршрут.
Зробіть наступне відключення нудним
Тримайте шлях до pid-файлу однаковим під час запуску й вимкнення, передаючи --pid-file щоразу, або запускайте openconnect під unit чий KillSignal збігається із сигналом, який документує ваша версія. Перевірка спершу на передньому плані показує повідомлення вимкнення, які друкує помічник.
Підключіться, відключіться й один раз виконайте три перевірки. Чистий вихід не залишає ні VPN-каналу, ні VPN-маршруту, ні запису VPN-resolver. Якщо одна з трьох перевірок вижила, тепер ви знаєте, який компонент не прибрав. Наступне розслідування тоді починається з цієї відповіді, а не з завислого запиту.