Зачем OpenVPN
В 2002 OpenVPN дал то, чего не было: VPN на TLS поверх UDP/TCP без IPsec-сложности. С тех пор остаётся стандартом для:
- Corp VPN с per-user-сертификатами и LDAP/RADIUS-аутентификацией
- TCP-443 маскировка (выглядит как HTTPS, проходит через DPI фаерволы, где WireGuard и IPsec блокируются)
- Site-to-site с push routes, динамическим назначением IP клиентам
- L2-bridging через tap-режим (когда нужен один broadcast-domain через тоннель)
Минусы по сравнению с [[wireguard|WireGuard]]:
- Userspace, медленнее, больше CPU
- Конфиг сложнее, сертификаты надо генерить
- Один процесс на сервер (не один на peer как WG)
tun vs tap
tun (L3): VPN видит IP-пакеты ─── default, ~99% случаев
tap (L2): VPN видит Ethernet-frames ─── когда нужен один broadcast-domain
- tun, IP-роутинг между подсетями. Эффективнее (~1500 byte/frame).
- tap, bridge-в-bridge. Нужен для DHCP/Wake-on-LAN/non-IP протоколов. На клиентах слабая поддержка (Android/iOS не умеют tap).
Если не знаешь что выбрать, tun.
Сертификаты через easy-rsa
apt install easy-rsa openvpn
cd /usr/share/easy-rsa
./easyrsa init-pki
./easyrsa build-ca # пароль на CA-key
./easyrsa gen-dh # diffie-hellman params
./easyrsa build-server-full vpn.example.com nopass
./easyrsa build-client-full client1 nopass
# tls-crypt key для защиты handshake (нет в easy-rsa, генерируется openvpn'ом)
openvpn --genkey secret /etc/openvpn/server/tls-crypt.key
Файлы:
pki/ca.crt, публичный CApki/issued/<name>.crt, выданный сертификатpki/private/<name>.key, приватный ключpki/dh.pem, DH-paramstls-crypt.key, симметричный ключ для шифрования handshake
Серверный конфиг
/etc/openvpn/server/server.conf:
port 1194
proto udp
dev tun
topology subnet
ca ca.crt
cert server.crt
key server.key
dh dh.pem
tls-crypt tls-crypt.key
server 10.8.0.0 255.255.255.0 # пул для клиентов
ifconfig-pool-persist ipp.txt # запоминать IP за клиентами
push "redirect-gateway def1 bypass-dhcp" # full-tunnel
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 8.8.8.8"
keepalive 10 120 # ping каждые 10s, timeout 120s
cipher AES-256-GCM
auth SHA256
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn-status.log
log-append /var/log/openvpn.log
verb 3
explicit-exit-notify 1
Запуск:
systemctl enable --now openvpn-server@server
Не забыть включить ip-forwarding и [[cmd-iptables|MASQUERADE]] для push'нутого full-tunnel.
Клиентский конфиг
client.ovpn, один файл, в него inline-вкладываются сертификаты:
client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
verb 3
<ca>
-----BEGIN CERTIFICATE-----
... ca.crt ...
-----END CERTIFICATE-----
</ca>
<cert>
... client.crt ...
</cert>
<key>
... client.key ...
</key>
<tls-crypt>
... tls-crypt.key ...
</tls-crypt>
Один файл, единственное что нужно дать пользователю. Импортируется во все клиенты (Tunnelblick, OpenVPN Connect, NetworkManager).
tls-auth vs tls-crypt
Оба защищают handshake от DDoS и пассивного анализа:
- tls-auth (HMAC), пакет отбрасывается без HMAC-подписи. Старый.
- tls-crypt (шифрование), handshake шифруется этим ключом. Снаружи не видно даже что это OpenVPN. Лучше.
С 2.5, tls-crypt-v2 с per-client ключами, ещё надёжнее.
TCP fallback
proto tcp
port 443
Маскирует трафик под HTTPS. Минусы:
- TCP-over-TCP с потерями каскадно деградирует (двойной retransmit)
- Медленнее UDP
Используй только если UDP заблокирован. Можно поднять оба сервера на разных портах и клиент пробует UDP сначала.
Аутентификация
- PKI cert-only (default), клиент с приватным ключом доверенного CA = ок
- PKI + username/password,
auth-user-pass-verifyс PAM/RADIUS/script - 2FA через TOTP, через PAM-стек (
pam-google-authenticator) - client-cert-not-required, только пароль (не используй, ослабляет)
Per-user revocation:
./easyrsa revoke client1
./easyrsa gen-crl # генерим CRL
cp pki/crl.pem /etc/openvpn/server/
# в server.conf: crl-verify crl.pem
systemctl reload openvpn-server@server
OpenVPN vs WireGuard vs IPsec
| Признак | OpenVPN | wireguard | ipsec-ike |
|---|---|---|---|
| Транспорт | UDP/TCP | UDP | UDP/IP-ESP |
| PKI/сертификаты | да | нет | да |
| Per-user auth | да (PAM/RADIUS) | нет (только ключ) | да (EAP) |
| Где работает | userspace | в ядре | ядро + userspace IKE |
| Маскировка под HTTPS | да (TCP-443) | нет | нет |
| Push routes/DNS | да | нет (через AllowedIPs) | да (mode-config) |
| Production-зрелость | 20+ лет | 5+ лет | 25+ лет |
Когда что-то пошло не так
TLS Error: TLS key negotiation failed to occur within 60 secondsUDP/TCP до сервера не доходит.nc -u 1194илиnc -z 443.- Клиент подключается, нет интернета, забыли
redirect-gatewaypush или MASQUERADE на сервере. Также DNS push. - Handshake падает с
cipher mismatch, server и client разошлись по cipher. Раньше былоBF-CBCdeprecated. Используй AES-GCM на обоих. Permission deniedна /dev/net/tun в контейнере, нужен--cap-add=NET_ADMIN --device=/dev/net/tun.- MTU-проблемы (медленно загружаются страницы), путь имеет MTU < 1500.
tun-mtu 1400 mssfix 1360решает. - CRL устарел, у CRL есть expiry. Если клиенты не могут конектиться
после месяцев,
easyrsa gen-crlснова, перезагрузить openvpn. - Высокий CPU на сервере, много клиентов на одном UDP-сокете,
OpenVPN single-threaded. Решение: 2.6+ с
--server-mtили несколько процессов на разных портах + LB.