Два демона OpenVPN могут оба сообщать об успешном туннеле, пока шлюз отправляет каждого клиента через один и тот же. Ничто в рукопожатии не решает, какой туннель использует клиент; это решает ядро, пакет за пакетом, проходя правила политики, а затем таблицу, которую называет каждое правило. Если смотреть так, конфигурация перестаёт быть про параметры OpenVPN и становится матрицей маршрутизации с двумя владельцами.

Решает ядро, а не демон

Пересылаемый пакет приходит на интерфейс LAN, и код маршрутизации оценивает список правил в порядке приоритета. Первое правило, селектор которого совпадает, называет таблицу, и маршруты этой таблицы выбирают устройство выхода. Если в таблице нет подходящего маршрута, поиск продолжается по следующему правилу, и именно эта деталь заставляет недоделанную настройку сбоить тихо, а не громко.

У процесса туннеля нет слова в этом проходе. Он создаёт интерфейс и может устанавливать маршруты, но попадёт ли пакет конкретного клиента в этот интерфейс, полностью зависит от таблицы, в которую его отправили. Поэтому два туннеля с одинаковыми импортированными маршрутами конкурируют, и последний записавший выигрывает для всех. Поэтому настройка может выглядеть сбалансированной в файлах и всё равно отправлять всех клиентов через один демон.

Дайте каждому экземпляру собственный набор ресурсов

Начните с имён, потому что повторно использованные имена — это путь, по которому два экземпляра случайно начинают делить состояние. Назначьте отдельные туннельные устройства, отдельные файлы конфигурации, отдельные учётные данные и отдельные сервисные единицы. Запишите внешнюю конечную точку и адрес туннеля каждого экземпляра в ту же таблицу, что и матрица политики, чтобы у более позднего изменения было одно место для проверки.

dev tun-office
route-nopull
pull-filter ignore "redirect-gateway"

dev tun-lab
route-nopull

route-nopull держит маршруты, которые проталкивает сервер, вне локальной таблицы, и это именно то, что нужно, когда таблицы политики должны быть явными. Проталкивает ли конкретный сервер также параметр redirect-gateway и поддерживает ли ваша версия клиента форму с фильтром, стоит проверять по руководству, а не предполагать.

Напишите матрицу: источник, таблица, устройство

Для каждой группы клиентов добавьте правило, выбирающее таблицу по адресу источника, а затем поместите нужный путь в эту таблицу:

ip rule add from 10.8.1.0/24 lookup 100 priority 1000
ip rule add from 10.9.1.0/24 lookup 200 priority 1000
ip route add default dev tun-office table 100
ip route add default dev tun-lab table 200

Таблице нужны маршруты назначения, которые должны быть у группы, плюс любые локальные или управленческие исключения, сохраняющие шлюз пригодным. Таблица, содержащая только маршрут по умолчанию, — это политика полного туннеля для этой группы, что может быть совершенно правильным, но это должно быть решением, а не упущением.

Собственный транспорт туннеля не в группе клиентов

Зашифрованные пакеты каждого демона возникают на самом шлюзе и адресованы внешнему партнёру. Правило, совпадающее только с префиксом источника клиента, оставляет эти пакеты в покое, поэтому правила, ограниченные источником, безопаснее правил, совпадающих со всем. Правило без селектора может захватить собственный транспорт туннеля и отправить его обратно через туннель, и тогда соединение сбоит так, что это выглядит проблемой провайдера.

Держите локальный сеанс управления и путь нижнего уровня явно вне таблиц политики. Запишите эти исключения рядом с матрицей; они часть замысла, а не обходной путь, который нужно заново обнаружить во время инцидента.

Выбор пути не даёт разрешения

Разрешение на пересылку — второе решение, принимаемое позже на пути. Правило межсетевого экрана, принимающее пакеты, выходящие через второй туннель, не заставляет код маршрутизации выбрать его, а правильная таблица не даёт разрешения пересылать. Должно быть и то и другое, а тест, доказывающий только одно, введёт вас в заблуждение насчёт другого. Когда одна группа работает, а другая нет, проверяйте эти два шага отдельно, вместо того чтобы переписывать таблицы.

Трансляция источника — третье решение, и она должна ограничиваться группой источника и туннельным устройством, которое действительно его несёт. Добавьте отдельную цепочку для двух экземпляров вместо очистки цепочки postrouting, потому что несвязанные службы могут иметь там записи, и очистка тихо их удаляет.

Что происходит, когда один туннель падает

Определите поведение при отказе заранее. Когда туннельная таблица теряет свой маршрут, поиск проваливается к следующему правилу, и трафик группы продолжает идти через другой туннель или обычный вышестоящий канал без всякой ошибки. Если это неприемлемо, добавьте завершающее правило с меньшим номером приоритета, которое для этого источника возвращает недостижимый результат, чтобы потеря была видна, а не поглощена.

Отправьте новый запрос из каждой группы источника и запишите четыре факта: выбранную таблицу, устройство выхода, транслированный источник и вернулся ли ответ тем же путём. Затем опустите один туннель и повторите. Два устройства TUN в списке интерфейсов доказывают, что оба демона запустились; они ничего не говорят о том, какое использовал конкретный клиент. Второй прогон, с одним отсутствующим туннелем, и есть тот, который показывает, делает ли ваше резервное правило то, что задумано.

Похожие статьи