# OpenVPN - TLS-based VPN _Протоколы · LinuxLab Knowledge Base_ **TL;DR:** OpenVPN - userspace TLS-VPN на сертификатах X.509. Режимы: tun (L3, default) или tap (L2). Поддерживает UDP/TCP, push routes, per-user-аутентификацию, TCP-443 как маскировку. Жирнее [[wireguard|WG]]. ## Зачем 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 ```bash 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`, публичный CA - `pki/issued/.crt`, выданный сертификат - `pki/private/.key`, приватный ключ - `pki/dh.pem`, DH-params - `tls-crypt.key`, симметричный ключ для шифрования handshake ## Серверный конфиг `/etc/openvpn/server/server.conf`: ```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 ``` Запуск: ```bash systemctl enable --now openvpn-server@server ``` Не забыть включить [ip-forwarding](/kb/ip-forwarding.md) и [[cmd-iptables|MASQUERADE]] для push'нутого full-tunnel. ## Клиентский конфиг `client.ovpn`, один файл, в него inline-вкладываются сертификаты: ```conf 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 -----BEGIN CERTIFICATE----- ... ca.crt ... -----END CERTIFICATE----- ... client.crt ... ... client.key ... ... tls-crypt.key ... ``` Один файл, единственное что нужно дать пользователю. Импортируется во все клиенты (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 ```conf 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: ```bash ./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](/kb/wireguard.md) | [ipsec-ike](/kb/ipsec-ike.md) | |---------|---------|---------------|---------------| | Транспорт | 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 seconds`** UDP/TCP до сервера не доходит. `nc -u 1194` или `nc -z 443`. - **Клиент подключается, нет интернета**, забыли `redirect-gateway` push или MASQUERADE на сервере. Также DNS push. - **Handshake падает с `cipher mismatch`**, server и client разошлись по cipher. Раньше было `BF-CBC` deprecated. Используй 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. ## Команды ```bash openvpn --genkey secret tls-crypt.key ``` Сгенерировать tls-crypt ключ - защита handshake от DPI ```bash easyrsa build-client-full client1 nopass ``` Выпустить клиентский сертификат без паролевой защиты ключа ```bash openvpn --config client.ovpn ``` Запустить клиента в foreground - удобно при дебаге ```bash tail -f /var/log/openvpn.log ``` Логи сервера - первое место смотреть при проблемах коннекта ```bash ss -tunlp | grep openvpn ``` На каких портах сервер слушает - отладить firewall-mismatch ```bash openssl x509 -in pki/issued/client1.crt -noout -dates -subject ``` Проверить срок и subject клиентского сертификата ```bash easyrsa revoke client1 && easyrsa gen-crl ``` Отозвать клиента и обновить CRL - перенести в /etc/openvpn ## См. также - [WireGuard - современный UDP-VPN](/kb/wireguard.md) - [IPsec и IKEv2 - стандарт корпоративных VPN](/kb/ipsec-ike.md) - [TLS handshake](/kb/tls-handshake.md) - [UDP - User Datagram Protocol](/kb/udp-basics.md) - [TCP three-way handshake](/kb/tcp-handshake.md) - [TLS-сертификаты - X.509, цепочка доверия, Let's Encrypt](/kb/tls-certificates.md) - [RADIUS - аутентификация для сети, VPN, Wi-Fi](/kb/radius.md)