Что делаем в этой части
В первой статье мы разобрали саму технологию Site-to-Site VPN. Здесь поднимаем центральный узел: арендуем VPS, ставим strongSwan, включаем маршрутизацию между офисами, готовим firewall и даём расширенный обезличенный пример конфигурации для трёх офисов и Road-Warrior клиентов.
Требования к VPS
| Параметр | Минимум | Комментарий |
|---|---|---|
| ОС | Ubuntu 24.04 LTS или Debian 12 | Актуальные пакеты strongSwan и nftables/ufw |
| CPU/RAM | 1 vCPU / 2 GB RAM | Хватает для небольшого hub-spoke контура |
| Диск | 30 GB NVMe | Логи, backup конфигов, state админки |
| Сеть | белый IPv4 | Без публичного адреса сайт-то-сайт будет сложнее поддерживать |
| Порты | UDP 500/4500 | IKEv2 и NAT-T; Cloudflare proxy эти UDP-порты не проксирует |
Если домен находится в Cloudflare, DNS-запись для VPN лучше делать отдельной, например vpn.example.com,
и ставить режим DNS only. Оранжевое облако подходит для сайта, но не для IKEv2/IPsec.
Пример адресного плана
| Узел | Назначение | Пример |
|---|---|---|
| VPS hub | strongSwan server | 203.0.113.10, ID vpn.example.com |
| Hub services | служебная сеть за хабом | 10.0.0.0/24 |
| Office 1 | первый объект | gateway 192.168.10.1, LAN 192.168.10.0/24 |
| Office 2 | второй объект | gateway 192.168.11.1, LAN 192.168.11.0/24 |
| Office 3 | третий объект | gateway 192.168.12.1, LAN 192.168.12.0/24 |
| Road-Warrior | удалённые сотрудники | pool 10.20.30.0/24 |
Установка и базовая подготовка
apt update
apt upgrade -y
apt install -y curl ca-certificates ufw nftables tcpdump strongswan strongswan-swanctl strongswan-pki
hostnamectl set-hostname vpn-hubДальше включаем forwarding и отключаем строгий reverse path filter, иначе hub может поднять туннели, но резать межсетевой трафик.
cat >/etc/sysctl.d/99-vpn-forwarding.conf <<'EOF'
net.ipv4.ip_forward=1
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
EOF
sysctl --systemРекомендуемые шифры и порты
Для совместимости с роутерами часто используют AES-256 / SHA-256 / DH14. Если все устройства поддерживают
современные наборы, можно переходить на GCM/ECP. Главное правило: Phase 1 и Phase 2 должны совпадать на хабе и роутере.
| Уровень | Совместимый вариант | Более современный вариант |
|---|---|---|
| IKE / Phase 1 | aes256-sha256-modp2048 | aes256gcm16-prfsha384-ecp384 |
| ESP / Phase 2 | aes256-sha256-modp2048 | aes256gcm16-ecp384 |
| Порты | UDP 500 IKE, UDP 4500 NAT-T | |
Вариант A: полный swanctl.conf для 3 офисов
В hub-spoke схеме каждый офис видит hub-сеть и остальные офисы через центральный VPS. Для каждого peer задаём свой remote.id и свою LAN в remote_ts.
# /etc/swanctl/swanctl.conf
connections {
site-office1 {
version = 2
local_addrs = %any
remote_addrs = %any
proposals = aes256-sha256-modp2048
local { auth = psk; id = "vpn.example.com"; }
remote { auth = psk; id = "office1-router"; }
children {
net {
local_ts = 10.0.0.0/24,192.168.11.0/24,192.168.12.0/24
remote_ts = 192.168.10.0/24
esp_proposals = aes256-sha256-modp2048
start_action = trap
dpd_action = restart
}
}
}
site-office2 {
version = 2
local_addrs = %any
remote_addrs = %any
proposals = aes256-sha256-modp2048
local { auth = psk; id = "vpn.example.com"; }
remote { auth = psk; id = "office2-router"; }
children {
net {
local_ts = 10.0.0.0/24,192.168.10.0/24,192.168.12.0/24
remote_ts = 192.168.11.0/24
esp_proposals = aes256-sha256-modp2048
start_action = trap
dpd_action = restart
}
}
}
site-office3 {
version = 2
local_addrs = %any
remote_addrs = %any
proposals = aes256-sha256-modp2048
local { auth = psk; id = "vpn.example.com"; }
remote { auth = psk; id = "office3-router"; }
children {
net {
local_ts = 10.0.0.0/24,192.168.10.0/24,192.168.11.0/24
remote_ts = 192.168.12.0/24
esp_proposals = aes256-sha256-modp2048
start_action = trap
dpd_action = restart
}
}
}
}
secrets {
ike-office1 { id = "office1-router"; secret = "CHANGE_ME_OFFICE1_LONG_RANDOM_PSK"; }
ike-office2 { id = "office2-router"; secret = "CHANGE_ME_OFFICE2_LONG_RANDOM_PSK"; }
ike-office3 { id = "office3-router"; secret = "CHANGE_ME_OFFICE3_LONG_RANDOM_PSK"; }
}Шаблон добавления нового офиса
Для Office 4 добавляем новый peer, а сети Office 4 включаем в local_ts остальных офисов. Это важный момент: если selectors не совпадают, туннель может быть online, но доступ к новым сетям не появится.
site-office4 {
version = 2
local_addrs = %any
remote_addrs = %any
proposals = aes256-sha256-modp2048
local { auth = psk; id = "vpn.example.com"; }
remote { auth = psk; id = "office4-router"; }
children {
net {
local_ts = 10.0.0.0/24,192.168.10.0/24,192.168.11.0/24,192.168.12.0/24
remote_ts = 192.168.13.0/24
esp_proposals = aes256-sha256-modp2048
start_action = trap
dpd_action = restart
}
}
}Вариант B: ipsec.conf + ipsec.secrets
Если используется классический starter, та же логика описывается через ipsec.conf. Для некоторых версий удобнее делать отдельный conn на каждую пару traffic selectors.
# /etc/ipsec.conf
config setup
uniqueids=no
conn %default
keyexchange=ikev2
type=tunnel
authby=psk
left=%any
[email protected]
ike=aes256-sha256-modp2048!
esp=aes256-sha256-modp2048!
dpdaction=restart
dpddelay=30s
rekey=yes
auto=add
conn office1
right=%any
rightid=@office1-router
leftsubnet=10.0.0.0/24,192.168.11.0/24,192.168.12.0/24
rightsubnet=192.168.10.0/24
conn office2
right=%any
rightid=@office2-router
leftsubnet=10.0.0.0/24,192.168.10.0/24,192.168.12.0/24
rightsubnet=192.168.11.0/24
conn office3
right=%any
rightid=@office3-router
leftsubnet=10.0.0.0/24,192.168.10.0/24,192.168.11.0/24
rightsubnet=192.168.12.0/24# /etc/ipsec.secrets
@vpn.example.com @office1-router : PSK "CHANGE_ME_OFFICE1_LONG_RANDOM_PSK"
@vpn.example.com @office2-router : PSK "CHANGE_ME_OFFICE2_LONG_RANDOM_PSK"
@vpn.example.com @office3-router : PSK "CHANGE_ME_OFFICE3_LONG_RANDOM_PSK"Road-Warrior: удалённые сотрудники
Road-Warrior — это не офисная подсеть, а отдельный клиент: ноутбук, телефон или планшет. Для него обычно используют EAP-MSCHAPv2 с сертификатом сервера или полноценную X.509-аутентификацию.
connections {
rw-eap {
version = 2
local_addrs = %any
pools = rw-pool
proposals = aes256-sha256-modp2048
local {
auth = pubkey
certs = vpn-server-cert.pem
id = "vpn.example.com"
}
remote {
auth = eap-mschapv2
eap_id = %any
}
children {
net {
local_ts = 10.0.0.0/24,192.168.10.0/24,192.168.11.0/24,192.168.12.0/24
esp_proposals = aes256-sha256-modp2048
}
}
}
}
pools {
rw-pool { addrs = 10.20.30.0/24; }
}
secrets {
eap-user1 { id = "user1"; secret = "CHANGE_ME_USER1_LONG_RANDOM_SECRET"; }
}Для production лучше выпускать CA и server certificate заранее, хранить CA private key отдельно и планировать продление сертификатов до истечения срока.
Firewall на сервере: UFW и nftables
Открыть UDP-порты недостаточно. Для hub-spoke обязательно разрешить routed forwarding между VPN-подсетями.
ufw allow 22/tcp
ufw allow 500/udp
ufw allow 4500/udp
ufw route allow from 192.168.10.0/24 to 192.168.11.0/24
ufw route allow from 192.168.11.0/24 to 192.168.10.0/24
ufw route allow from 192.168.10.0/24 to 192.168.12.0/24
ufw route allow from 192.168.12.0/24 to 192.168.10.0/24
ufw --force enable# /etc/nftables.conf, фрагмент
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif lo accept
tcp dport 22 accept
udp dport {500, 4500} accept
}
chain forward {
type filter hook forward priority 0; policy drop;
ip saddr {192.168.10.0/24,192.168.11.0/24,192.168.12.0/24} ip daddr {192.168.10.0/24,192.168.11.0/24,192.168.12.0/24,10.0.0.0/24} accept
}
}Применение и проверка
swanctl --load-all
swanctl --list-conns
swanctl --list-sas
ip xfrm policy
ss -lunp | grep -E ':500|:4500'Отладка и типичные ошибки
| Симптом | Чаще всего причина | Что проверить |
|---|---|---|
AUTH_FAILED | не совпал PSK или ID | local id, remote id, PSK на роутере и хабе |
no matching peer config | роутер ожидает другой server ID | Remote ID на роутере должен быть vpn.example.com |
| туннель online, устройств не видно | FORWARD/firewall режет трафик | ufw route, nft list ruleset, gateway конечного устройства |
| поднялась только часть сетей | не совпали traffic selectors | local_ts/remote_ts и remote subnets на роутере |
| пакеты не доходят | Cloudflare proxy или закрыт UDP | DNS only, tcpdump -ni any udp port 500 or 4500 |
| после rekey трафик пропал | роутер не переинициировал CHILD SA | DPD, reconnect, swanctl --terminate --ike ... |
journalctl -u strongswan --no-pager -n 200
journalctl -u strongswan --follow
tcpdump -ni any udp port 500 or udp port 4500
iptables -L ufw-user-forward -n -v
nft list ruleset
ping -I 192.168.10.1 192.168.11.10Автоматический скрипт установки
Обезличенный пример ставит strongSwan, включает forwarding, открывает UDP 500/4500, создаёт swanctl-конфиг для Office 1/2/3 и добавляет route-правила между подсетями.
export VPN_DOMAIN="vpn.example.com"
export VPN_PUBLIC_IP="203.0.113.10"
export OFFICE1_ID="office1-router"
export OFFICE1_LAN="192.168.10.0/24"
export OFFICE1_PSK="CHANGE_ME_OFFICE1_LONG_RANDOM_PSK"
sudo -E bash install-strongswan-hub-example.shЧек-лист перед запуском
- VPS имеет белый IPv4, UDP 500/4500 открыты.
- DNS для VPN в режиме DNS only, если используется Cloudflare.
ip_forward=1,rp_filter=0.- В каждом офисе уникальные
Remote IDи PSK. - Traffic selectors зеркально совпадают с remote subnets на роутерах.
- Firewall разрешает routed forwarding между офисными сетями.
- Есть backup
swanctl.conf, secrets и сертификатов.