OpenVPN
OpenVPN - это клиент-серверная VPN-платформа на базе SSL с открытым исходным кодом, которая позволяет настроить VPN-сеть. Виртуальная частная сеть (VPN) может рассматриваться как безопасный туннель, который соединяет два узла через небезопасное соединение. OpenVPN использует библиотеку OpenSSL, поэтому он может использовать все возможности, которые присутствуют в этой библиотеке, включая широкий список строгих стандартов шифрования. Фактически самым высоким уровенем шифрования, возможным с OpenVPN, является шифрование 256-бит. Кроме того, OpenVPN может использовать UDP или TCP для передачи данных - при этом UDP является более предпочтительным в плане скорости передачи данных. Также OpenVPN использует свою собственную схему безопасности, основанную на технологиях SSL и TLS, не имея ничего общего с IPsec, L2TP или чем-то подобным.
Кроме того, это одно из немногих решений, которое отлично работает не только на третьем (route), но и на втором (bridge) уровне сетевой модели. Также несомненным плюсом является тот факт, что для работы OpenVPN нужен всего один порт, причем можно использовать тот же порт 443, который использует SSL. Еще одна замечательная особенность заключается в том, что обе конечные точки туннеля могут иметь динамические IP-адреса, что означает, что для работы не нужен статический IP-адрес. Кроме того, по принципу реализации протокол OpenVPN может использовать прокси и без проблем работать через NAT.
Большинство конфигураций для связи клиентов с сервером, а также между серверами, предполагает использование связки приватных или приватно/публичных ключей для обеспечения безопасности внутреннего трафика. Для корпоративных сетей в режиме MultiPoint-To-SinglePoint обычно используется свой центр сертификации PKI, который легко строится либо при помощи easy-rsa, либо на основе XCA. Для межсервенной коммуникации типа Point-to-point, в основном используется конфигурация с общим ключом.
Механизмы аутентификации
-
Сертификатная аутентификация. Создаётся свой центр сертификации, который выпускает пользовательские сертификаты. С помощью центра сертификации обеспечивается контроль за подключением пользователей к OpenVPN серверу. При окончании времени действия сертификата или его отзыве, доступ пользователя блокируется. Приватные ключи с установленым на них паролем, выпускаемые совместно с сертификатом обеспечивают безопасность от несанкционированного подключения к внутренним ресурсам.
-
Приватные point-to-point ключи. С точки зрения подключения к ресурсам компании только одного пользователя/сервера, используется схема с приватными ключами. На одном из хостов генерируется ключ, который является общим для сервера и клиента.
Сертификаты для OpenVPN
OpenVPN серверу для работы нужны сертификаты, их можно создавать разными способами, но класическим и бесплатным является использование Easy-RSA
В первую очередь необходимо создать локальный центр сертификации (CA) инфраструктуры открытых ключей (PKI - public key infrastructure). PKI состоит из:
-
Создать закрытый ключ центра сертификации - основы всей инфраструктуры PKI
pki/private/ca.key(корневой ключ) и его открытый сертификатpki/ca.crt(корневой сертификат).Первый ключ секретный, его нужно оставить на сервере и никому не отдавать. Второй - открытый, его мы будем вместе с пользовательскими сертификатами передавать клиентам.
- Создать файл параметров Диффи-Хелмана
Будет помещен в директорию pki/dh.pem
-
Создать ключ и сертификат для сервера:
- Закрытый ключ сервера
pki/private/server.key. Закрытый ключ является секретным доступ к нему также должен быть ограничен. - При создании ключа, также будет создан файл запроса
/pki/reqs/server.req, который нужно будет подписать на следующем шаге. - Сертификат для сервера
pki/issued/server.crt
- Закрытый ключ сервера
# Сначала нужно содать запрос на сертификат
# server - имя сервера
./easyrsa gen-req server nopass
# Затем подписать запрос на получение сертификата у нашего CA
./easyrsa sign-req server server
# Сертификат будет помещен в директорию pki/issued/server.crt
- Создать ключ для шифрования TLS control channel
- Скопировать все необходимые для работы сервера ключи и сертификаты.
cp pki/ca.crt /etc/openvpn/server/ca.crt
cp pki/dh.pem /etc/openvpn/server/dh.pem
cp pki/issued/server.crt /etc/openvpn/server/server.crt
cp pki/private/server.key /etc/openvpn/server/server.key
-
Создать ключи и сертификаты для клиентов
- Сначала создается запрос на сертификат
- Затем, на основании запроса, сертификат выпускается
# Сначала нужно содать запрос на сертификат
./easyrsa gen-req vpn_user_1 nopass
# Затем подписать запрос на получение сертификата у нашего CA
./easyrsa sign-req client vpn_user_1
# Сертификат будет помещен в директорию pki/issued/server.crt
# Команды gen-req и sign-req можно объединить в одну с помощью build-client-full
./easyrsa build-client-full vpn_user_2 nopass
В результате получаем следующие файлы:
- сертификат клиента -
/etc/openvpn/keys/easy-rsa/pki/issued/vpn_user_1.crt - ключ клиента -
/etc/openvpn/keys/easy-rsa/pki/private/vpn_user_1.key
Итого, файлы необходимые для успешного подключения клиента:
- Корневой сертификат CA:
/etc/openvpn/server/ca.crt - Сертификат клиента:
/etc/openvpn/keys/easy-rsa/pki/issued/vpn_user_1.crt - Ключ клиента:
/etc/openvpn/keys/easy-rsa/pki/private/vpn_user_1.key - TLS ключ для шифрования соединения:
/etc/openvpn/server/tc.key
Отзыв сертификатов
На практике случаются ситуации, когда выданные пользователям сертификаты требуется отозвать. Для этого необходимо выполнить следующие действия:
- Создать список отозванных сертификатов.
- В конфиг openvpn необходимо добавить директиву
crl-verify
- revoke. Теперь любой выданный клиентский сертификат может быть отозван командой
revoke.
./easyrsa revoke vpn_user_1
# после отзыва следует повторно опубликовать список отозванных сертификатов:
./easyrsa gen-crl
> Проверка сертификата происходит при подключении клиента.
# Посмотреть список сертификатов можно с помощью команды:
cat pki/index.txt
# Действующие сертификаты имеют статус V в начале строки, отозванные - R.
# Для отозванных клиентов рекомендуется удалять выданные сертификаты и настройки
server config
Файл конфигурации сервера OpenVPN обычно хранится в директории: /etc/openvpn/server/server.conf
# Директива local указывает, к какому IP-адресу привязать сокет сервера.
# Актуально, если openvpn спрятан за proxy. OpenVPN по умолчанию слушает 0.0.0.0
;local 127.0.0.1
# Директива port указывает на каком порту слушает openvpn сервер, по умолчанию, используется порт 1194
port 1194
# Директива proto отвечает за протокол, на котором слушает сервер TCP/UDP
# Один инстанс севера может слушать только 1 протокол/порт!
;proto tcp
proto udp
# Директива dev определяет тип виртуального сетевого интерфейса, который создаётся для VPN.
# "dev tun" создает маршрутизируемый (Layer 3) интерфейс tun0. Использует маршрутизацию, Не передаёт broadcast
# "dev tap" создает мостовой (Layer 2) интерфейс tap0. Клиенты могут быть "как в одной локалке"
;dev tap
dev tun
ca, cert, key, dh
Директивы отвечающие за TLS-аутентификацию и шифрование. то, какие сертификаты используются и где они хранятся
-
ca. CA — это главный удостоверяющий центр, корневой сертификат центра сертификации, проверяет подлинность клиентов. Если клиент не подписан этим CA — сервер его не пустит.
В директиве
caуказывается путь по которому храниться корневой сертификат.
-
cert - сертификат сервера: подтверждает клиенту, что он подключается к правильному серверу, содержит публичный ключ сервера, при подключении клиент проверяет туда ли он подключается.
В директиве
certуказывается путь по которому храниться сертификат сервера.
-
key - приватный ключ сервера: используется для TLS-рукопожатия. доказывает, что сервер владеет сертификатом, должен храниться строго на сервере, права доступа обычно 600.
В директиве
keyуказывается путь по которому храниться приватный ключ сервера.
-
dh - параметры Diffie-Hellman, используются для: генерации временного сеансового ключа, обеспечения Perfect Forward Secrecy (PFS)
В директиве
dhуказывается путь по которому хранитьсяdh.pem.
topology, server, push, route, etc..
Настройки виртуальной сети и подключаемых к ней клиентов.
- topology - определяет способ выдачи IP клиентам.
- server - включает серверный режим и автоматически настраивает несколько параметров сети VPN. Фактически создать VPN-подсеть
10.8.0.0/24и выдавать клиентам адреса из неё.
- server-bridge - используется только с dev tap. OpenVPN работает как
bridge, клиенты получают IP из LAN, VPN — как будто физически в одной сети.
- ifconfig-pool-persist - сохраняет соответствие:
client_name → IP, использую для этого текстовый файл. Чтобы клиент при повторном подключении получал тот же IP.
- push - используется на сервере, чтобы передать настройки клиенту при подключении, сервер "пушит" конфигурацию клиенту, и клиент автоматически её применяет, как локальные настройки.
push "redirect-gateway def1" #клиент меняет свой маршрут по умолчанию
push "dhcp-option DNS 1.1.1.1" #Клиент начинает использовать эти DNS.
push "dhcp-option DNS 9.9.9.9" #без них клиент использует локальные настройки DNS
;push "route 192.168.10.0 255.255.255.0" #Маршрут к внутренней сети
# Так же необходимо с помощью route добавить маршрут на самом сервере
;route 192.168.10.0 255.255.255.0
- Чтобы пустить весь интернет трафик клиента через vpn-сервер, нужно применить следующую директиву:
```openvpn title="push "redirect-gateway def1 bypass-dhcp"" push "redirect-gateway def1 bypass-dhcp"
- **client-config-dir** позволяет передавать клиентам индивидуальные маршруты, которые хранятся в соответствующих файлах. Имена файлов соответствуют именам клиентов.
```bash title="Использование директивы client-config-dir"
# Для того чтобы директива client-config-dir работала
# необходимо создать соответствующие файлы с настройками
cat "iroute 192.168.150.0 255.255.255.0" > /etc/openvpn/ccd/client_ivanov
# где client_ivanov - имя соответствующего сертификата клиента
- client-to-client позволяет клиентам видеть друг друга, когда они подключены к виртуальной сети vpn-сервера.
# Директива сообщающая, что сервер работает в режиме TLS-сервера.
# включает: проверку клиентских сертификатов, полноценный TLS handshake, mTLS (взаимную аутентификацию)
tls-server
# Директива определяющая минимальный уровень TLS
# Разрешает только TLS 1.3, дает: встроенный PFS, защита от downgrade-атак,
# современные AEAD-алгоритмы, меньше криптографического “мусора”
# Старые клиенты (OpenVPN < 2.5) подключиться не смогут.
tls-version-min 1.3
# Директивы для доп безопасности с помощью TLS, защищает от флуда и ddos
# tls-auth Добавляет HMAC-подпись к TLS handshake. на сервере устанавливается 0, на клиенте 1
;tls-auth /path/to/key/ta.key 0
# есть более современная директива
# В современных конфигурациях лучше использовать директиву tls-crypt
# не только аутентифицирует , но и шифрует весь TLS control channel
# скрывает сертификат сервера от анализа, защищает от DoS/DDoS, делая трафик невидимым для стороннего наблюдателя.
tls-crypt /path/to/key/ta.key
verify-client-cert
Директива verify-client-cert проверяет наличие клиентского сертификата. Возможные опции:
-
require. Сервер обязательно требует клиентский сертификат, и проверяет подпись CA, проверяется цепочка доверия, проверяется CRL; если всё OK → подключение разрешается. Если сертификата нет - подключение будет отклонено.
require- самый безопасный вариант.
- optional. Клиент может подключиться без сертификата. Используется если есть:
auth-user-pass,RADIUS,LDAP,MFA
-
none. Сервер не требует сертификат вообще. Используется только если:
username/passwordилиOAuth/SSO.none- самый опасный вариант, не рекомендуется к использованию.
cipher, data-ciphers
- Директива cipher определяет симметричный алгоритм шифрования.
- data-ciphers - более современные директивы . Определяет шифры для передачи данных (data channel).
data-ciphers AES-256-GCM:AES-128-GCM
data-ciphers-fallback AES-256-GCM # Используется, если клиент старый и не поддерживает negotiation.
auth SHA256 # нужна для совместимости и fallback-сценариев.
ecdh-curve, tls-groups
# Следующая директива определяет кривую для ECDHE (обмен ключами).
# В TLS 1.3 ключи создаются через ECDHE автоматически, эта директива уточняет кривую.
# задаёт алгоритмы, с помощью которых клиент и сервер создают общий секретный ключ при TLS-handshake.
;ecdh-curve secp384r1
tls-groups X25519:secp384r1 #современный вариант
# Директива ограничивающая слабые криптоалгоритмы в сертификатах.
tls-cert-profile preferred #оптимальное значение
# Если TLS handshake не завершился за 5 секунд — соединение разрывается.
tls-timeout 5
# Принудительная смена ключей каждые 3600 секунд (1 час). уменьшает криптографический риск
reneg-sec 3600
keepalive
Директива keepalive проверяет жив ли клиент, отправляя ему: каждые 10 сек пинг, если в течении 120 сек ответа нет - соединение перезапускается. Нужно для обнаружения “мертвых” клиентов.
user, group
Директивы, позволяющие ограничить привелегии демона openvpn. Сервер стартует от root, создает тунель tun, затем отбрасывает привелегии. Рекомендуется вклячать эти директивы для повышения безопасности.
persist-key, persist-tun
Директивы которые позволяют использовать имеющиеся ключи при перезапуске тонеля
logs
- status - записывает текущее состояние сервера в указанный файл.
По умолчанию, логи пишутся в syslog.
- log - записывае логи в указанный лог-файл, перезаписывает лог при каждом рестарте сервера.
- log-append - записывае логи в указанный лог-файл. Сохраняет старый лог, дописывая его
- verb - задает уровень логирования.
- mute. Директива тишины в логах. Полезно при флуде ошибок. Повторяющиеся сообщения будут выводиться не более 20 раз подряд.
- explicit-exit-notify. Директива уведомления сервера об отключении клиента. Используется в UDP-режиме.
sndbuf, rcvbuf
Директивы управляющие размером сетевых буферов сокета для отправки и приёма данных.
- Send buffer — размер буфера отправки. В современных дистрибутивах linux рекомендуется использовать автонастройку ядра ОС.
- Receive buffer — буфер приёма. В современных дистрибутивах linux рекомендуется использовать автонастройку ядра ОС.
sndbuf 0 #использовать автонастройку ядра ОС
rcvbuf 0 #использовать автоматический размер из ядра Linux
# Директивы push отправляют размеры буферов клиентам. Без push клиент может использовать другие значения.
push "sndbuf 0"
push "rcvbuf 0"
Пример UDP-конфига
Пример конфигурации OpenVPN сервера, работающего по UDP
# server
port 1195
proto udp
dev tun
# certs
ca /etc/openvpn/keys/server/ca.crt
cert /etc/openvpn/keys/server/server.crt
key /etc/openvpn/keys/server/server.key
dh /etc/openvpn/keys/server/dh2048.pem
verify-client-cert require
# crypto
tls-server
tls-version-min 1.3
tls-crypt /etc/openvpn/keys/server/ta.key 0 # This file is secret
data-ciphers AES-256-GCM:AES-128-GCM
data-ciphers-fallback AES-256-GCM
auth SHA256
tls-groups X25519:secp384r1
tls-cert-profile preferred
tls-timeout 5
reneg-sec 3600
# network
topology subnet
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 8.8.8.8"
ifconfig-pool-persist /var/log/openvpn/ipp-udp.txt
# other
sndbuf 0
rcvbuf 0
push "sndbuf 0"
push "rcvbuf 0"
tun-mtu 1500
mssfix 1400
persist-key
persist-tun
keepalive 10 60
max-clients 10
user nobody
group nogroup
# Компрессия запрещена (VORACLE safe)
compress stub-v2
allow-compression no
;log-append /var/log/openvpn/openvpn.log
status /var/log/openvpn/status-udp.log
verb 3
mute 10
explicit-exit-notify 1
crl-verify /etc/easy-rsa/pki/crl.pem
Пример TCP-конфига
Пример конфигурации OpenVPN сервера, который работает по протоколу TCP, при этом спрятан за прокси, например nginx. Требует доп. настройки nginx
# server
local 127.0.0.1
port 1194
proto tcp-server
dev tun
# certs
ca /etc/openvpn/keys/server/ca.crt
cert /etc/openvpn/keys/server/server.crt
key /etc/openvpn/keys/server/server.key
dh /etc/openvpn/keys/server/dh2048.pem
verify-client-cert require
# crypto
tls-server
tls-version-min 1.3
tls-crypt /etc/openvpn/keys/server/ta.key 0
data-ciphers AES-256-GCM:AES-128-GCM
data-ciphers-fallback AES-256-GCM
auth SHA256
tls-groups X25519:secp384r1
tls-cert-profile preferred
tls-timeout 5
reneg-sec 3600
# network
topology subnet
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 8.8.8.8"
ifconfig-pool-persist /var/log/openvpn/ipp.txt
# other
sndbuf 0
rcvbuf 0
push "sndbuf 0"
push "rcvbuf 0"
tun-mtu 1500
mssfix 1400
persist-key
persist-tun
keepalive 10 60
max-clients 10
user nobody
group nogroup
reneg-sec 3600
tls-timeout 10
# Компрессия запрещена (VORACLE safe)
compress stub-v2
allow-compression no
;log-append /var/log/openvpn/openvpn.log
status /var/log/openvpn/status.log
verb 3
mute 10
crl-verify /etc/easy-rsa/pki/crl.pem
client config
udp config
client
remote 100.200.300.1
port 1194
proto udp
dev tun
resolv-retry infinite
nobind
remote-cert-tls server
tls-version-min 1.3
data-ciphers AES-256-GCM:AES-128-GCM
data-ciphers-fallback AES-256-GCM
auth SHA256
compress stub-v2
verb 3
<ca>
Содержимое корневого сертификата
/etc/openvpn/server/ca.crt
</ca>
<cert>
Содержимое сертификата клиента
/etc/openvpn/keys/easy-rsa/pki/issued/vpn_user_1.crt
</cert>
<key>
Содержимое ключа клиента
/etc/openvpn/keys/easy-rsa/pki/private/vpn_user_1.key
</key>
<tls-crypt>
Содержимое TLSключа для шифрования соединения
/etc/openvpn/server/tc.key
</tls-crypt>
tcp config
client
remote myserver.ru
port 443
proto tcp-client
dev tun
resolv-retry infinite
nobind
remote-cert-tls server
tls-version-min 1.3
data-ciphers AES-256-GCM:AES-128-GCM
data-ciphers-fallback AES-256-GCM
auth SHA256
compress stub-v2
verb 3
<ca>
Содержимое корневого сертификата
/etc/openvpn/server/ca.crt
</ca>
<cert>
Содержимое сертификата клиента
/etc/openvpn/keys/easy-rsa/pki/issued/vpn_user_1.crt
</cert>
<key>
Содержимое ключа клиента
/etc/openvpn/keys/easy-rsa/pki/private/vpn_user_1.key
</key>
<tls-crypt>
Содержимое TLSключа для шифрования соединения
/etc/openvpn/server/tc.key
</tls-crypt>
firewall for openvpn
Настройки Linux iptables для успешной работы OpenVPN сервера.
# Включаем IP forwarding. Разрешаем шлюзу передавать транзитный трафик
sysctl -w net.ipv4.ip_forward=1
# Разрешаем входящие соединения на порт OpenVPN-сервера, либо TCP, либо UDP
iptables -A INPUT -p udp --dport 1194 -j ACCEPT
iptables -A INPUT -p tcp --dport 1194 -j ACCEPT
# Вносим изменения в таблицу filter разрешаем исходящие соединения из tun
# tun0 - виртуальная сетевая карта, точка входа в тунель, создается VPN-сервером, работает на сетевом уровне (Layer 3)
# ens3 - имя внешнего сетевого интерфейса VPS
iptables -A FORWARD -i tun0 -o ens3 -j ACCEPT
# Разрешаем ответы из интернета
iptables -A FORWARD -i ens3 -o tun0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# Вносим изменения в таблицу nat. Делаем маскарадинг, при этом ip-адреса исходящих пакетов будут заменены на внешний ip хоста.
# 10.8.0.0/24 - сеть для vpn-клиентов, если сетей несколько, нужно делать правила для каждой сети
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o ens3 -j MASQUERADE
# Если внешний ip vpn-сервера статический, практичнее вместо маскарадинга сделать SNAT - будет работать быстрее
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o ens3 -j SNAT --to-source 100.101.102.103
# Происходит явная подмена source-IP на фиксированный внешний адрес хоста --to-source 100.101.102.103
install openvpn
Отличная ansible роль для установки и настройки openvpn сервера