OpenVPN 2.4+ личный гайдлайн

Aug 20, 2018 13:00

Коллега попросил поделиться своими личными best-practice по использованию OpenVPN. Причем с нуля.
Поэтому я и написал сей гайдлайн. Замечу, что я рассматриваю OpenVPN версии старше 2.4.0, где XP уже не поддерживается, зато в остальных ОС появились очень приятные плюшки.
[Генерация ключей]

Начинаем, как обычно, с ключей. Генерить их можно где угодно и как угодно. Кто-то использует easyRSA, который практически в комплекте с OpenVPN идет, кто-то вообще openssl напрямую использует, я же предпочитаю XCA
Основные его преимущества - мультиплатформенность, наглядность, портативность базы (один зашифрованный файл совместимый с sqlite), ну и наличие всех необходимых возможностей.

1. Создаем новую базу и придумываем для нее пароль. Сертификаты хранятся в открытом виде, и их можно посмотреть, не зная пароля, а вот закрытые ключи будут недоступны.

2. Сразу идем в настройки. Задаем алгоритм подписи по умолчанию. Если вы нормальный человек, то SHA256 вам хватит, если вы немножко параноик и полагаете что надо использовать опережающую криптографию, то можете увеличить.
Далее ставим галку "Отключить устаревшие расширения Netscape". Ну правда, на кой нам они? Мы современные люди и использовать будем x509v3
Сохраняем, продолжаем.

3. Создаем корневой сертификат.
Вкладка "Первоисточник"
Создать самозаверенный сертификат
Шаблон для нового сертификата - [default] CA - Применить всё

Вкладка "Субъект"
Internal Name - имя, которое будет отображаться в самом XCA и более никуда не попадет. Кириллица допустима.
Common Name - имя сертификата, которое будет отображаться в логах соединения. Я их называю по шаблону "последний октет IP-адреса (нижнее подчеркивание) имя сертификата", поскольку далее назначаю статические адреса клиентам с помощью CCD (client-config dir), и такой метод позволяет сразу увидеть какие из них заняты.
Остальные поля можете заполнять или не заполнять - по желанию. Для того чтобы OpenVPN работал, достаточно одного лишь Common Name
Далее создаем закрытый ключ.
Щелкаем "Сгенерировать новый ключ" и... делаем небольшое отступление в теорию.
Начиная с версии 2.4.0 OpenVPN поддерживает эллиптические кривые в качестве ключей. Список доступных кривых ограничивается теми, что есть в OpenSSL, к сожалению, так что на Ed25519 не приходится рассчитывать раньше чем OpenVPN 2.5.0 (текущая - 2.4.6)
С одной стороны, эллиптика считается не менее безопасной чем RSA, и она действительно ощутимо быстрее. С другой стороны - существуют конспирологические теории относительно того, что кривые, стандартизированные NIST, имеют бэкдоры (их пока никто не нашел, а эллиптику для себя использует даже Google). Полезные ссылки - Хабр и проект SafeCurves
Из моих личных экспериментов, эллиптические ключи сокращают время коннекта к серверу 6-7 секунд до 3-4. Ну и нагрузка на сервер OpenVPN будет ниже (что будет заметно только когда клиентов наберется под пару сотен). Ассиметричные ключи используются только при коннекте и при регенерации ключей (каждый час, по умолчанию) так что тут уж сами выбирайте, что вам важнее - скорость или паранойя.
Сгенерировав ключ и задав ему имя (рекомендую, кстати, впереди писать все тот же последний октет IP-адреса, будет проще их искать впоследствии) идем на следующую вкладку.

Вкладка "Расширения"
Поскольку мы применили на первом шаге шаблон CA, то x509v3 Basic Constrains уже выставлен в нужные значения, и здесь мы задаем только время действия сертификата. Я обычно выбираю вчерашний день и ставлю галку "Начинать с полуночи", и "Применить". На сколько вы его выпускаете - смотрите сами.

Вкладка "Область применения ключа"
Поскольку мы применили на первом шаге шаблон CA, то нужная нам область применения уже выбрана.

