Убитый 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. Если одна из трёх проверок не прошла, теперь вы знаете, какой компонент не убрал за собой. Следующее расследование тогда начинается с этого ответа, а не с зависшего запроса.