· 17 мин чтения

Site-to-site IPsec на Linux: как я соединил три офиса строительной компании за две недели

Этот материал — не учебник, а пересказ боевого проекта. Меня зовут Семёнов Евгений Сергеевич, я директор АйТи Фреш. В прошлом году к нам обратилась строительная компания: головной офис в Москве, филиалы в Санкт-Петербурге и Казани, 150 сотрудников, 1С и ERP в центральной серверной. Сотрудники филиалов работали через RDP поверх открытого интернета — медленно, небезопасно, с регулярными разрывами. Мы развернули IPsec site-to-site на strongSwan и закрыли задачу за две недели. Ниже — ровно те шаги, которые я проходил, с конфигурациями и ошибками.

Что было в начале

На первой встрече я увидел типичную картину: файлы проектной документации гоняются по почте, пароли к 1С у всех одинаковые, Wi-Fi в казанском офисе вообще без шифрования. У руководства болит голова не от VPN, а от того, что проектировщики из Казани жалуются на тормоза.

Аудит показал: три офиса живут отдельными мирами, между ними нет защищённой связности, в каждом стоит свой Windows Server с локальным доменом, нет общего файлообменника. Моё предложение — объединить всё в одну сеть через IPsec, вынести ERP в московский DMZ и открыть доступ только через туннель.

Архитектура, которую я нарисовал

Full-mesh на трёх узлах — это три туннеля: МСК—СПб, МСК—Казань, СПб—Казань. Не hub-and-spoke, потому что нагрузка на московский шлюз с мешем была бы слишком неравномерной, а full-mesh распределяет трафик.

ОфисWANLANЖелезо шлюза
Москва (HQ)2 провайдера, статика10.10.0.0/24 + 10.11.0.0/24 VLAN серверовDell PowerEdge R350, Debian 12
СПбStatic IP10.20.0.0/24Intel NUC i5, Debian 12
КазаньЗа NAT провайдера, dynamic10.30.0.0/24Intel NUC i5, Debian 12

Бюджет на железо для двух филиалов — 72 000 рублей. В Москве шлюзом выступила уже стоявшая виртуалка на ProxMox — дополнительных затрат не было.

Создание PKI

Отдельная машина — наш технический ноутбук с Debian — служит корневым CA. Никогда не ставлю CA на тот же шлюз, который сам шифрует трафик.

cd /etc/ipsec.d
# Корневой CA на 10 лет
ipsec pki --gen --type rsa --size 4096 --outform pem > private/ca-key.pem
ipsec pki --self --ca --lifetime 3650 \
    --in private/ca-key.pem \
    --dn "C=RU, O=Stroy, CN=Stroy VPN CA" \
    --outform pem > cacerts/ca-cert.pem

# Шаблон подписи для шлюза Москвы
ipsec pki --gen --type rsa --size 4096 --outform pem > private/gw-msk-key.pem
ipsec pki --pub --in private/gw-msk-key.pem | \
  ipsec pki --issue --lifetime 1825 \
    --cacert cacerts/ca-cert.pem --cakey private/ca-key.pem \
    --dn "C=RU, O=Stroy, CN=gw-msk.stroy.local" \
    --san gw-msk.stroy.local --san 203.0.113.10 \
    --flag serverAuth --flag ikeIntermediate \
    --outform pem > certs/gw-msk-cert.pem

Аналогично подписал сертификаты gw-spb и gw-kzn. Затем скопировал ключи на соответствующие шлюзы через SCP на тот момент, когда был физически рядом с каждой машиной. Удалённо через незашифрованный канал я приватные ключи никогда не передаю.

Базовая настройка шлюзов

Для экономии времени начал с PSK-варианта — проверить связность до перехода на сертификаты. Конфигурация Москвы:

# /etc/ipsec.conf — GW-MSK, первый этап с PSK
config setup
    charondebug="ike 2, knl 2, cfg 2"
    uniqueids=yes

