Почему маршрут OpenVPN проигрывает политике XFRM strongSwan
Конкретный маршрут OpenVPN не отменяет политику XFRM: прочитайте маршрут и селекторы политики, затем сузьте, сделайте исключение или перейдите на интерфейс XFRM.
Пакеты могут идти по маршруту OpenVPN и всё же попадать под политику IPsec, и эта комбинация с любого угла выглядит как ошибка маршрутизации, кроме правильного. Linux решает маршрут и затем обращается к отдельной базе политик безопасности, поэтому более конкретный маршрут к назначению не вытесняет подходящую политику XFRM. Видимый симптом — трафик, который покидает хост и никогда не приходит, хотя оба туннеля сообщают о своей исправности. Есть три варианта решения, и какой выбрать, зависит от того, какой из двух путей должен нести этот префикс.
Два решения, а не одно
Выбор маршрута отвечает на узкий вопрос: какой следующий узел и адрес источника должны нести этот пакет. База политик безопасности отвечает на другой: требует ли этот пакет защиты IPsec и под какими селекторами. Оба работают для одного пакета, и выполнение первого ничего не говорит о втором. Поэтому изменение метрики или добавление статического маршрута может оставить симптом нетронутым.
Широкий селектор IPsec — обычная причина. Политика, защищающая 172.16.0.0/12, покрывает и 172.20.8.0/24, куда администратор, возможно, собирается попасть через туннель OpenVPN. Намерение существует только в таблице маршрутизации, и база политик о нём никогда не знала.
Относитесь к этому как к конфликту между двумя настроенными путями защиты, а не как к состязанию двух метрик. Исправление принадлежит тому компоненту, который был настроен с неверным охватом.
Прочитайте маршрут, который ядро действительно выбирает
Начните с поиска, который выполняет ядро, включая адрес источника и любое правило политики, способное направить его в другую таблицу. Маршрут в главной таблице может никогда не рассматриваться, если более раннее правило выбирает другую таблицу, а совпадение по самому длинному префиксу действует только внутри таблицы, выбранной правилом.
ip rule show
ip route show table all
ip route get 172.20.8.20 from 10.44.7.15
Последняя команда — та, что важна, потому что она печатает выбранный маршрут вместе с адресом источника, который ядро использовало бы. Сравните этот вывод с селектором, которому соответствует политика IPsec. Когда маршрут указывает на интерфейс OpenVPN, а политика по-прежнему соответствует той же паре, вы воспроизвели конфликт без догадок.
Держите дампы свободными от посторонних адресов, прежде чем они попадут в тикет. Таблица маршрутизации с рабочего хоста несёт внутреннюю топологию, и вставлять стоит только строки, отвечающие на вопрос.
Прочитайте и политику, которая также применяется
Список политик показывает направление, селекторы и шаблон, который решает, что происходит с подходящим пакетом. Сначала читайте исходящее направление, затем входящую сторону для обратного трафика, потому что одностороннее исключение даёт соединение, которое начинается и никогда не завершается.
ip -s xfrm policy
swanctl --list-sas
Сравните селекторы в списке с префиксами, которые согласовало соединение. Отключение установки маршрутов в strongSwan не удаляет эти политики, а изменение метрики не меняет, какую пару источника и назначения защищает политика. Эти две ложные правки стоит исключить сразу, потому что люди пробуют именно их.
Если в списке нет политики для ожидаемого префикса, проблема в другом месте, и таблица маршрутизации, вероятно, говорит правду. Если в нём есть более широкая политика, охватывающая префикс, вы нашли перехват.
Три варианта, когда оба пути законны
Сужение селектора IPsec — самый чистый вариант, когда широкий префикс был удобством, а не требованием. Сокращение селектора удалённого трафика до подсетей, которые действительно находятся за IPsec, снимает конфликт сразу для всех хостов, и это стоит пересогласования ключей, а не нового компонента.
Исключение с проходом — хирургический вариант, когда широкий селектор должен остаться. strongSwan поддерживает отдельное соединение, чей child использует режим pass, что сообщает ядру: подходящий трафик не должен обрабатываться IPsec. Удалённый адрес loopback удерживает это соединение от выбора для входящих партнёров, и селекторы должны описывать реальную разрешённую пару, а не всё.
connections {
openvpn-exception {
remote_addrs = 127.0.0.1
children {
openvpn-exception {
local_ts = 10.44.7.0/24
remote_ts = 172.20.8.0/24
mode = pass
start_action = trap
}
}
}
}
Примеры конфигурации strongSwan описывают этот тип политики и соглашение о loopback-партнёре. Третий вариант — это дизайн на основе маршрутизации с интерфейсами XFRM, который привязывает политику к трафику, маршрутизируемому через именованный интерфейс, а не к глобальному селектору. Это миграция, а не настройка, и трафик всё равно должен соответствовать согласованным селекторам.
| Option | Use it when | Cost |
|---|---|---|
| Narrow the selector | The broad prefix was convenience | A rekey and a policy review |
| Passthrough child | The broad selector must stay | One exception per intended pair |
| XFRM interface | Policy should follow routing | A design migration |
Докажите исключение, не ослабляя остальное
После загрузки изменения проверьте исключение и обычный адрес назначения, который должен остаться защищённым. Проверьте оба направления, затем опустите туннель OpenVPN и подтвердите, что происходит с исключённым трафиком. Исключение, которое молча отправляет этот префикс открыто при опущенном туннеле, — это решение о политике, которое нужно принять осознанно, а не обнаружить во время инцидента.
Запишите, какой префикс использует какой путь и почему. Иначе следующий инженер, увидев широкий селектор, снова откроет то же расследование, и ответ будет лежать в сообщении commit, которое никто не читает.