Site-to-site VPN между офисами на IKEv2 (strongSwan)
Два офиса, два шлюза, одна общая сеть без публикации сервисов наружу — классическая задача для IPsec. WireGuard тоже справится, но когда нужна совместимость с оборудованием других вендоров или у одной из сторон уже стоит strongSwan/Cisco/Mikrotik с поддержкой IKEv2, выбор падает на IPsec. Разберём, как поднять туннель через strongSwan: конфигурацию conn на обеих сторонах и разницу между policy-based и route-based режимом — от этого выбора зависит, как потом придётся жить с маршрутизацией.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Как устроен site-to-site на IKEv2
IKEv2 — протокол согласования ключей, а не сам туннель. Он строит два уровня безопасности: IKE SA (защищённый канал между шлюзами для служебных сообщений) и один или несколько Child SA — это уже ESP-туннели, которые шифруют пользовательский трафик. В site-to-site схеме Child SA привязывается к паре подсетей: «всё из 192.168.10.0/24 в 192.168.20.0/24 идёт через этот туннель».
В отличие от remote-access, где сервер раздаёт клиентам виртуальные IP из пула, здесь оба участника — равноправные шлюзы с известными заранее подсетями и публичными адресами (или DDNS-именами при динамическом IP). Аутентификация строится на PSK (pre-shared key) для простых схем или на X.509-сертификатах для более серьёзных требований — разницу между site-to-site и remote-access архитектурами подробно разбирали в статье site-to-site или remote-access VPN: в чём разница.
Ключевая развилка: как трафик попадает в туннель — по политике IPsec (policy-based) или по обычному IP-маршруту (route-based). Это архитектурное решение, а не деталь конфига — от него зависит, сможете ли вы завтра добавить третью подсеть без пересоздания туннеля.
Установка strongSwan на обоих шлюзах
Ставится одинаково на Ubuntu/Debian с обеих сторон:
apt update
apt install -y strongswan strongswan-pki libcharon-extra-plugins
Модуль libcharon-extra-plugins нужен для дополнительных плагинов, в частности для VTI. Проверьте, что демон charon — реализация IKE в strongSwan — стартует:
systemctl enable --now strongswan
systemctl status strongswan
Дальше на обоих шлюзах включите форвардинг пакетов — без него сервер не пропустит транзитный трафик между локальной сетью и туннелем:
sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
Для site-to-site NAT (MASQUERADE) на внутреннем трафике обычно не нужен и вреден — вторая сторона увидит вместо реальной подсети адрес шлюза, что ломает симметричную маршрутизацию. NAT в этой схеме нужен только для собственного исходящего интернет-трафика шлюза, не для трафика между офисами.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверPolicy-based IPsec: conn с двух сторон в ipsec.conf
Самый распространённый вариант — подсети прописаны прямо в conn, а ядро автоматически строит SPD (Security Policy Database) на основе leftsubnet/rightsubnet. Пример: офис в Москве с публичным IP 203.0.113.10 и сетью 192.168.10.0/24, филиал в Питере с IP 198.51.100.20 и сетью 192.168.20.0/24.
Конфиг на шлюзе офиса А (/etc/ipsec.conf):
config setup
charondebug="ike 1, knl 1, cfg 0"
conn %default
keyexchange=ikev2
authby=secret
ike=aes256-sha256-modp2048!
esp=aes256-sha256-modp2048!
keyingtries=%forever
dpdaction=restart
dpddelay=30s
dpdtimeout=120s
conn office-a-to-b
left=%defaultroute
leftid=203.0.113.10
leftsubnet=192.168.10.0/24
right=198.51.100.20
rightid=198.51.100.20
rightsubnet=192.168.20.0/24
auto=start
ike= и esp= жёстко фиксируют набор алгоритмов (восклицательный знак запрещает fallback на более слабые предложения). dpddelay/dpdtimeout — Dead Peer Detection: если пир не отвечает 120 секунд, соединение считается разорванным и переподнимается по dpdaction=restart.
Общий ключ — в /etc/ipsec.secrets:
203.0.113.10 198.51.100.20 : PSK "здесь-длинный-случайный-ключ-минимум-32-символа"
На шлюзе офиса Б conn — зеркальное отражение первого, с переставленными left/right:
config setup
charondebug="ike 1, knl 1, cfg 0"
conn %default
keyexchange=ikev2
authby=secret
ike=aes256-sha256-modp2048!
esp=aes256-sha256-modp2048!
keyingtries=%forever
dpdaction=restart
dpddelay=30s
dpdtimeout=120s
conn office-b-to-a
left=%defaultroute
leftid=198.51.100.20
leftsubnet=192.168.20.0/24
right=203.0.113.10
rightid=203.0.113.10
rightsubnet=192.168.10.0/24
auto=start
Строка в ipsec.secrets на этой стороне идентична первой — PSK один и тот же для обоих участников. Важно: leftsubnet на одной стороне обязан совпадать с rightsubnet на другой — это частая причина, почему туннель поднимается (IKE SA есть), а трафик не ходит: подсети описаны асимметрично, и Child SA не совпадают по selector'ам.
После правки конфига на обеих сторонах:
ipsec restart
ipsec status
Если всё верно, ipsec status покажет ESTABLISHED для IKE SA и INSTALLED для соответствующего Child SA с указанными подсетями.
Route-based IPsec: VTI вместо leftsubnet/rightsubnet
Policy-based удобен для схемы «одна подсеть на другую», но плохо масштабируется: чтобы добавить ещё одну подсеть, приходится создавать дополнительные conn или писать leftsubnet списком через запятую — и при каждом изменении IPsec пересчитывает и переустанавливает Child SA, что на секунду-другую рвёт трафик.
Route-based решает это иначе: туннель поднимается как обычный сетевой интерфейс (VTI — Virtual Tunnel Interface), а какой трафик в него попадает, решает не IPsec-политика, а таблица маршрутизации Linux. ESP-туннель шифрует всё, что приходит на интерфейс, а какие подсети туда направить — решает ip route add, как с любым другим интерфейсом.
Конфиг conn для route-based схемы (офис А):
conn office-a-to-b-vti
leftsubnet=0.0.0.0/0
rightsubnet=0.0.0.0/0
leftid=203.0.113.10
right=198.51.100.20
rightid=198.51.100.20
mark=42
leftupdown=/etc/strongswan/updown-vti.sh
auto=start
leftsubnet/rightsubnet здесь заведомо «широкие» — реальная фильтрация идёт не через них. mark помечает пакеты для этого туннеля, а скрипт updown-vti.sh при поднятии соединения создаёт сам VTI-интерфейс:
#!/bin/bash
# /etc/strongswan/updown-vti.sh
PLUTO_MARK_OUT_ID=${PLUTO_MARK_OUT#*/}
PLUTO_MARK_IN_ID=${PLUTO_MARK_IN#*/}
case "$PLUTO_VERB" in
up-client)
ip link add vti0 type vti local "$PLUTO_ME" remote "$PLUTO_PEER" \
okey "$PLUTO_MARK_OUT_ID" ikey "$PLUTO_MARK_IN_ID"
sysctl -w "net.ipv4.conf.vti0.disable_policy=1"
ip addr add 169.254.42.1/30 remote 169.254.42.2/30 dev vti0
ip link set vti0 up mtu 1436
ip route add 192.168.20.0/24 dev vti0
;;
down-client)
ip route del 192.168.20.0/24 dev vti0 2>/dev/null
ip link del vti0 2>/dev/null
;;
esac
Дальше трафик направляется через vti0 обычным маршрутом — если завтра появится третья подсеть в офисе Б, достаточно ip route add 192.168.30.0/24 dev vti0 без изменений в ipsec.conf и без пересборки Child SA. disable_policy=1 на интерфейсе критичен — без него ядро повторно прогонит пакет через IPsec policy engine поверх уже расшифрованного трафика и всё сломает.
Что выбрать: policy-based или route-based
| Критерий | Policy-based | Route-based (VTI) |
|---|---|---|
| Конфигурация подсетей | В leftsubnet/rightsubnet конкретного conn | Через обычные ip route на интерфейсе |
| Добавление новой подсети | Правка conn, пересчёт Child SA | ip route add, без изменений в IPsec |
| Совместимость с OSPF/статической маршрутизацией | Плохая — маршруты внутри IPsec-политики | Хорошая — VTI виден как обычный интерфейс |
| Один туннель с двумя фиксированными сетями | Проще и нагляднее | Избыточно |
| Поведение при переподъёме | Может кратковременно ронять трафик подсети | Интерфейс остаётся, трафик ждёт восстановления SA |
| Диагностика | ipsec status, ip xfrm policy | ip link show vti0, ip route |
| Поддержка на стороне оборудования (Cisco, Mikrotik) | Универсально | Не всегда есть аналог VTI |
Для двух офисов с одной фиксированной подсетью на каждой стороне policy-based — разумный выбор: меньше движущихся частей, конфиг читается за секунду. Route-based имеет смысл, когда точек больше двух и нужна гибкая маршрутизация (hub-and-spoke, динамическая маршрутизация поверх туннелей, рост числа подсетей) — тогда VTI избавляет от пересборки Child SA при каждом изменении топологии. Если офисов больше трёх, стоит присмотреться и к mesh-решениям поверх WireGuard, которые сами управляют таблицей маршрутов — сравнение подходов есть в статье про Netmaker: mesh VPN на WireGuard.
Проверка и диагностика туннеля
Первым делом — статус IKE и Child SA:
ipsec status
ipsec statusall
statusall покажет и согласованные алгоритмы шифрования — полезно, когда обе стороны настроены разными людьми и подозревается рассинхрон в ike=/esp=. Что реально установлено в ядре:
ip xfrm state
ip xfrm policy
Для policy-based именно ip xfrm policy покажет селекторы — если тут пусто или не те подсети, дело в leftsubnet/rightsubnet, а не в IKE. Проверка связности:
ping -c 4 192.168.20.1
tcpdump -ni any esp
tcpdump с фильтром esp покажет, идут ли зашифрованные пакеты вообще — если нет ни в одну сторону, проблема в маршрутизации или firewall до IPsec, а не в самом туннеле. Отдельно проверьте, что на промежуточном firewall открыты UDP 500 и UDP 4500 (NAT-T) — без 4500 туннель может подняться, но развалится при первой смене NAT-маппинга.
Частые ошибки при настройке
- Асимметричные подсети.
leftsubnetна одной стороне не совпадает сrightsubnetна другой — IKE SA поднимается, а Child SA — нет или поднимается только для узкого пересечения подсетей. - NAT без явного NAT-T. strongSwan определяет NAT автоматически и переключается на UDP 4500, но за жёстким firewall этот порт нужно открыть отдельно от 500.
- MASQUERADE на трафике между офисами. Применённый по ошибке к транзитному трафику, а не только к исходящему в интернет, он подменяет внутренние адреса на IP шлюза — обратные пакеты не находят маршрут назад к конкретному хосту.
- Забытый forwarding в firewall.
ip_forward=1включает форвардинг на уровне ядра, но при политикеDROPпо умолчанию на цепочкеFORWARDвiptables/nftablesпакеты всё равно не пройдут — нужно явное разрешение для интерфейсаipsec0(policy-based) илиvti0(route-based). - Пересекающиеся подсети офисов. Если оба офиса сидят на одной адресации (частый случай для роутеров из коробки, например
192.168.1.0/24на обеих сторонах), туннель поднимется, но маршрутизация станет неоднозначной. Перед настройкой стоит свериться с диапазонами — похожие нюансы IPsec разбираются и в статье про L2TP/IPsec через Libreswan, где показан альтернативный демон для той же связки.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли использовать сертификаты вместо PSK?
Да, и для постоянного межофисного туннеля это надёжнее — вместо authby=secret указывается authby=pubkey, генерируется CA и сертификаты для обоих шлюзов через strongswan-pki. PSK проще для старта, но при компрометации ключа его придётся менять на обеих сторонах сразу — с сертификатами можно отозвать один, не трогая остальные.
Что будет, если у одного из офисов динамический публичный IP?
Сторона, принимающая подключение, ставит right=%any и ждёт входящего соединения. Стороне с динамическим адресом нужен DDNS, а rightid на принимающей стороне указывается как доменное имя, а не IP — идентификация пира тогда идёт по DDNS-имени независимо от текущего адреса.
Route-based обязательно требует VTI, или есть альтернативы?
В Linux для strongSwan VTI — стандартный путь, но есть и XFRM interfaces (ip link add xfrm0 type xfrm) — механизм новее, поддерживает несколько туннелей на разных if_id без конфликта по mark. Для двух офисов разница некритична, XFRM интереснее при большом числе туннелей на одном шлюзе.
Как понять, что туннель разваливается, а не просто не поднимается с нуля?
Смотрите journalctl -u strongswan -f в момент проблемы — циклические rekeying или DPD-таймауты говорят о нестабильности канала или рассинхроне dpddelay. Если IKE SA не устанавливается вообще, ищите в логе NO_PROPOSAL_CHOSEN — несовпадение ike=/esp= наборов.
Нужен ли отдельный VPS под сам туннель?
Не обязательно — strongSwan легковесен и живёт на том же сервере, что и другие сервисы, если тот не перегружен по CPU (шифрование ESP — единственная заметная нагрузка, и на современном железе для типичных офисных объёмов трафика она невелика). Отдельный узел оправдан при постоянном высоконагруженном трафике или когда нужно изолировать точку отказа.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →