Полный туннель убил вашу SSH-сессию: закрепите обратный маршрут
Полный туннель перехватывает ответы для вашей собственной SSH-сессии. Закрепите маршрут к хосту для административного адреса через старый шлюз и переустанавливайте его при переподключении.
Запустите клиент OpenVPN на машине, с которой работаете по SSH, и посреди команды сессия зависает. Туннель сообщает о подключении, хост может выходить в интернет через него, а ваши нажатия клавиш по-прежнему доходят, хотя обратно ничего не приходит. Изменился не туннель: изменился обратный путь для пакетов, адресованных вам, теперь он соответствует новому маршруту по умолчанию и уходит в туннель, который удалённый шлюз не станет использовать, чтобы добраться до вашего рабочего места.
Что на самом деле устанавливает redirect-gateway
В форме def1 параметр redirect-gateway добавляет 0.0.0.0/1 и 128.0.0.0/1 вместо перезаписи маршрута по умолчанию. Эти две половины покрывают всё адресное пространство, при этом обе остаются более длинными префиксами, чем 0.0.0.0/0, поэтому любой адрес назначения без более конкретного совпадения теперь уходит в туннель. Именно этот механизм и следует запомнить: каждое исправление ниже работает за счёт установки более конкретного совпадения.
Ваш административный адрес — один из таких адресов назначения.
VPN-сервер пересылает трафик своих клиентов в интернет. У него нет маршрута для публичного адреса, с которого вы подключаетесь, и нет причин считать эти пакеты чем-то иным, кроме трафика от клиента, поэтому он их отбрасывает. При этом отправленный вами запрос всё же дошёл до хоста — вот почему сессия выглядит живой только с одной стороны.
ip route show table main | head -n 20
ip route get 198.51.100.23Найдите свой исходный адрес и путь до туннеля
На сервере выведите установленное SSH-соединение и отметьте адрес пира, с которого оно пришло. Именно этот адрес должен покрывать ваш обратный маршрут, и это не всегда то, что вы думаете: промежуточный хост, NAT-шлюз или транслятор оператора может подставить другой источник.
Затем найдите физический шлюз и интерфейс, которые несли трафик до запуска туннеля. В схеме def1 маршрут по умолчанию по-прежнему присутствует под полумаршрутами, так что информация доступна, хотя чтение длинной таблицы маршрутов на глаз располагает к ошибкам.
Запишите оба значения и имя интерфейса вместе, потому что маршруту, который вы собираетесь добавить, нужны все три. Если хост выбирал аплинк по правилу политики маршрутизации, обычный маршрут может вообще не учитываться, и эта возможность меняет исправление.
Закрепите маршрут к хосту, который важнее полумаршрутов
Маршрут /32 длиннее любого из полумаршрутов, поэтому ответы на ваш адрес выбирают его, а не туннель. Следующий узел — шлюз, существовавший до туннеля, а устройство — физический интерфейс, что удерживает пакет на том пути, который он использовал до появления туннеля.
ip route add 198.51.100.23/32 via 203.0.113.1 dev eth0Проверяйте поиском по таблице, а не просмотром таблицы: в ответе должны быть eth0 и шлюз, и никогда tun0.
OpenVPN уже добавляет маршрут к хосту по собственному адресу VPN-сервера по той же причине, поэтому схема знакома, а административный адрес — просто ещё одно исключение. Не прибегайте к route-nopull, чтобы это исправить: он отбрасывает продвигаемые маршруты, нужные туннелю, включая удалённую сеть и параметры DNS.
Сделайте так, чтобы это пережило переподключение
Маршрут, добавленный вручную, исчезает, когда клиент переподключается и устанавливает свои собственные, что превращает исправление в повторяющийся сбой. Привяжите команду к чему-нибудь, что выполняется после установки маршрутов.
Подойдёт и скрипт route-up, и хук pre-up сетевого менеджера, а надёжная проверка — переподключение с последующим тем же поиском.
В Windows эквивалент — постоянный маршрут, добавленный с -p: он переживает перезагрузки, но после смены сети всё равно должен указывать на правильный шлюз. Какой бы ни была платформа, напишите причину рядом с маршрутом: следующему администратору нужно знать, что тот существует для защиты сеанса управления, а не потому, что этого требовала схема сети.
Когда закреплённого маршрута всё ещё недостаточно
Фильтрация обратного пути может отбросить пакет, который приходит через один интерфейс, а уходит через другой, именно это и создаёт закреплённый маршрут. Проверьте действующее значение rp_filter, прежде чем отключать что-либо глобально, и предпочтите исправить асимметрию, а не выключать проверку. Применяется настройка для интерфейса, а мягкий режим часто лишь регистрирует асимметрию, не отбрасывая пакет. Прочитайте оба варианта, прежде чем решать, что виноват фильтр.
Хостам с политикой маршрутизации нужно не только правило, но и маршрут, потому что база правил выбирает таблицу раньше, чем из неё читается маршрут. Маршрут в основной таблице невидим для потока, который совпадает с правилом, указывающим на другую таблицу. Прочитайте правила, прежде чем что-то добавлять в main. Если правило уже покрывает трафик управления, исключение должно быть в таблице этого правила.
Держите открытой консоль вне основного канала, пока тестируете, и перепроверьте из второго входа, прежде чем отключать тот, которым пользуетесь. Маршрут, отправляющий ваш собственный трафик управления в туннель, обрывает соединение, через которое вы его чините. Вернуться тогда можно только через последовательную консоль или аварийную загрузку, плохой размен за пропущенный шаг проверки.