Skip to content

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(корневой сертификат).

    Первый ключ секретный, его нужно оставить на сервере и никому не отдавать. Второй - открытый, его мы будем вместе с пользовательскими сертификатами передавать клиентам.

Создание CA
./easyrsa init-pki
./easyrsa build-ca
  • Создать файл параметров Диффи-Хелмана

Будет помещен в директорию pki/dh.pem

Создания параметров Диффи-Хелмана
./easyrsa gen-dh
  • Создать ключ и сертификат для сервера:

    • Закрытый ключ сервера 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
TLS control channel key
openvpn --genkey --secret /etc/openvpn/server/tc.key
  • Скопировать все необходимые для работы сервера ключи и сертификаты.
Копирование ключей
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

Создание сертификатов

Отзыв сертификатов

На практике случаются ситуации, когда выданные пользователям сертификаты требуется отозвать. Для этого необходимо выполнить следующие действия:

  • Создать список отозванных сертификатов.
crl
./easyrsa gen-crl
In -s /etc/easy-rsa/pki/crl.pem /etc/openvpn/keys/ # ссылка на список
  • В конфиг openvpn необходимо добавить директиву crl-verify
crl-verify
crl-verify /etc/openvpn/keys/crl.pem
  • revoke. Теперь любой выданный клиентский сертификат может быть отозван командой 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 указывается путь по которому храниться корневой сертификат.

ca
ca /etc/openvpn/server/ca.crt
  • cert - сертификат сервера: подтверждает клиенту, что он подключается к правильному серверу, содержит публичный ключ сервера, при подключении клиент проверяет туда ли он подключается.

    В директиве cert указывается путь по которому храниться сертификат сервера.

cert
cert /etc/openvpn/server/server.crt
  • key - приватный ключ сервера: используется для TLS-рукопожатия. доказывает, что сервер владеет сертификатом, должен храниться строго на сервере, права доступа обычно 600.

    В директиве key указывается путь по которому храниться приватный ключ сервера.

cert
key /etc/openvpn/server/server.key
  • dh - параметры Diffie-Hellman, используются для: генерации временного сеансового ключа, обеспечения Perfect Forward Secrecy (PFS)

    В директиве dh указывается путь по которому храниться dh.pem.

dh
dh /etc/openvpn/server/dh.pem

topology, server, push, route, etc..

Настройки виртуальной сети и подключаемых к ней клиентов.

  • topology - определяет способ выдачи IP клиентам.
topology
topology subnet #Все клиенты находятся в одной подсети и получают IP как в обычной подсети.
  • server - включает серверный режим и автоматически настраивает несколько параметров сети VPN. Фактически создать VPN-подсеть 10.8.0.0/24 и выдавать клиентам адреса из неё.
server
server 10.8.0.0 255.255.255.0
  • server-bridge - используется только с dev tap. OpenVPN работает как bridge, клиенты получают IP из LAN, VPN — как будто физически в одной сети.
server-bridge
;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100
  • ifconfig-pool-persist - сохраняет соответствие: client_name → IP, использую для этого текстовый файл. Чтобы клиент при повторном подключении получал тот же IP.
ifconfig-pool-persist
ifconfig-pool-persist /var/log/openvpn/ipp.txt
  • push - используется на сервере, чтобы передать настройки клиенту при подключении, сервер "пушит" конфигурацию клиенту, и клиент автоматически её применяет, как локальные настройки.
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"

Text Only
- **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 - имя соответствующего сертификата клиента

ccd
client-config-dir /etc/openvpn/ccd
  • client-to-client позволяет клиентам видеть друг друга, когда они подключены к виртуальной сети vpn-сервера.
client-to-client
;client-to-client
Настройки криптографии
# Директива сообщающая, что сервер работает в режиме 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 - самый безопасный вариант.

verify-client-cert require
verify-client-cert require
  • optional. Клиент может подключиться без сертификата. Используется если есть: auth-user-pass, RADIUS, LDAP, MFA
verify-client-cert optional
verify-client-cert optional
  • none. Сервер не требует сертификат вообще. Используется только если: username/password или OAuth/SSO.

    none- самый опасный вариант, не рекомендуется к использованию.

verify-client-cert none
verify-client-cert none

cipher, data-ciphers

  • Директива cipher определяет симметричный алгоритм шифрования.
cipher
;cipher AES-256-CBC # устаревший вариант
;cipher AES-256-GCM  # более современный вариант
  • data-ciphers - более современные директивы . Определяет шифры для передачи данных (data channel).
data-ciphers
data-ciphers AES-256-GCM:AES-128-GCM
data-ciphers-fallback AES-256-GCM # Используется, если клиент старый и не поддерживает negotiation.
auth SHA256 # нужна для совместимости и fallback-сценариев.

ecdh-curve, tls-groups

Text Only
# Следующая директива определяет кривую для 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 сек ответа нет - соединение перезапускается. Нужно для обнаружения “мертвых” клиентов.

keepalive
keepalive 10 120

user, group

Директивы, позволяющие ограничить привелегии демона openvpn. Сервер стартует от root, создает тунель tun, затем отбрасывает привелегии. Рекомендуется вклячать эти директивы для повышения безопасности.

user, group
user nobody
group nobody

persist-key, persist-tun

Директивы которые позволяют использовать имеющиеся ключи при перезапуске тонеля

persist-key
persist-key
persist-tun

logs

  • status - записывает текущее состояние сервера в указанный файл.
status
status /var/log/openvpn/openvpn-status.log

По умолчанию, логи пишутся в syslog.

  • log - записывае логи в указанный лог-файл, перезаписывает лог при каждом рестарте сервера.
log
;log         /var/log/openvpn/openvpn.log
  • log-append - записывае логи в указанный лог-файл. Сохраняет старый лог, дописывая его
log-append
;log-append  /var/log/openvpn/openvpn.log
  • verb - задает уровень логирования.
verb
verb 3 # оптимальный вариант
  • mute. Директива тишины в логах. Полезно при флуде ошибок. Повторяющиеся сообщения будут выводиться не более 20 раз подряд.
mute
;mute 20
  • explicit-exit-notify. Директива уведомления сервера об отключении клиента. Используется в UDP-режиме.
explicit-exit-notify
explicit-exit-notify 1

sndbuf, rcvbuf

Директивы управляющие размером сетевых буферов сокета для отправки и приёма данных.

  • Send buffer — размер буфера отправки. В современных дистрибутивах linux рекомендуется использовать автонастройку ядра ОС.
  • Receive buffer — буфер приёма. В современных дистрибутивах linux рекомендуется использовать автонастройку ядра ОС.
sndbuf, rcvbuf
sndbuf 0 #использовать автонастройку ядра ОС
rcvbuf 0 #использовать автоматический размер из ядра Linux

# Директивы push отправляют размеры буферов клиентам. Без push клиент может использовать другие значения.
push "sndbuf 0"
push "rcvbuf 0"

Пример UDP-конфига

Пример конфигурации OpenVPN сервера, работающего по UDP

/etc/openvpn/server/server.conf
# 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

udp client 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

tcp client 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 сервера