IPsec внутри IPsec: какие адреса должен нести внешний туннель
Дайте внешнему туннелю адреса внутренних шлюзов, а не подсети приложений. Затем докажите пересылку, трансляцию и MTU на каждом уровне, прежде чем называть это вложенным.
Вложенный IPsec проще осмыслить, когда два уровня заканчиваются на разных машинах. Четыре шлюза, два туннеля и один вопрос, который решает, работает ли схема: что внешний туннель действительно видит, когда внутренний закончил с пакетом? Ответьте на него — и селекторы, маршруты и порядок поиска неисправностей последуют сами. Ошибётесь — проведёте день, отлаживая туннель, который технически поднят.
Модель четырёх шлюзов
Внешние шлюзы A и B строят первый туннель между двумя площадками. За A стоит внутренний шлюз C с транзитным адресом 10.60.0.2; за B стоит внутренний шлюз D с транзитным адресом 10.70.0.2. Сети приложений живут за C и D, и все адреса в примере намеренно не пересекаются.
application net -> C -> A == outer IPsec == B -> D -> application net
\---------- inner IPsec ----------/
C transit: 10.60.0.2 D transit: 10.70.0.2
A and B: underlay addresses only
Разделение уровней по четырём хостам означает, что каждая машина держит одну границу. Одному хосту, запускающему оба уровня, приходится согласовывать два набора политик, две таблицы маршрутизации и два режима отказа на одной машине; это возможно и гораздо труднее для наблюдения.
Каждый уровень снимает только свою защиту
C шифрует пакет приложения для D. Результат адресован от C к D, и именно он достигает A. Всё дальше зависит от этого переписывания.
A шифрует его снова для B. B расшифровывает внешний уровень, видит пакет от C к D и пересылает его всё ещё зашифрованным. D снимает внутреннюю защиту и доставляет пакет приложения.
Итак, A и B видят внутренние конечные точки и их метаданные, но не являются сторонами, которые расшифровывают полезную нагрузку приложения. Это реальное свойство схемы, а не утверждение, что C, D или хосты приложений заслуживают доверия.
Внешние селекторы называют внутренние шлюзы
Здесь большинство таких построений и рушится. Для внешнего туннеля на основе политик селекторы, которые вы согласуете, должны содержать адреса, которыми A и B действительно оперируют: 10.60.0.2/32 и 10.70.0.2/32, в правильном локальном и удалённом порядке.
Помещение итоговых подсетей приложений во внешние селекторы не работает, потому что к моменту, когда пакет доходит до A, внутренняя инкапсуляция уже переписала то, что A должен защищать. Тогда внешняя политика не совпадёт ни с чем, и туннель поднимется, не неся данных.
Не сужайте внешнее разрешение до UDP 500. У внутреннего соединения свой путь данных: он использует ESP или инкапсуляцию UDP в зависимости от того, что согласовано, и внешняя политика должна разрешать этот протокол.
Проверьте результат с помощью swanctl --list-sas на каждом шлюзе и убедитесь, что дочерние ассоциации безопасности сообщают именно те адреса, которые вы задумали, а не те, что предположили. Если список показывает подсети приложений, внешняя политика написана для неверного уровня. Исправьте селекторы, прежде чем отлаживать маршрутизацию, потому что маршрутизация будет выглядеть правильно, а счётчики не сдвинутся.
Пересылка и ловушка рекурсии
Селекторы не заменяют маршрутизацию. A и B должны пересылать трафик между C и D в обоих направлениях, что означает включённую пересылку IP, маршруты, указывающие на туннель, и обратный путь, существующий на другой стороне.
Если внешний туннель использует интерфейсы XFRM, маршруты выбирают интерфейс, а согласованные политики по-прежнему ограничивают то, что он несёт. Интерфейс не расширяет защищаемое; он лишь меняет то, как ядро подхватывает пакет.
Ловушка — рекурсия. Маршрут A к внешней конечной точке B должен идти по нижележащей сети, а не по туннелю, который строит A, иначе инкапсуляция пытается ехать внутри себя, и соединение никогда не завершается.
Проверьте трансляцию перед добавлением уровней
Посмотрите на любой source NAT на A и B, прежде чем что-либо ещё настраивать. Правило, переписывающее адрес C до применения политики IPsec, может сломать согласованные селекторы, а также изменить то, что D получает на другой стороне.
Широкий маскарадинг не становится безопаснее из-за двух уровней. Он скрывает, какой адрес видит удалённая сторона, а это именно та информация, которая нужна, когда туннель поднят, а приложение не работает.
Если правило NAT действительно необходимо, запишите, с каким адресом каждая сторона считает, что говорит. Эта одна строка решает большинство споров о том, виноват туннель или трансляция. Она также подскажет следующему инженеру, куда смотреть, когда правило уберут через год. Ping ничего из этого не сделает.
Докажите fail-closed и проверьте MTU
Исчезновение маршрута само по себе не является политикой fail-closed. Другая таблица, маршрут по умолчанию или правило политики могут тихо дать запасной путь, и единственный способ узнать это — опустить внешний туннель и понаблюдать, что делает трафик приложений. Сделайте это намеренно, в окне обслуживания, а не обнаруживайте случайно.
Проверьте три состояния: внешний туннель опущен, внутренний туннель опущен и восстановление после возвращения обоих. Используйте счётчики политик на каждом шлюзе, потому что два установленных сеанса IKE доказывают лишь то, что согласование на уровне управления прошло успешно.
Учитывайте обе инкапсуляции. Работающий IKE — это результат для малых пакетов, а пакеты приложений полного размера всё ещё могут не проходить после добавления двух заголовков; тестируйте с известным размером полезной нагрузки на реальном пути, а не предполагайте, что числа сложатся. Арифметика проста, а путь — нет.