Полный туннель в strongSwan требует 0.0.0.0/0 с обеих сторон
Полному туннелю нужен 0.0.0.0/0 как remote_ts клиента и как local_ts шлюза, плюс перенаправление, NAT и обратный маршрут. Проверьте все четыре.
Подключение strongSwan, работающее для одной частной подсети, не начнёт передавать интернет-трафик только потому, что кто-то отредактировал одну строку. Полный туннель — это соглашение двух сторон о том, какие адреса защищает child SA, и каждая сторона называет другую относительно себя. Сделайте одну сторону правильной, а другую неправильной, и child SA либо не поднимется, либо поднимется уже, чем задумано. Пять проверок ниже следуют этому соглашению от клиента через шлюз до интернета.
Сначала проверьте селектор клиента
Клиент описывает то, что хочет защитить на дальней стороне, как remote_ts, и всё, что он отправляет, исходит из его собственного назначенного адреса. Для интернет-трафика это значение должно покрывать адреса, которых пользователь действительно достигнет, что на практике означает всё пространство IPv4. Клиент, который всё ещё перечисляет одну подсеть, просит разделённый туннель, как бы профиль ни назывался в интерфейсе. Сторона источника обычно dynamic, поскольку адрес назначается при подключении. Фиксированный источник, записанный там, ломается, как только меняется пул адресов.
children {
net {
local_ts = dynamic
remote_ts = 0.0.0.0/0
}
}
Этот фрагмент не является полным файлом подключения, и он предполагает, что аутентификация, идентичности и пул виртуальных адресов уже настроены. Селектор источника клиента и адрес, который назначает сервер, всё ещё должны совпадать, иначе child SA поднимется с охватом, которого не ожидала ни одна сторона. Загрузите его с помощью swanctl --load-all и прочитайте вывод, прежде чем считать, что всё получилось. Файл, который разбирается, всё равно может быть отклонён из-за селектора, не пересекающегося с предложением другой стороны.
Проверьте селектор шлюза на его собственной стороне
Шлюз читает то же понятие в противоположном направлении. Интернет-назначения локальны для шлюза, поэтому его local_ts — широкий, а remote_ts описывает пул клиентов. Эта инверсия — самая частая ошибка в конфигурации полного туннеля, и она проходит проверку, потому что обе строки по отдельности выглядят правдоподобно.
children {
rw {
local_ts = 0.0.0.0/0
remote_ts = 10.77.0.0/24
}
}
Копирование фрагмента клиента в файл шлюза даёт пару селекторов, которая не описывает ничего полезного, поскольку обе стороны претендовали бы на одну и ту же роль. Руководство strongSwan по перенаправлению явно документирует сопряжение клиента и шлюза, и его стоит читать рядом с файлом подключения, а не после сбоя. Файлу шлюза также нужно определение пула, на который ссылается remote_ts. Селектор, называющий несуществующий пул, загружается без жалоб и терпит неудачу при подключении.
Старый ipsec.conf использует левую и правую роли с разными ключами, и строка rightsubnet не является прямой заменой значения swanctl. Держите два синтаксиса в отдельных файлах, вместо того чтобы вставлять один в другой. Смешивание их в одном каталоге — это то, как рабочее подключение тихо возвращается назад после перезагрузки.
Проверьте согласованный child SA, а не файл
Сохранённая конфигурация доказывает намерение и ничего больше. Другая сторона может сузить запрошенное, а существующий child SA не заменяется только потому, что файл под ним изменился. Подтвердите, что действительно установлено, прежде чем менять что-то ещё.
swanctl --list-conns
swanctl --list-sas
ip xfrm policy list
Первая команда показывает, что загрузил демон, вторая — установленные child SA, а третья — политики, которые применит ядро. Если файл говорит 0.0.0.0/0, а список показывает одну подсеть, переговоры сузили охват, и перечитывание файла это не объяснит. Завершите child, запустите её заново и снова сравните все три вывода. Child, возвращающаяся с тем же узким охватом, сужается дальней стороной, а не локальным файлом, и это разговор с другим администратором, а не локальная правка.
Читайте оба направления в списке политик, потому что туннель, устанавливающий одно направление и не устанавливающий другое, — это проблема маршрутизации в костюме конфигурации. Политики вперёд и назад должны называть одну и ту же пару селекторов в зеркальном отражении, а отсутствующее зеркало — дефект демона или предложения, а не текста селектора.
Проверьте перенаправление и обратный маршрут
Селектор пропускает трафик к шлюзу, но не заставляет шлюз маршрутизировать этот трафик дальше. Перенаправление должно быть включено, межсетевой экран должен разрешать поток, а ответ должен найти путь назад к пулу клиентов. Это три отдельных требования, и каждое терпит неудачу с разным симптомом. Отсутствующее правило перенаправления ведёт себя как чёрная дыра, а отсутствующий обратный маршрут — как односторонний туннель.
sysctl net.ipv4.ip_forward
iptables -t nat -S | grep -i masq
ip route get 1.1.1.1
Частным адресам клиентов обычно нужен осознанный перевод источника, прежде чем они смогут покинуть публичный интерфейс, тогда как явно маршрутизированное распределение требует другого подхода. Если участвует NAT, сохраните поддерживаемые реализацией исключения, чтобы трафик, который должна проверять политика безопасности, не переводился в обход неё. Широкое правило masquerade, скопированное с другого шлюза, меняет гораздо больше потоков, чем предполагал его автор. Напишите правило только для пула клиентов и оставьте комментарий, почему оно существует.
На клиенте подтвердите маршруты, установленные бэкендом, а не маршруты, которые вы предположили. Менеджер с отключённой установкой маршрутов нуждается в проекте маршрутизации, поддерживаемом вручную, и этот проект должен обновляться при каждом изменении туннеля. Проверяйте таблицу маршрутизации после повторного подключения, а не только после свежей загрузки.
Проверьте, что туннель всё ещё не покрывает
Пара селекторов покрывает IPv4 и ничего больше. IPv6, DNS и любая политика на уровне приложения — отдельные решения, которые широкий селектор IPv4 молча игнорирует. Туннель, несущий каждый пакет IPv4, всё ещё может утекать каждый поиск имени.
Явно укажите предполагаемый путь DNS, потому что полный туннель, который всё ещё разрешает имена через локальный резолвер, утекает запросы за пределы туннеля и ломает частные имена. Если клиенту назначен адрес IPv6, этому семейству адресов нужно такое же обращение, иначе хост предпочтёт путь, который туннель не защищает. Проверяйте именем, на которое может ответить только частная сторона, и считайте публичный ответ утечкой.
resolvectl query intranet.example.internal
traceroute -n 1.1.1.1
Подтвердите цепочку этими двумя командами и согласованными селекторами из списка выше. Если traceroute показывает локальный маршрутизатор первым переходом, трафик не использует туннель, что бы ни утверждали селекторы. Доступ в интернет полон только тогда, когда выбранный трафик допущен, перенаправлен и возвращён через спроектированный шлюз. Найти 0.0.0.0/0 в профиле — это начало этой цепочки, а не её доказательство.