Клиент OpenVPN зависает, когда его сервер работает на том же хосте
Два экземпляра OpenVPN на одном хосте борются за один и тот же локальный порт и одну и ту же таблицу маршрутизации. Закрепите порт, разделите устройства и проверьте, какая таблица победит.
У меня была лабораторная машина, которая принимала туннель с удалённой площадки и одновременно набирала сеть поставщика. Исходящий профиль работал неделями. После добавления входящего сервера исходящий подключился, а затем в течение нескольких секунд перестал пропускать трафик или отказался запускаться с ошибкой «адрес уже используется». Файлы конфигурации не менялись; хост просто получил второй процесс OpenVPN со своим мнением о портах и маршрутах.
Сбой не случаен, и это не проблема аутентификации. Два демона на одной машине конкурируют за один и тот же локальный сокет и одну и ту же таблицу маршрутизации, и тот, кто запустился или переподключился последним, обычно побеждает. Знание того, какое из этих двух столкновений у вас, определяет, куда смотреть в первую очередь.
Читайте симптом в обратном порядке
Начните с того, когда туннель умирает. Ошибка привязки при запуске указывает на слушающую сторону: что-то уже владеет этим портом, и OpenVPN отказывается запускаться, вместо того чтобы делить его. Туннель, который поднимается и затем замолкает, указывает на маршрутизацию, потому что маршрут, установленный другим экземпляром, может увести пакеты внешнего соединения с их пути.
Оба случая дают одну и ту же жалобу пользователя, поэтому циклы повторных попыток и сторожевые скрипты ничего не исправляют. Они снова подключают клиент к тому же конфликту. Полезный первый вопрос — работает ли процесс в момент остановки трафика.
Один сокет и одно устройство на экземпляр
Слушающий сервер привязывает свой порт; исходящему клиенту тоже нужен локальный порт для инкапсулированного трафика. Когда оба живут на одном хосте, поведение клиента по умолчанию может столкнуться с портом сервера. Локальный порт клиента можно закрепить, а привязку можно пропустить там, где партнёру не нужен фиксированный порт источника:
lport 1195
nobind
dev tun1Эти числа — примеры, а не требование. Важно, чтобы клиент перестал конкурировать за порт сервера и каждый экземпляр получил отдельное туннельное устройство. Два демона, совместно использующие tun0, перезаписывают состояние устройства друг друга, даже когда их порты различаются, поэтому одно устройство на туннель обязательно.
nobind относится к клиентской стороне. Сервер всё равно должен привязываться и слушать, поэтому не копируйте строку в конфигурацию сервера и не отключайте привязку на клиенте, чей партнёр фильтрует по фиксированному порту источника.
Выберите одного владельца маршрута по умолчанию
Только одно соединение может установить маршрут по умолчанию. Если оба профиля перенаправляют весь трафик, второе подключение молча заменяет первое, и первое выглядит сломанным. Либо держите исходящий туннель раздельным и проталкивайте только префиксы поставщика, либо дайте ему отдельную таблицу маршрутизации.
ip rule add from 10.9.0.2 table 120
ip route add default dev tun1 table 120
ip route get 10.9.0.2Адреса и номер таблицы выше — это заполнители. Сразу после добавления правила убедитесь, что собственный адрес VPN-сервера по-прежнему разрешается через обычную таблицу; таблица, перехватывающая внешний транспорт, ломает туннель, который должна была защитить, а следующий за этим цикл переподключения выглядит как ненадёжный провайдер.
Для конфигурации, которая должна переживать переподключения и перезагрузки, сетевое пространство имён — более прочная граница. Второй клиент работает в своём пространстве имён со своими интерфейсами и маршрутами, и раскрываются только службы, которым нужно пересечь границу. Хост сохраняет один маршрут по умолчанию, и переподключение пространства имён не может его перезаписать.
Проверяйте таблицей, а не строкой состояния
Клиент, сообщающий о подключении, доказывает только свой канал управления. Зафиксируйте состояние маршрутизации до и после каждого подключения, затем спросите ядро, какое устройство использовал бы реальный адресат:
ip route show
ip route get 10.40.0.20
ss -lunp | grep 1194Если выбранное устройство для адреса поставщика меняется при запуске второго туннеля, у вас столкновение маршрутов. Если оба процесса видны на одном локальном порту, у вас столкновение сокетов. Исправление первого без второго лишь переносит сбой на следующее переподключение.
Запишите порты, устройства, таблицы и владельца маршрута в runbook хоста. Иначе следующий человек, добавляющий третий туннель, снова обнаружит то же столкновение, и единственным видимым доказательством будет соединение, которое работает, пока не перезапустится чужой демон.