На этом все. Нажимаем OK и получаем свой корневой сертификат. Отмечу, что XCA позволяет генерировать CRL. Для этого надо щелкнуть по корневому сертификату правой кнопкой мыши, выбрать "ЦС" - "Сгенерировать CRL". В случае с OpenVPN я этим не пользуюсь, предпочитая механизм "ccd-exclusive", о котором будет позже. Но вообще, по феншую, использовать его стоит.

Теперь создаем сертификат для сервера OpenVPN.
Создание его полностью аналогично созданию CA, разве что сертификат подписывается свежесозданным CA, а в качестве шаблона мы теперь выбираем и применяем [default] HTTPS_server
Отличия начинаются на вкладке "Область применения ключа".
В старых версиях OpenVPN была опция ns-cert-type, предназначенная для усложнений MitM-атак. В нынешних версиях OpenVPN она помечена как "DEPRECATED" и будет вскоре удалена. Поэтому мы будем использовать новую версию, remote-cert-tls
А для того чтобы она работала, у ключей должны быть выставлены определенные флаги расширенного использования.
Для сервера нам нужен "TLS Web Server Authentication"
На этом отличия заканчиваются. Ключ сервера готов.

Ключ клиента создается аналогично ключу сервера, но шаблон [default] HTTPS_client, а поле расширенного использования - "TLS Web Client Authentication"

На этом наши ключики готовы, и мы можем переходить к созданию конфигов.

[Серверный конфиг]

Первый конфиг - серверный. У меня он выглядит так:

#
# Секция параметров OpenVPN
#

# Общие настройки сервера
mode server ;указание на то, что демон OpenVPN будет ожидать подключений
proto udp4 ;протокол - UDP, используется только IPv4
port 1194 ;порт, по которому ожидаются соединения
server 172.16.1.0 255.255.255.0 ;пул адресов, из которого выдаются IP-адреса клиентам, не имеющим статического, заданного ccd
topology subnet ;кому интересно нафига оно - идут сюда
dev tun ;какой тип виртуального адаптера использовать. TUN - это OSI L3, IP-пакеты. TAP - это OSI L2, Ethernet-кадры.
# Что из этого лучше зависит от того, что вам нужно. Кратко: TAP бриджуется и позволяет слать внутри туннеля любые протоколы, однако имеет оверхед за счет Ethernet-заголовков у каждого пакета, плохо масштабируется, не работает с Android (ну разве что у вас есть рут)
# TUN не перекидывает broadcast-трафик, не бриджуется, позволяет слать внутри туннеля только IPv4 и IPv6, зато использует меньше трафика за счет отсутствия оверхеда
# Подробнее можно почитать тут
keepalive 15 45 ;суть - каждые 15 секунд OpenVPN шлет пакет keepalive, если в течении 45 секунд (3х пакетов) ничего не вернулось, то клиент считается упавшим
client-config-dir ccd ; директория (относительно файла сервера, либо надо указать абсолютный путь) в которой хранятся конфиги клиентов
ccd-exclusive ;опция, треубющая наличие ccd-файла для успешного подключения. Есть файл - подключится, нет файла - отлуп.
client-to-client ;опция, разрешающая клиентам видеть друг друга средствами самого OpenVPN. Соединения все равно будут идти через сервер
compress lz4-v2 ;сжатие трафика в туннеле (ВНИМАНИЕ: lz4-v2 ТОЛЬКО для OpenVPN старше 2.4!) Мнения тут расходятся. С одной стороны, если в туннеле бегает исключительно шифрованный трафик, то мы создаем лишнюю нагрузку на сервер. С другой стороны, при этом всегда сжимаются заголовки пакетов, что может дать некоторую экономию. Так же опция где-то на 1мс повышает время прохождения пакета через туннель, относительно этого же времени вне туннеля. Как обычно, решайте сами. Если не нужно - можно указать "none" или удалить строку целиком

# Ускорение (Linux-only) ;очень черная и экспериментальная магия. Вторая опция работает только если протокол - UDP
#txqueuelen 300
#fast-io

