IKEv2 с сертификатами для нескольких пользователей на strongSwan
Когда VPN использует один человек, пароль в ipsec.secrets — нормальное решение. Но как только к серверу подключается команда из пяти-двадцати человек, схема начинает трещать: пароли расшаривают в чатах, никто не помнит, кому какой выдан, а при увольнении сотрудника приходится либо менять общий секрет для всех, либо надеяться, что человек сам удалит профиль с телефона. Сертификатная PKI решает это иначе — у каждого свой ключ, а отзыв доступа занимает одну команду и не трогает остальных.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Чем сертификатная схема отличается от EAP-паролей
В базовой установке IKEv2 на strongSwan клиенты авторизуются по логину и паролю через EAP-MSCHAPv2. Это быстро настраивается, но с ростом числа пользователей всплывают проблемы: пароль можно скопировать и передать третьему лицу без вашего ведома, а скомпрометированный пароль не отличить от легитимного логина — в логах будет просто «ivan подключился», без привязки к конкретному устройству.
При взаимной сертификатной аутентификации (rightauth=pubkey вместо eap-mschapv2) каждый клиент предъявляет собственный сертификат, подписанный вашим CA. Скопировать его сложнее, чем пароль — это файл .p12 с приватным ключом, который либо экспортируют целиком, либо не работает вовсе. Но главное преимущество в управляемости: у каждого сертификата есть серийный номер, срок действия и CN с именем владельца. Отозвать доступ одному человеку — значит внести его серийный номер в список отзыва (CRL), не трогая сертификаты остальных.
Минус тоже есть: сертификаты сложнее в эксплуатации, чем пароли. Нужно генерировать .p12-файл на каждого пользователя, безопасно передавать его (не почтой в открытом виде), объяснять, как установить сертификат на телефон. Для команды из 3-5 человек, где важна прослеживаемость доступа, оно того стоит. Для личного VPN одного человека — избыточно, там EAP-пароль или вовсе WireGuard быстрее.
Разворачиваем собственный CA
Сервер должен быть уже установлен — strongSwan, ядро с ip_forward=1, открытые порты 500/4500 UDP. Если этого ещё нет, сначала пройдите базовую установку из статьи выше, а сюда возвращайтесь на этапе сертификатов.
Структуру PKI держим отдельно от системных директорий, чтобы приватный ключ CA не путался с рабочими файлами:
mkdir -p ~/ca/{cacerts,certs,private,reqs}
chmod 700 ~/ca
cd ~/ca
Генерируем корневой ключ и самоподписанный сертификат CA сроком на 10 лет — CA живёт долго, его не переиздают при каждой ротации клиентских сертификатов:
ipsec pki --gen --type rsa --size 4096 --outform pem > private/ca-key.pem
chmod 600 private/ca-key.pem
ipsec pki --self --ca --lifetime 3650 \
--in private/ca-key.pem --type rsa \
--dn "CN=Company VPN Root CA" \
--outform pem > cacerts/ca-cert.pem
Сертификат сервера подписываем этим же CA — замените vpn.example.com на реальный адрес:
ipsec pki --gen --type rsa --size 4096 --outform pem > private/server-key.pem
ipsec pki --pub --in private/server-key.pem --type rsa | \
ipsec pki --issue --lifetime 1825 \
--cacert cacerts/ca-cert.pem \
--cakey private/ca-key.pem \
--dn "CN=vpn.example.com" \
--san "vpn.example.com" \
--flag serverAuth --flag ikeIntermediate \
--outform pem > certs/server-cert.pem
cp cacerts/ca-cert.pem /etc/ipsec.d/cacerts/
cp certs/server-cert.pem /etc/ipsec.d/certs/
cp private/server-key.pem /etc/ipsec.d/private/
chmod 600 /etc/ipsec.d/private/server-key.pem
Приватный ключ CA (private/ca-key.pem) — самый чувствительный файл во всей схеме. Если он утечёт, злоумышленник сможет подписывать сертификаты от вашего имени, и единственный выход — полная замена CA и переиздание всех клиентских сертификатов. Держите его под chmod 600 и не копируйте на рабочие машины; для организаций с повышенными требованиями к безопасности разумно генерировать его на отдельной изолированной машине, перенося сюда только подписанные сертификаты.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверВыпуск сертификата на каждого пользователя
Для нового сотрудника генерируем ключ и запрос, подписываем его от CA. CN должен быть уникальным — используйте email или логин, это станет идентификатором в логах и в CRL:
USER=ivan
DOMAIN=vpn.example.com
ipsec pki --gen --type rsa --size 4096 --outform pem > private/${USER}-key.pem
ipsec pki --pub --in private/${USER}-key.pem --type rsa | \
ipsec pki --issue --lifetime 730 \
--cacert cacerts/ca-cert.pem \
--cakey private/ca-key.pem \
--dn "CN=${USER}@${DOMAIN}" \
--san "${USER}@${DOMAIN}" \
--flag clientAuth \
--outform pem > certs/${USER}-cert.pem
Срок жизни клиентского сертификата (--lifetime 730 — два года) стоит держать заметно короче, чем у CA — это естественный механизм гигиены: даже если про отзыв забудут, доступ протухнет сам. Для команд с высокой текучкой разумно ставить 365 дней.
Пользователю нужен не набор отдельных файлов, а один .p12-контейнер с ключом, сертификатом и цепочкой до CA — так проще импортировать на телефон одним действием:
openssl pkcs12 -export \
-inkey private/${USER}-key.pem \
-in certs/${USER}-cert.pem \
-certfile cacerts/ca-cert.pem \
-name "${USER} VPN" \
-out ${USER}.p12
Утилита запросит пароль на экспорт — отдельный секрет, защищающий сам файл .p12 при передаче (пароля от VPN в этой схеме вообще нет, авторизация только по сертификату). Передавайте .p12 по защищённому каналу — мессенджер с самоуничтожением, Vault, личная встреча — но не почтой в открытом виде.
Настройка ipsec.conf под сертификатную аутентификацию
Ключевое отличие от EAP-схемы — rightauth=pubkey вместо eap-mschapv2, и клиент теперь предъявляет сертификат, а не идентификатор с паролем:
config setup
charondebug="ike 1, knl 1, cfg 0"
uniqueids=no
conn ikev2-cert
auto=add
compress=no
type=tunnel
keyexchange=ikev2
fragmentation=yes
rekey=no
left=%any
leftid=@vpn.example.com
leftcert=server-cert.pem
leftsendcert=always
leftsubnet=0.0.0.0/0
right=%any
rightid=%any
rightauth=pubkey
rightsourceip=10.10.20.0/24
rightdns=1.1.1.1,8.8.8.8
rightsendcert=never
ike=aes256-sha256-modp2048,aes256-sha1-modp2048!
esp=aes256-sha256,aes256-sha1!
rightid=%any означает, что сервер примет любой сертификат, подписанный доверенным CA (тем, что лежит в /etc/ipsec.d/cacerts/) — не нужно перечислять каждого пользователя в конфиге отдельной строкой, доступ регулируется фактом наличия действующего сертификата плюс CRL для отзыва.
В /etc/ipsec.secrets теперь нужна только строка с ключом сервера — пользовательские пароли из файла убираем совсем:
: RSA server-key.pem
Перезапустите службу:
ipsec restart
ipsec statusall
Если в сети уже есть подключение по паролям (ikev2-vpn из базовой установки), можно оставить оба conn-блока одновременно — strongSwan разберёт входящий IKE_AUTH по типу аутентификации клиента, и старая схема продолжит работать, пока вы поэтапно переводите пользователей на сертификаты.
CRL: список отзыва и его публикация
Отзыв в PKI работает не через удаление сертификата (у пользователя он и так остаётся на устройстве), а через список отозванных серийных номеров — CRL, который сервер проверяет при каждом новом подключении. Генерируем пустой CRL сразу при разворачивании CA, чтобы механизм был готов до того, как понадобится первый отзыв:
mkdir -p ~/ca/crl
cd ~/ca
ipsec pki --signcrl --lifetime 30 \
--cacert cacerts/ca-cert.pem \
--cakey private/ca-key.pem \
--outform pem > crl/ca.crl
cp crl/ca.crl /etc/ipsec.d/crls/
--lifetime 30 — срок действия самого CRL в днях, не сертификатов. По истечении strongSwan перестанет доверять устаревшему CRL, поэтому его нужно перевыпускать регулярно, даже если список отзыва не менялся. Практичнее всего — cron-задача:
cat > /etc/cron.d/ipsec-crl <<'EOF'
0 3 * * * root cd /root/ca && /usr/lib/ipsec/pki --signcrl --lifetime 30 --cacert cacerts/ca-cert.pem --cakey private/ca-key.pem --outform pem > crl/ca.crl && cp crl/ca.crl /etc/ipsec.d/crls/ && ipsec rereadcrls
EOF
Проверьте фактический путь до бинарника pki в вашей системе (which ipsec) — в некоторых сборках он вызывается напрямую как ipsec pki, без отдельного пути /usr/lib/ipsec/pki.
В ipsec.conf включите проверку CRL явно, если она не включена по умолчанию в вашей сборке strongSwan:
config setup
charondebug="ike 1, knl 1, cfg 0, cfg 2"
strictcrlpolicy=no
strictcrlpolicy=no — сознательный выбор для большинства сценариев: если CRL временно недоступен (например, ошибка cron-задачи), подключения не должны массово падать из-за отсутствия свежего списка. yes жёстче — без валидного CRL никто не подключится, — оправдано только там, где отзыв доступа критичнее доступности сервиса.
Отзыв доступа: пошагово
Когда сотрудник увольняется или теряет устройство, вам нужен серийный номер его сертификата. Посмотреть его можно прямо в файле сертификата:
openssl x509 -in ~/ca/certs/ivan-cert.pem -noout -serial
Добавьте сертификат в CRL, переиздав список с указанием отзываемого файла:
cd ~/ca
ipsec pki --signcrl --lifetime 30 \
--cacert cacerts/ca-cert.pem \
--cakey private/ca-key.pem \
--cert certs/ivan-cert.pem --reason superseded \
--outform pem > crl/ca.crl
cp crl/ca.crl /etc/ipsec.d/crls/
ipsec rereadcrls
Если у отозванного пользователя уже была активная сессия, rereadcrls не разорвёт её мгновенно — CRL проверяется при установлении нового соединения, а не постоянно во время работы туннеля. Чтобы завершить сессию сразу, найдите имя соединения и оборвите его вручную:
ipsec statusall | grep -i ivan
ipsec down ikev2-cert[<номер-сессии>]
Для срочных случаев (утеря устройства, подозрение на компрометацию) не полагайтесь только на CRL — сразу выполняйте оба шага: обновление CRL и принудительный разрыв активной сессии. Отдельно стоит вести реестр выданных сертификатов вне сервера (пользователь, CN, серийный номер, даты выдачи и истечения) — без него через год-два вы не вспомните, кому какой сертификат принадлежит.
Установка сертификата на устройства пользователей
.p12-файл содержит всё нужное для подключения — отдельно передавать ca-cert.pem не требуется, он уже упакован внутрь контейнера.
iOS / macOS. Отправьте .p12 на устройство, откройте файл — система запросит пароль экспорта и предложит установить профиль (на Mac — через Связку ключей). Далее в Настройки → VPN → Добавить конфигурацию → IKEv2 выберите установленный сертификат вместо ввода логина/пароля.
Windows. Импортируйте .p12 через certmgr.msc в «Личное» хранилище текущего пользователя (не в «Доверенные корневые», это ключ пользователя, а не CA). При создании VPN-подключения тип аутентификации — «Сертификат компьютера/пользователя».
Android. В приложении strongSwan (Google Play) — «Импортировать сертификат» с указанием .p12 и пароля, затем профиль с типом «IKEv2 Certificate».
| Платформа | Куда импортировать .p12 | Тип аутентификации в профиле |
|---|---|---|
| iOS / macOS | Профиль/Связка ключей | Сертификат (автоматически) |
| Windows 10/11 | certmgr.msc → Личное | Сертификат компьютера/пользователя |
| Android | Приложение strongSwan | IKEv2 Certificate |
| Linux | /etc/ipsec.d + swanctl | pubkey |
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли совмещать EAP-пароли и сертификаты на одном сервере?
Да, достаточно держать два разных conn-блока в ipsec.conf с разными именами и разными rightauth — удобно на переходный период, пока не все пользователи переведены на сертификаты.
Что если пользователь потерял .p12, но устройство не скомпрометировано?
Отзывать не обязательно — перевыпустите новый сертификат с тем же CN, старый можно оставить действующим до истечения срока или отозвать по желанию.
Нужно ли публиковать CRL на внешнем URL (CDP), как у публичных CA?
Нет, strongSwan проверяет CRL из локального файла /etc/ipsec.d/crls/, внешний Distribution Point не обязателен для одиночного сервера.
Что будет, если забыть продлить CRL при strictcrlpolicy=yes?
Все новые подключения начнут получать отказ, пока не появится свежий CRL — поэтому cron-задача на переиздание становится критичной инфраструктурой.
Команды выпуска и отзыва можно выполнить вручную, срочно, в обход cron?
Да, cron нужен только для регулярного переиздания CRL по сроку, а сам выпуск и отзыв — обычные команды ipsec pki, их можно запускать руками в любой момент.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →