Пакеты могут идти по маршруту 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, который привязывает политику к трафику, маршрутизируемому через именованный интерфейс, а не к глобальному селектору. Это миграция, а не настройка, и трафик всё равно должен соответствовать согласованным селекторам.

OptionUse it whenCost
Narrow the selectorThe broad prefix was convenienceA rekey and a policy review
Passthrough childThe broad selector must stayOne exception per intended pair
XFRM interfacePolicy should follow routingA design migration

Докажите исключение, не ослабляя остальное

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

Запишите, какой префикс использует какой путь и почему. Иначе следующий инженер, увидев широкий селектор, снова откроет то же расследование, и ответ будет лежать в сообщении commit, которое никто не читает.

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