У мене була лабораторна машина, яка приймала тунель з віддаленого майданчика і водночас набирала мережу постачальника. Вихідний профіль працював тижнями. Після додавання вхідного сервера вихідний підключився, а потім протягом кількох секунд перестав пропускати трафік або відмовився запускатися з помилкою «адреса вже використовується». Файли конфігурації не змінювалися; хост просто отримав другий процес 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 хоста. Інакше наступна людина, яка додасть третій тунель, знову виявить те саме зіткнення, і єдиним видимим доказом буде з'єднання, яке працює, доки не перезапуститься чужий демон.

Схожі статті