# Management Interface ; настройки взаимодействия с менеджмент-интерфейсом OpenVPN. Позволяет управлять демоном через telnet, и умеет много чего. За уточнение по этому поводу спасибо klink0v
management 127.0.0.1 7505
management-query-passwords
auth-retry interact

# Логирование и внешние файлы
ifconfig-pool-persist 2018_UDP_Pool.txt ;в этом файле хранятся адреса, выданные внутренним DHCP OpenVPN клиентам, у которых такие адреса не заданы жестко
log-append 2018_UDP.log ;в этом файле хранится лог
status 2018_UDP_Status.log 10 ;в этом файле хранится текущий статус сервера - сколько работает, какие клиенты подключены. Последняя цифра означает, что обновляется этот файл раз в 10 секунд
status-version 3 ;что именно указывается в предыдущем файле. 3 - это для OpenVPN старше 2.4.0, максимум данных и они удобно отформатированы
verb 3 ;насколько подробным должен быть лог

# Настройки безопасности демона
persist-key ;не перечитывать ключи при мягких перезапусках OpenVPN. Подробнее можно смотртеь тут
persist-tun ;не переоткрывать устройство TUN/TAP при мягких перезапусках OpenVPN, подробнее там же
auth-nocache ;не хранить пароли в памяти, подробнее там же
#mlock ;linux-only опция, при включении которой ключи в памяти никогда не будут записаны на диск
#user nobody ;тоже linux-only, задание пользователя и группы под которыми будет работать OpenVPN после инициализации
#group nogroup

# Улучшение работы на Linux-машинах (https://habrahabr.ru/post/246953/)
sndbuf 393216
rcvbuf 393216

# Настройки шифрования
auth SHA256 ;алгоритм подписи, выбранный для сертификатов при их генерации
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 ;алгоритм шифрования, использующийся во время подключения и согласования симметричного ключа. Если вы выбрали эллиптику для ключей, то посмотрите "Дополнительные материалы" внизу.
cipher AES-256-GCM ;алгоритм шифрования симметричным ключом. По сравнению с AES-128, AES-256 медленнее всего на 15%
ncp-ciphers AES-256-GCM ;новая функция в OpenVPN старше 2.4, позволяющая согласовать более стойкий шифр при соединении, а не взять его из конфига. В старых версиях OpenVPN игнорируется.

# Дополнительная безопасность соединения.
tls-version-min 1.2 ;какую версию TLS использовать при согласовании соединений
remote-cert-tls client ;Подтверждение типа клиентского сертификата, то самое, для чего нужны дополнительные флаги при генерации ключей

#
# Секция сертификатов и ключей
#

# Ключи - Сертификат удостоверяющего центра

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

# Ключи - Сертификат сервера

Место для сертификата

# Ключи - Закрытый ключ сервера

Место для закрытого ключа

# Ключи - Параметры Diffie-Hellman

Параметры можно сгенерировать в XCA, "Дополнительно - сгенерировать параметры Диффи-Хэлманна

# Ключи - Статический ключ HMAC-фаервола

А вот эта опция интересная. Ключ создается так же, как и старая добрая tls-auth, с помощью команды "openvpn --genkey --secret static.txt", но в отличие от старой опции, которая только подписывала пакеты, эта (поддерживается только с openvpn 2.4.0) их шифрует.
А это значит, что никакие DPI не смогут понять, что пересылаемый трафик принадлежит OpenVPN, в то время как раньше отловить характерные для OpenVPN пакеты не составляло никакого труда. Как и заблочить это на взлете
Естественно, как и tls-auth, tls-crypt защищает от DoS-атак.

Теперь - Client Config Directory, оно же CCD
Это механизм, который дает OpenVPN ту невероятную гибкость, которую так любят многие администраторы. Суть в том, что для каждого клиента можно настроить не только выдаваемый ему статический адрес, но и спускаемые маршруты, DNS-сервера, search domain, выполняемые команды и много других вещей, ради которых стоит почитать man.
CCD должен называться так же, как и common name клиента. Если файл CCD пуст, то OpenVPN лишь позволит аутентифицироваться клиенту, и выдаст ему IP-адрес из заданного параметром server пула адресов.
Обычно я вношу туда только одну команду - "ifconfig-push 172.16.1.2 255.255.255.0", то есть задаю клиенту статический адрес.
Еще одна важная особенность - по умолчанию CCD дополняют те опции, что есть в основном файле конфига. Т.е. если у вас в конфиге сервера написано:
push "route 192.168.0.0 255.255.255.0 172.16.1.2", а в CCD "192.168.1.0 255.255.255.0 172.16.1.2", то клиент получит оба маршрута. Если нужно, чтобы CCD перезаписывал параметры конфига, в первой строке CCD надо написать push-reset

[Клиентский конфиг]

Теперь переходим к конфигу клиента.

#
# Секция параметров OpenVPN
#

# Общие настройки клиента
client
remote dnsname.or.ip 1194 ;где 1194 это порт подключения. Можно задать несколько адресов, и OpenVPN может подключаться к ним по очереди. Так же, начиная с 2.4.0 появилась возмонжость указывать не просто адреса, а целый набор параметров, заключенных между тегами . Подробнее про поддерживаемые параметры можно посмотреть здесь
proto udp4
dev tun
keepalive 15 45
compress lz4-v2

# Ускорение (Linux-only)
#txqueuelen 300
#fast-io

# Логирование и внешние файлы
status status.log 10
status-version 3
verb 3

# Настройки безопасности демона
persist-key
persist-tun
auth-nocache
#mlock
#user nobody
#group nogroup

# Улучшение работы на Linux-машинах (https://habrahabr.ru/post/246953/)
sndbuf 393216
rcvbuf 393216

# Настройки шифрования
auth SHA256
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384
cipher AES-256-GCM
ncp-ciphers AES-256-GCM

# Дополнительная безопасность соединения.
tls-version-min 1.2
remote-cert-tls server ;Подтверждение типа серверного сертификата

#
# Секция сертификатов и ключей
#

# Ключи - Сертификат удостоверяющего центра

# Ключи - Сертификат клиента

# Ключи - Закрытый ключ клиента

# Ключи - Статический ключ HMAC-фаервола

Готово. Можно подключаться и пользоваться, а так же настраивать разные дополнительные фичи.

[Дополнительные материалы]

Некоторый собственный опыт.
Во-первых, насчет эллиптики и RSA. Использовать смешанные вариации нельзя, так что если у вас RSA, то
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 или другие RSA
Если же вы выбрали EC, то
tls-cipher ECDHE-ECDSA-AES256-GCM-SHA384 или другие ECDHE-ECDSA
В принципе, можно указать оба в одну строчку. Или вообще выбрать что полегче. Посмотреть поддерживаемые шифры можно запуская OpenVPN с опциями... которые вы найдете в мануалах. Благо ссылки я на них оставил в больших количествах.

По поводу производительности и нагрузки OpenVPN в зависимости от используемых опций есть замечательная статья.
Автор рассматривает производительность OpenVPN на роутере, но так разница видна еще лучше.

Однажды сталкивался с проблемой в iOS, когда конфиги не работали, если в них были комментарии. Да и вообще, храните конфиги в сберегательном ANSI

При необходимости спускать маршруты на ойфоны, необходимо писать не push "route СЕТЬ МАСКА ГЕЙТ", а только push "route СЕТЬ МАСКА", иначе они будут проигнорированы. За это дополнение спасибо hvostat_hvostat

Реализация OpenVPN в Android имеет множество странностей и ограничений (почитать о которых можно в FAQ ) и порой там приходится втыкать костыли, чтобы нормально бегали пакетики. На официальных прошивках такое встречается редко, а на кастомных иногда бывает необходимость делать так:
ip rule add to 172.16.1.0/24 lookup 62
ip route add 172.16.1.0/24 dev tun0 table 62

Обычно для этого нужен root и установленный BusyBox, впрочем, раз у вас кастомная прошивка, то вы справитесь.

self-hosted, Инструкции, Личная безопасность, openvpn, IT-сфера, android

Previous post Next post
Up