Два клиента OpenVPN на одном шлюзе Linux: разделите политику
Оба туннеля могут подняться, хотя каждый клиент использует один. Решайте по источнику, дайте каждой группе свою таблицу, затем разрешите и транслируйте на выбранном устройстве.
Два демона 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 в списке интерфейсов доказывают, что оба демона запустились; они ничего не говорят о том, какое использовал конкретный клиент. Второй прогон, с одним отсутствующим туннелем, и есть тот, который показывает, делает ли ваше резервное правило то, что задумано.