OpenVPN-сервер на Linux с нуля: от PKI до клиентских профилей
Семёнов Евгений Сергеевич, директор АйТи Фреш. За 15+ лет я поднял больше сотни OpenVPN-инсталляций — от VPS для фрилансера до многофилиальных корпоративных узлов с отказоустойчивостью. И каждый раз вижу типовые ошибки: CA-ключ лежит на сервере, все клиенты используют один сертификат, TCP вместо UDP, дефолтный 1194, нет CRL. В статье — рабочий гайд, которым я пользуюсь у нас на практике: Ubuntu 22.04, easy-rsa, TLS-crypt, split-tunnel, нормальный мониторинг.
Когда OpenVPN действительно нужен
OpenVPN — один из старейших open-source VPN, которому уже больше 20 лет. На фоне современных WireGuard и VLESS у него есть минусы (однопоточность, ресурсоёмкая криптография), но и свои плюсы:
- Гибкая аутентификация: сертификаты, логин+пароль, TOTP, сертификаты AD.
- Поддержка split-DNS, push routes, push DNS — полноценный корпоративный VPN.
- Работа на TCP — полезно для проброса через прокси.
- Широкая поддержка клиентов: Windows, macOS, Linux, Android, iOS, роутеры, MikroTik.
- Развитая экосистема: pfSense, OPNsense, TrueNAS — везде встроен.
Я рекомендую OpenVPN когда нужна интеграция с существующим AD/NPS, split-tunneling, учёт трафика на пользователя, или когда клиент работает с оборудованием MikroTik/Fortinet, которое нативно поддерживает OpenVPN.
Подготовка сервера
Беру свежий VPS или виртуалку: Ubuntu 22.04 LTS, 2 vCPU с AES-NI, 2 ГБ RAM, 30 ГБ SSD, белый IP. На нашем стенде в дата-центре МТС типовая конфигурация для клиента до 100 сотрудников — виртуалка в кластере Proxmox на хостах Dell Xeon Platinum 8280 с AES-NI, которая спокойно держит 250 Мбит/с зашифрованного трафика на ядро.
# Первичная настройка
apt update && apt upgrade -y
apt install openvpn easy-rsa ufw fail2ban iptables-persistent -y
# Отключаем IPv6, если не используется
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
# Включаем форвардинг
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-openvpn.conf
sysctl -p /etc/sysctl.d/99-openvpn.conf
PKI через easy-rsa
easy-rsa — скрипты управления собственным CA. Я всегда поднимаю CA на отдельной машине (или в chroot-директории на сервере), чтобы приватный ключ CA никогда не попадал на рабочий OpenVPN:
mkdir -p /root/openvpn-ca
cp -r /usr/share/easy-rsa/* /root/openvpn-ca/
cd /root/openvpn-ca
# Инициализация PKI
./easyrsa init-pki
# Параметры CA в vars
cat > pki/vars << EOF
set_var EASYRSA_REQ_COUNTRY "RU"
set_var EASYRSA_REQ_PROVINCE "Moscow"
set_var EASYRSA_REQ_CITY "Moscow"
set_var EASYRSA_REQ_ORG "ITfresh"
set_var EASYRSA_REQ_EMAIL "admin@itfresh.ru"
set_var EASYRSA_REQ_OU "IT"
set_var EASYRSA_KEY_SIZE 2048
set_var EASYRSA_ALGO rsa
set_var EASYRSA_CA_EXPIRE 3650
set_var EASYRSA_CERT_EXPIRE 1095
EOF
# Создаём CA (запомните парольную фразу!)
./easyrsa build-ca
# Серверный сертификат без пароля
./easyrsa --batch build-server-full server nopass
# Параметры DH и TLS-crypt ключ
./easyrsa gen-dh
openvpn --genkey secret pki/ta.key
После создания ключи лежат в pki/. Для сервера нам нужны: ca.crt, issued/server.crt, private/server.key, dh.pem, ta.key.
Конфигурация сервера
Копируем ключи в /etc/openvpn/server/, создаём конфиг:
# /etc/openvpn/server/server.conf
port 1194
proto udp
dev tun
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/server.crt
key /etc/openvpn/server/server.key
dh /etc/openvpn/server/dh.pem
tls-crypt /etc/openvpn/server/ta.key
topology subnet
server 10.88.0.0 255.255.255.0
ifconfig-pool-persist /var/log/openvpn/ipp.txt
# Корпоративные сети, к которым открываем доступ
push "route 10.10.0.0 255.255.0.0"
push "route 192.168.100.0 255.255.255.0"
push "dhcp-option DNS 10.10.0.10"
push "dhcp-option DOMAIN corp.example.ru"
# Split-tunnel — не гнать весь трафик в VPN
# Уберите комментарий, если нужен full-tunnel:
# push "redirect-gateway def1 bypass-dhcp"
client-to-client
keepalive 10 120
cipher AES-256-GCM
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
auth SHA256
tls-version-min 1.2
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn/status.log 30
log-append /var/log/openvpn/server.log
verb 3
mute 20
# CRL для отзыва сертификатов
crl-verify /etc/openvpn/server/crl.pem
# Аутентификация по сертификату + логин/пароль через PAM
# (раскомментируйте, если нужна двухфакторная)
# plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so login
# verify-client-cert require
systemctl enable --now openvpn-server@server
systemctl status openvpn-server@server
ss -ulnp | grep 1194
Firewall и NAT
Без правильного firewall VPN работать не будет — клиенты получат IP, но в корпоративную сеть пакеты не пройдут:
# UFW allow
ufw allow 22/tcp
ufw allow 1194/udp
ufw default deny incoming
ufw default allow outgoing
# В /etc/ufw/before.rules в начало файла добавляем:
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.88.0.0/24 -o eth0 -j MASQUERADE
COMMIT
# В /etc/default/ufw меняем
DEFAULT_FORWARD_POLICY="ACCEPT"
ufw disable && ufw enable
# Проверяем
iptables -t nat -L POSTROUTING -n -v
Для корпоративных сетей, к которым открыт доступ по VPN, на маршрутизаторе корпоративной сети добавляем обратный маршрут: 10.88.0.0/24 via IP_OpenVPN_сервера.
Клиентские сертификаты и ovpn-профиль
Я никогда не раздаю один сертификат всем сотрудникам. Для каждого — свой:
# На машине с CA
cd /root/openvpn-ca
./easyrsa --batch build-client-full ivanov nopass
# Собираем inline-профиль
cat > /root/clients/ivanov.ovpn << 'EOF'
client
dev tun
proto udp
remote vpn.example.ru 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
verb 3
<ca>
EOF
cat pki/ca.crt >> /root/clients/ivanov.ovpn
echo "</ca>" >> /root/clients/ivanov.ovpn
echo "<cert>" >> /root/clients/ivanov.ovpn
openssl x509 -in pki/issued/ivanov.crt >> /root/clients/ivanov.ovpn
echo "</cert>" >> /root/clients/ivanov.ovpn
echo "<key>" >> /root/clients/ivanov.ovpn
cat pki/private/ivanov.key >> /root/clients/ivanov.ovpn
echo "</key>" >> /root/clients/ivanov.ovpn
echo "<tls-crypt>" >> /root/clients/ivanov.ovpn
cat pki/ta.key >> /root/clients/ivanov.ovpn
echo "</tls-crypt>" >> /root/clients/ivanov.ovpn
Файл ivanov.ovpn отправляется сотруднику (лучше через корпоративный чат или зашифрованный канал) и импортируется в OpenVPN Connect или Tunnelblick.
Отзыв сертификатов и CRL
Уволили сотрудника — обязательно отзываем его сертификат, иначе он продолжит ходить в корпоративную сеть:
cd /root/openvpn-ca
./easyrsa revoke ivanov
./easyrsa gen-crl
cp pki/crl.pem /etc/openvpn/server/
systemctl reload openvpn-server@server
CRL нужно обновлять регулярно даже без отзывов — срок его действия 180 дней по умолчанию. Я ставлю в cron ежемесячную регенерацию.
Таблица параметров для разных сценариев
| Сценарий | Протокол | Порт | Cipher | Compression |
|---|---|---|---|---|
| Домашние пользователи | UDP | 1194 | AES-256-GCM | Нет |
| Обход блокировок | TCP | 443 | CHACHA20-POLY1305 | Нет |
| Корпоративный филиал | UDP | 1194 | AES-128-GCM | Нет |
| Медленный канал (3G) | UDP | 1194 | CHACHA20-POLY1305 | LZ4-v2 |
Мини-кейс: сеть из 6 филиалов
В октябре 2025 года к нам на проект пришла сеть розничной торговли — 6 филиалов по Москве и Подмосковью, 85 рабочих мест. Задача — связать все филиалы с центральным офисом и дать удалённый доступ 15 руководителям. На центральном офисе стоит MikroTik CCR2004, в филиалах — MikroTik hEX S.
Решение:
- OpenVPN-сервер на Ubuntu 22.04 в дата-центре МТС, виртуалка на Dell Xeon Platinum 8280, 4 vCPU / 4 ГБ.
- Два инстанса OpenVPN:
server.confдля клиентских сертификатов руководителей иserver-sites.confдля филиальных MikroTik с client-config-dir и статическими IP. - Пакеты ipp.txt фиксированы, MikroTik получают IP по MAC-адресу сертификата.
- CRL регенерируется раз в месяц по cron, бэкап CA на флешке у владельца бизнеса.
- Мониторинг через Prometheus openvpn-exporter, дашборд в Grafana с активными сессиями и пропускной способностью.
Пропускная способность между филиалами — 180–220 Мбит/с, задержка до центра — 4–8 мс. Стоимость проекта: 165 000 руб. за разовую настройку + 12 000 руб./мес. за мониторинг и сопровождение. За 6 месяцев — один инцидент (выпал MikroTik в филиале после отключения электричества, перезалив сертификата за 15 минут).
Мониторинг и аудит
status.log на сервере обновляется раз в 30 секунд и показывает активные сессии с IP, временем коннекта, пройденным трафиком. Я парсю его через openvpn-exporter и отправляю в Prometheus:
# Docker-контейнер
docker run -d --name openvpn-exporter \
--network host \
-v /var/log/openvpn/status.log:/etc/openvpn_exporter/status.log:ro \
kumina/openvpn-exporter \
-openvpn.status_paths /etc/openvpn_exporter/status.log
В Grafana собираю дашборд: количество активных сессий, топ-10 пользователей по трафику, карта гео-распределения подключений, ошибки аутентификации. Для корпоративного аудита критически важно видеть, кто когда подключался и откуда.
Типичные ошибки при развёртывании
- CA-ключ на рабочем сервере. Выпустите все сертификаты и унесите CA-ключ в офлайн. На сервере он не нужен.
- Один сертификат на всех. Отозвать у одного — отозвать у всех. Для каждого пользователя — свой.
- compress lz4-v2 с современными клиентами. Сжатие — вектор атак VORACLE. Отключайте.
- Статическая ключевая аутентификация.
secretбез PKI — игрушка для дома, не для корпоратива. - Порт 1194 без tls-crypt. Без tls-crypt сторонний observer видит OpenVPN-хэндшейк и может делать fingerprinting. tls-crypt шифрует control channel.
- Отсутствие CRL. Уволенный сотрудник ходит по VPN ещё год до истечения сертификата.
Настроим OpenVPN для офиса за 2–3 дня
Разворачиваем корпоративный OpenVPN с PKI, клиентскими профилями под каждого сотрудника, интеграцией с AD, мониторингом в Grafana. Работаем с инфраструктурой от 10 до 500 пользователей, VPS или ваши серверы. 15+ лет опыта, выделенные SLA, круглосуточная поддержка.
Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш
FAQ — частые вопросы по OpenVPN
- UDP или TCP выбрать для OpenVPN?
- По умолчанию — UDP на 1194 или 443. UDP быстрее и стабильнее на потерях. TCP используйте только как fallback, когда UDP режется провайдером. Можно поднять два инстанса и раздать клиентам оба профиля.
- Сколько клиентов выдержит один OpenVPN?
- На VPS 2 vCPU/2 ГБ — до 100 одновременных сессий. На выделенном сервере с AES-NI — 500+. Узким местом обычно становится однопоточность OpenVPN — для больших инсталляций разворачивают несколько инстансов за балансировщиком.
- Нужен ли статический IP для OpenVPN-сервера?
- Предпочтительно да. Если IP меняется — клиентам приходится менять remote-адрес в конфиге. Либо используйте DynDNS-сервис с автоматическим обновлением A-записи.
- Безопасно ли хранить CA-ключ на сервере?
- Нет. CA-ключ должен лежать на отдельной машине или на внешнем носителе. На сервере хранятся только серверный сертификат и CRL. Компрометация OpenVPN-сервера не должна означать компрометацию CA.
- Как отозвать сертификат уволенного сотрудника?
- easy-rsa revoke client-name, затем gen-crl и скопировать crl.pem в директорию OpenVPN. Сервер проверяет CRL при каждом подключении — клиент с отозванным сертификатом получит отказ.