conn %default
    keyexchange=ikev2
    ikelifetime=24h
    lifetime=8h
    dpdaction=restart
    dpddelay=30s
    dpdtimeout=150s
    keyingtries=%forever
    ike=aes256-sha256-modp2048!
    esp=aes256gcm16-sha256!

conn msk-spb
    auto=start
    authby=secret
    left=203.0.113.10
    leftsubnet=10.10.0.0/24,10.11.0.0/24
    leftid=@gw-msk.stroy.local
    right=198.51.100.5
    rightsubnet=10.20.0.0/24
    rightid=@gw-spb.stroy.local

conn msk-kzn
    auto=start
    authby=secret
    left=203.0.113.10
    leftsubnet=10.10.0.0/24,10.11.0.0/24
    leftid=@gw-msk.stroy.local
    right=%any
    rightid=@gw-kzn.stroy.local
    rightsubnet=10.30.0.0/24

На стороне СПб и Казани — зеркальные файлы. PSK-секрет — длинная строка из /dev/urandom, 40 символов. Для тестов этого хватает, для продакшена — нет.

Переход на сертификаты

Когда все три туннеля поднялись и прошёл ping — начал менять на pubkey-аутентификацию. Фрагмент конфига Москвы после перехода:

conn msk-spb
    auto=start
    authby=pubkey
    ike=aes256gcm16-sha384-ecp384!
    esp=aes256gcm16-sha384!

    left=203.0.113.10
    leftsubnet=10.10.0.0/24,10.11.0.0/24
    leftid=@gw-msk.stroy.local
    leftcert=gw-msk-cert.pem
    leftsendcert=always

    right=198.51.100.5
    rightsubnet=10.20.0.0/24
    rightid=@gw-spb.stroy.local
    rightca="C=RU, O=Stroy, CN=Stroy VPN CA"

Файл ipsec.secrets — одна строка: : RSA gw-msk-key.pem. Права 600, владелец root. И никаких PSK-строк больше не осталось.

Казанский офис за NAT

Самая весёлая история — казанский офис. Провайдер выдавал серый IP через карьерный NAT, никаких статических адресов за деньги не продавал. Пришлось играть от имени клиента.

# /etc/ipsec.conf на gw-kzn
conn to-msk
    auto=start
    authby=pubkey
    left=%defaultroute
    leftsubnet=10.30.0.0/24
    leftid=@gw-kzn.stroy.local
    leftcert=gw-kzn-cert.pem
    leftfirewall=yes

    right=203.0.113.10
    rightsubnet=10.10.0.0/24,10.11.0.0/24,10.20.0.0/24
    rightid=@gw-msk.stroy.local

    forceencaps=yes
    ike=aes256gcm16-sha384-ecp384!
    esp=aes256gcm16-sha384!

forceencaps = yes — критичная строка. Без неё провайдерский NAT ломал ESP. С ней весь трафик ушёл в UDP 4500 и прошёл как миленький.

Маршрутизация и DHCP

Внутри каждого офиса на маршрутизаторах добавил статические маршруты на удалённые подсети через VPN-шлюз. Это простая часть. Но клиенту хотелось, чтобы маршруты раздавались по DHCP автоматически — на случай если появится новый филиал и придётся переписывать сотни ПК. Я настроил DHCP Option 121 (classless static routes):

# /etc/dhcp/dhcpd.conf на маршрутизаторе МСК
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
subnet 10.10.0.0 netmask 255.255.255.0 {
    range 10.10.0.100 10.10.0.200;
    option routers 10.10.0.1;
    option rfc3442-classless-static-routes
        24, 10, 20, 0, 10, 10, 0, 1,
        24, 10, 30, 0, 10, 10, 0, 1;
}

Windows и Linux-клиенты оба подхватывают эту опцию, и при каждом обновлении лизы маршруты актуализируются. macOS имеет свои причуды — но в офисе стройки яблок почти не было.

Failover через второго провайдера

Московский офис был самой важной точкой, туда сходится весь трафик. Под неё мы добавили резервный канал от второго провайдера. Две конфигурации — primary и backup. Скрипт переключает трафик, если основной не отвечает 60 секунд:

#!/bin/bash
# /usr/local/bin/vpn-failover.sh
REMOTE=10.20.0.1
PRIMARY=msk-spb-primary
BACKUP=msk-spb-backup

if ! ping -c3 -W2 "$REMOTE" >/dev/null 2>&1; then
    if ! ipsec status | grep -q "$BACKUP.*ESTABLISHED"; then
        ipsec down "$PRIMARY"
        sleep 2
        ipsec up "$BACKUP"
        logger -t vpn "failover: switched to backup channel"
    fi
else
    if ipsec status | grep -q "$BACKUP.*ESTABLISHED"; then
        ipsec down "$BACKUP"
        sleep 2
        ipsec up "$PRIMARY"
        logger -t vpn "recovery: switched back to primary"
    fi
fi

Проверка — раз в 60 секунд через systemd timer. За год работы два реальных переключения: один раз провайдер делал обслуживание узла, второй — физически порвали магистраль на стройке возле офиса.

Мониторинг и уведомления

Подключил Zabbix-агент к каждому шлюзу, написал простой item, который парсит ipsec statusall и отдаёт количество ESTABLISHED-SA. При падении любого SA — алерт в Telegram техническому директору клиента и мне.

# UserParameter для Zabbix
UserParameter=vpn.established,ipsec status | grep -c ESTABLISHED

# Триггер: если меньше 3 — алерт
{gw-msk:vpn.established.last()}<3

За 8 месяцев до истечения проекта было 11 алертов, 9 разобрались сами за 3–10 минут (DPD подтянул туннель), два потребовали нашего вмешательства — оба раза виноваты провайдеры.

Что получил клиент в итоге

Смета проекта: железо двух филиалов 72 000 руб., работы и документация 195 000 руб., итого 267 000 руб. По сравнению с коммерческими VPN-шлюзами вроде Fortinet экономия для клиента составила около 380 000 руб. на железе и примерно 60 000 руб./год на лицензиях.

Типовые ошибки, с которыми я столкнулся

Соберу VPN-сеть для ваших филиалов

Проектирую, строю, документирую. Для объединения двух-пяти офисов срок обычно 7–14 рабочих дней. Железо подбираем под бюджет — от Intel NUC до Dell PowerEdge. После сдачи — обучение вашего админа и 30 дней бесплатной поддержки.

Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш

FAQ — частые вопросы по site-to-site IPsec

Сколько времени у меня заняло объединение трёх офисов?
Чистое внедрение — 8 рабочих дней: три дня PKI и сбор шлюзов, два дня установка в Москве, по дню на СПб и Казань, и финальный день на failover и мониторинг. Весь проект с документацией и обучением админа клиента уместился в две недели.
Почему я не выбрал WireGuard для этой задачи?
Потому что в казанском офисе стоял Cisco ISR, который отдавать и менять клиент не хотел. Cisco умеет IKEv2 IPsec, но не знает WireGuard. strongSwan идеально вставал и туда, и на Debian, и на Mikrotik.
Что делать, если филиал сидит за NAT провайдера?
Ставим на филиале left=%defaultroute и forceencaps=yes. На NAT-маршрутизаторе пробрасываем UDP 500, UDP 4500 и протокол ESP (IP 50) — но если есть forceencaps, ESP не нужен.
PSK или сертификаты?
Сертификаты X.509. Всегда. PSK для site-to-site — это дыра, которую рано или поздно найдут. У каждой стороны должен быть свой приватный ключ, это азы.
Выдержит ли 1С через такой VPN?
Выдержит, и неплохо. В нашем проекте скорость работы 1С через VPN выросла в 3–4 раза по сравнению с предыдущим RDP-через-интернет. Главное — обеспечить минимум 10–20 Мбит/с симметричного канала и следить за MTU.

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.