Конфигурация OpenVPN с Easy-RSA#

(Nitrokey Pro 2 - Windows)

Примечание

Это руководство находится в процессе разработки и будет обновляться по мере необходимости. Пожалуйста, примите во внимание этот статус.

В этом руководстве показано, как настроить клиентов OpenVPN на вход в систему с помощью Nitrokey Pro 2 или Nitrokey Storage 2. Для программного управления ключами мы будем использовать Easy-RSA, утилиту, которая развивалась параллельно с OpenVPN.

Для подписи сертификатов мы будем использовать Nitrokey HSM 2, настроенный как центр сертификации, однако в данном руководстве не рассматривается настройка самого ЦС (это четко и хорошо описано здесь).

Мы будем использовать Easy-RSA, так как он, по-видимому, обеспечивает определенную гибкость и позволяет управлять ключами через внешние PKI. Мы будем использовать его на сервере для выдачи запроса на подписание, и повторим тот же процесс на клиенте. Запросы на подписание сертификатов будут подписываться ЦС на Nitorkey HSM и повторно передаваться на сервер и клиенту.

Пререквизиты#

В следующей документации нам понадобятся 3 различные машины:

  • Сервер OpenVPN (v. 2.5) на Debian 10 (виртуальная машина EC2 - AWS)

  • Клиент OpenVPN (v. 2.4.9) на Fedora 30 (локальная машина)

  • Центр сертификации будет доступен с отдельной машины с Fedora 30 (локальная машина).

Для взаимодействия с устройствами нам потребуется OpenSC 0.20, установленный на машине клиента и CA (локальные машины). Вы можете следовать инструкциям по его установке в этой ссылке (*Unix).

Для загрузки зависимостей на машины Fedora мы можем воспользоваться этой инструкцией:

su -c 'dnf install readline-devel openssl-devel libxslt docbook-style-xsl pcsc-lite-devel automake autoconf libtool gcc zlib-devel'

Для Debian Linux более свежие пакеты OpenSC доступны здесь.

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

Напомним, что для создания центра сертификации на Nitrokey HSM 2 вы можете следовать инструкциям, доступным в документации.

В качестве альтернативы вы можете установить свой собственный CA на отдельной машине, или использовать учебник OpenVPN, который также полагается на Easy-RSA. Последние 2 варианта полагаются на программные решения для управления ключами.


Сторона сервера#

1. Установите OpenVPN#

  1. Сначала нам нужно включить IP Forwarding, отредактировав файл /etc/sysctl.conf.

$ editor /etc/sysctl.conf
  1. Снимите комментарий или отредактируйте соответствующим образом следующую строку

net.ipv4.ip_forward=1
  1. Закройте его после сохранения и введите следующую команду

$ sysctl -p

После того, как переадресация IP будет выполнена, нам нужно будет загрузить последний выпуск OpenvPN для нашего сервера Debian 10, согласно этой инструкции:

  1. Перейдите в права root и загрузите ключ GPG, которым был подписан пакет

$ sudo -s
# wget -O - https://swupdate.openvpn.net/repos/repo-public.gpg|apt-key add -
  1. Добавьте URL соответствующих пакетов OpenVPN в файл sources.list.

# echo "deb http://build.openvpn.net/debian/openvpn/release/2.5 buster main" > /etc/apt/sources.list.d/openvpn-aptrepo.list
# exit

Мы загрузили OpenVPN 2.5, так как «запрос пароля» требует для входа как минимум OpenVPN версии 2.4.8.

  1. Далее мы загружаем OpenVPN

$ sudo apt install openvpn

Если вы хотите проверить версию, это можно сделать, вызвав --version и вывести следующее:

$ sudo openvpn --version
OpenVPN 2.5_beta3 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Sep  1 2020
library versions: OpenSSL 1.1.1d 10 Sep 2019, LZO 2.10
Originally developed by James Yonan
Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
Compile time defines: enable_async_push=no enable_comp_stub=no enable_crypto_ofb_cfb=yes enable_debug=yes enable_def_auth=yes enable_dependency_tracking=no \ enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown enable_fast_install=needless enable_fragment=yes enable_iproute2=yes \ enable_libtool_lock=yes enable_lz4=yes enable_lzo=yes enable_maintainer_mode=no enable_management=yes enable_multihome=yes enable_pam_dlopen=no enable_pedantic=no \ enable_pf=yes enable_pkcs11=yes enable_plugin_auth_pam=yes enable_plugin_down_root=yes enable_plugins=yes enable_port_share=yes enable_selinux=no \ enable_shared=yes enable_shared_with_static_runtimes=no enable_silent_rules=no enable_small=no enable_static=yes enable_strict=no enable_strict_options=no \ enable_systemd=yes enable_werror=no enable_win32_dll=yes enable_x509_alt_username=yes with_aix_soname=aix with_crypto_library=openssl with_gnu_ld=yes \ with_mem_check=no with_sysroot=no

2. Установите Easy-RSA#

Для создания PKI мы загрузим последнюю версию Easy-RSA на серверную и клиентскую машины. Чтобы получить последнюю версию, перейдите на страницу Releases официального проекта EasyRSA на GitHub, скопируйте ссылку на скачивание файла, заканчивающегося на .tgz, а затем вставьте ее в следующую команду:

  1. Загрузите последнюю версию

$ cd ~
wget -P ~/ https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.7/EasyRSA-3.0.7.tgz
  1. Распакуйте tarball

$ cd ~
$ tar xvf EasyRSA-3.0.7.tgz
$ mv EasyRSA-3.0.7/ easyrsa/ # rename folder

3. Создание PKI для сервера OpenVPN#

Прежде чем создавать закрытый ключ и сертификат сервера OpenVPN, вам необходимо создать локальный каталог Public Key Infrastructure на вашем сервере OpenVPN. Вы будете использовать этот каталог для управления запросами сертификатов сервера и клиентов, вместо того, чтобы делать их непосредственно на сервере CA.

Чтобы создать каталог PKI на вашем сервере OpenVPN, вам нужно заполнить файл vars некоторыми значениями по умолчанию.

  1. Создайте файл vars.

$ touch ~/easyrsa/vars
$ cd easyrsa/
$ editor vars
  1. После открытия файла вставьте следующие две строки

set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"

Это единственные две строки, которые нужны в этом vars файле на вашем сервере OpenVPN, поскольку он не будет использоваться в качестве центра сертификации. Они обеспечат, чтобы ваши закрытые ключи и запросы сертификатов были настроены на использование криптографии эллиптических кривых (ECC) для генерации ключей и безопасных подписей для ваших клиентов и сервера OpenVPN.

Что касается выбора криптографических алгоритмов, я следую модели, приведенной в этом руководстве, а вы можете настроить их в соответствии со своими конкретными потребностями.

  1. Инициализация ИПК

После заполнения файла vars вы можете приступить к созданию каталога PKI. Для этого запустите скрипт easyrsa с опцией init-pki:

$ ./easyrsa init-pki

После инициализации PKI на сервере OpenVPN вы готовы перейти к следующему шагу - созданию запроса на сертификат сервера OpenVPN и закрытого ключа.

4. Создайте server.req и server.key.#

Теперь, когда на вашем сервере OpenVPN установлены все необходимые условия, следующим шагом будет создание ключевой пары, состоящей из закрытого ключа (для сохранения секретности) и запроса на подписание сертификата (.csr) на вашем сервере OpenVPN.

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

Совет

Заметки по конфигурации OpenVPN:

  1. Сервер и каждый клиент должны иметь свой собственный файл cert и key. Сервер и все клиенты будут использовать один и тот же файл CA.

  2. Сертификат сервера должен иметь следующее:

  • keyUsage:  digitalSignature, keyEncipherment

  • extendedKeyUsage: serverAuth`

  1. Создайте запрос на подписание для сервера

Перейдите в каталог ~/easyrsa на сервере OpenVPN от имени пользователя, не являющегося root, и введите следующие команды:

$ cd easyrsa/
$ ./easyrsa gen-req server nopass

В результате будет создан закрытый ключ для сервера и файл запроса сертификата server.req.

Когда у вас есть подписанный сертификат, вы передадите его обратно на сервер OpenVPN.

  1. Скопируйте ключ в каталог сервера OpenVPN

$ sudo cp /home/admin/EasyRSA/pki/private/server.key /etc/openvpn/server/

Выполнив эти шаги, вы успешно создали закрытый ключ для вашего сервера OpenVPN. Вы также создали запрос на подпись сертификата для сервера OpenVPN.

Совет

Расширения файлов для запросов на подписание сертификата

Расширение файла, принятое в учебнике по CA и HSM, указывает на создание файла .csr, однако Easy-RSA создает запросы на подписание сертификата с расширением .req.

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

В следующем разделе этого руководства мы подпишем файл .req с нашим ЦС, развернутым на устройстве HSM 2. Для этой цели я буду использовать выделенную машину для подписи запросов.

5. Подписать и получить server.crt.#

Следующие инструкции требуют передачи файла server.req (или server.csr) в систему CA.

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

Чтобы пройти через эти шаги, я буду в значительной степени полагаться на эти инструкции, чтобы подписать запросы на подписание сертификатов, после того как мы сгенерируем их с помощью Easy-RSA.

5.1. Подпишите файл server.req.#

На локальной машине, выделенной для доступа к HSM, мы будем использовать инструменты, предоставляемые Opensc 0.20, чтобы подписать файл .req и отправить его обратно на сервер OpenVPN. Мы предполагаем, что мы передали файл с машины сервера на машину CA.

Для начала подключим HSM Nitrokey и введем эту инструкцию для перечисления доступных клавиш.

  1. Запрос списка доступных устройств

  $ p11tool --list-all

**(Required step)** If this is the first time you sign a certificate with the CA, you might want to retrieve the URI of the CA’s private key from the HSM, and include it in the config file.
  • URI ключа должен иметь такой формат:

pkcs11:model=PKCS%2315%20emulated;manufacturer=www.CardContact.de;serial=DENK0104068;token=SmartCard-HSM%20%28UserPIN%29%00%00%00%00%00%00%00%00%00;id=%E0%16%1C%C8%B6%F5%D6%6A%C6%83%5E%CD%EC%B6%23%FC%05%06%A6%75;object=root;type=private
  1. Создайте каталог openvpn/ под каталогом certificate-authority/.

$ mkdir/opt/certificate-authority/
$ cd /opt/certificate-authority/
  1. Подпишите server.req.

$ openssl ca -config sign_server_csrs.ini -engine pkcs11 -keyform engine -days 375 -notext -md sha512 -create_serial -in server.req -out /home/user/pki/issued/server.crt

5.2. Извлечение файла server.crt на серверную машину#

  1. Перенесите подписанные сертификаты на сервер

С машины CA скопируйте файлы server.crt и chain.crt на сервер OpenVPN. В данном примере мы будем использовать команду scp следующим образом:

$ scp openvpn/{server.crt,chain.crt} admin@your_openvpnserver_ip:/tmp
  1. Поместите сертификаты в каталог сервера

$ mv /tmp/{server.crt,chain.crt} /etc/openvpn/server

Предупреждение

Сертификат CA и chain.crt.

В приведенном выше примере ЦС возвращает подписанный сертификат sever и включает сертификат ЦС CA.crt, который является файлом chain.crt. Это может быть сделано по небезопасному каналу, хотя клиенту рекомендуется подтвердить, что полученный chain.crt является действительным, если транспорт не является доверенным.

Можно переименовать файл chain.crt в CA.crt на целевой машине, однако в следующих инструкциях мы будем использовать chain.crt.

6. Настройте сервер OpenVPN#

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

OpenVPN server

    - The root certificate file (CA.crt or chain.crt in our setup)
    - Server certificate
    - Server key
    - Diffie Hellman Parameters (optional)

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

# OpenVPN Server Certificate - CA, server key and certificate
ca chain.crt
cert server.crt
key server.key

Вот файл конфигурации, который мы можем использовать для тестирования этих инструкций:

port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
dh dh.pem
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
keepalive 10 120
tls-auth ta.key 0 # This file is secret
cipher AES-256-CBC
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log         /var/log/openvpn/openvpn.log
log-append  /var/log/openvpn/openvpn.log
verb 3
explicit-exit-notify 1
tls-version-min 1.2 # Lower boundary for TLS version
tls-version-max 1.2 # Higher boundary for TLS version

Чтобы проверить, правильно ли работает конфигурация, мы можем использовать эту команду:

$ sudo openvpn --server --config server.conf

7. Запустите службу OpenVPN на сервере#

Включите службу OpenVPN, добавив ее в systemctl, и запустите ее с помощью этих команд:

$ sudo systemctl -f enable openvpn@server
$ sudo systemctl start openvpn@server

Чтобы дважды проверить, активна ли служба OpenVPN, используйте эту команду:

$ sudo systemctl status openvpn@server

На этом этапе OpenVPN должен быть запущен.


Конфигурация на стороне клиента#

1. Установите OpenVPN и Easy-RSA#

  1. Установите программное обеспечение

Мы можем использовать непосредственно dnf install для установки OpenVPN 2.4.9 и Easy-RSA 3.0.7

$ sudo dnf install openvpn easy-rsa
  1. Затем мы создадим как не root каталог для Easy RSA под названием Easy-RSA.

$ mkdir ~/easyrsa
  1. И свяжите его с пакетом Easy RSA, который мы только что установили

$ ln -s /usr/share/easy-rsa/3/* ~/easyrsa/

2. Создайте PKI для клиента OpenVPN#

Точно так же, как мы создавали PKI на сервере OpenVPN, мы создадим PKI с использованием Easy-RSA на стороне клиента.

3. Создайте client.req и client.key.#

Таким же образом, как мы создавали пару ключей на сервере, мы генерируем пару ключей для клиента, которая будет состоять из файла client.req и файла client.key. Последний должен храниться в секрете на клиентской машине.

4. Подпишите client.req и выдайте файл client.crt.#

Для переноса файла client.req на машину CA мы будем использовать тот же метод, что и для файла server.req.

После передачи, на машине ЦС мы подписываем файл запроса на подписание сертификата с помощью следующей команды

$ openssl ca -config sign_server_csrs.ini -engine pkcs11 -keyform engine -days 375 -notext -md sha512 -create_serial -in client.req -out /home/user/pki/issued/client.crt

5. Импортируйте client.crt на Nitrokey с машины CA#

После создания файла client.crt, мы подключаем устройство Nitrokey Pro 2 к машине CA и импортируем файл .crt на устройство Pro 2 с помощью этой команды:

$ pkcs15-init --store-certificate client.crt --id 3

Вы можете проверить, эффективно ли хранится ключ на Nitrokey, с помощью этой команды:

$ pkcs15-tool -c

Или в качестве альтернативы

$ pkcs11-tool --list-objects

Дополнительные команды вы можете найти в OpenSC wiki.

6. Извлеките файл chain.crt с машины CA#

Пока мы держим client.crtstored on the nitrokey Pro 2 device, we must retrieve the chain.crt файл на клиентской машине и храним его в адекватной директории. Мы можем использовать scp, как в методе, описанном в серверном разделе данного руководства.

7. Настройте клиент на взаимодействие с Nitrokey#

Теперь вернемся на клиентскую машину, подключим Nitrokey Pro и используем его для установления VPN-соединения с сервером. В общих чертах, соединение, использующее TLS, требует нескольких сертификатов и ключей для аутентификации:

OpenVPN client
    - The root certificate file (`chain.crt`)
    - Client certificate
    - Client key

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

client
dev tun
proto udp
remote <server> 1194
resolv-retry infinite
nobind
user nobody
group nobody
persist-key
persist-tun
ca ca.crt
remote-cert-tls server
cipher AES-256-CBC
verb 3
redirect-gateway def1
tls-version-min 1.2 # Lower boundary for TLS version
tls-version-max 1.2 # Higher boundary for TLS version
  1. Определите правильный объект

Каждый провайдер PKCS#11 может поддерживать несколько устройств. Для просмотра списка доступных объектов можно использовать следующую команду:

$ openvpn --show-pkcs11-ids /usr/lib64/pkcs11/opensc-pkcs11.so

The following objects are available for use.
Each object shown below may be used as parameter to

--pkcs11-id option please remember to use single quote mark.

Certificate
       DN:             CN=client
       Serial:         E53DA75C5B8F1518F520BCEF0128C09F
       Serialized id:  pkcs11:model=pkcs11:model=PKCS%NNNN%20emulated;token=User%20PIN%20%28OpenPGP%20card%29;manufacturer=ZeitControl;serial=000NNNNNN;id=%03

Каждый сертификат/пара закрытых ключей имеют уникальную строку Serialized id. Сериализованная строка id запрашиваемого сертификата должна быть указана в конфигурационном файле. Это можно сделать, добавив опцию pkcs11-id, используя одинарные кавычки.

pkcs11-id 'pkcs11:model=pkcs11:model=PKCS%NNNN%20emulated;token=User%20PIN%20%28OpenPGP%20card%29;manufacturer=ZeitControl;serial=000NNNNNN;id=%03'
  1. Добавьте полученный сериализованный идентификатор в файл конфигурации

Используя ваш любимый текстовый редактор, откройте файл server.conf и добавьте следующие строки, не забыв вставить свои собственные Serialized id:

pkcs11-providers /usr/lib64/pkcs11/opensc-pkcs11.so
pkcs11-id 'pkcs11:model=pkcs11:model=PKCS%NNNN%20emulated;token=User%20PIN%20%28OpenPGP%20card%29;manufacturer=ZeitControl;serial=000NNNNNN;id=%03'

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

Примечание

Нажмите для просмотра кода

# nitrokey config

pkcs11-providers /usr/lib64/pkcs11/opensc-pkcs11.so
pkcs11-id 'pkcs11:model=pkcs11:model=PKCS%NNNN%20emulated;token=User%20PIN%20%28OpenPGP%20card%29;manufacturer=ZeitControl;serial=000NNNNNN;id=%03'
# pkcs11-pin-cache 300
# daemon
# auth-retry nointeract
# management-hold
# management-signal
# management 127.0.0.1 8888
# management-query-passwords
pkcs11-cert-private 1 # Prompt for PIN

Необязательный шаг

Если вам нужно проверить конфигурацию с токеном на Nitrokey и без него, вы можете добавить строки в тот же client.conf и закомментировать/отменить соответствующие строки в соответствии с вашими потребностями:

Примечание

Нажмите для просмотра кода

# non_nitrokey login

# cert client.crt
# key client.key
# tls-auth ta.key 1
  1. Настройка клиента OpenVPN

Окончательный конфигурационный файл client.conf должен выглядеть следующим образом:

client
dev tun
proto udp
remote <server> 1194
resolv-retry infinite
nobind
user nobody
group nobody
persist-key
persist-tun
ca ca.crt
remote-cert-tls server
cipher AES-256-CBC
verb 3
redirect-gateway def1
tls-version-min 1.2 # Lower boundary for TLS version
tls-version-max 1.2 # Higher boundary for TLS version

# nitrokey login

pkcs11-providers /usr/lib64/pkcs11/opensc-pkcs11.so
pkcs11-id 'pkcs11:model=pkcs11:model=PKCS%NNNN%20emulated;token=User%20PIN%20%28OpenPGP%20card%29;manufacturer=ZeitControl;serial=000NNNNNN;id=%03'
# pkcs11-pin-cache 300
# daemon
# auth-retry nointeract
# management-hold
# management-signal
# management 127.0.0.1 8888
# management-query-passwords
pkcs11-cert-private 1 # Prompt for PIN

# OR

# non_nitrokey login

# cert client.crt
# key client.key
# tls-auth ta.key 1
  1. Настройка OpenVPN

Для того чтобы установить рукопожатие, необходимо настроить OpenSSL, входящий в состав OpenVPN.

Создайте каталог ssl в C:\Program Files\OpenVPN и создайте файл openssl.cnf со следующим содержимым :

openssl_conf = default_conf

[ default_conf ] ssl_conf = ssl_sect

[ ssl_sect ] system_default = ssl_default_sect

[ ssl_default_sect ] SignatureAlgorithms = RSA+SHA512:ECDSA+SHA512:RSA+SHA384:ECDSA+SHA384:RSA+SHA256:ECDSA+SHA256 MaxProtocol = TLSv1.2 MinProtocol = TLSv1.2

При такой модификации у вас не будет возникать ошибок, о которых сообщается здесь, здесь и здесь.

  1. Известные проблемы

Существует несколько известных проблем, связанных с входом в OpenVPN с помощью OpenSC. Пожалуйста, ознакомьтесь с этими проблемами здесь.

8. Запустите клиент OpenVPN#

  1. Запустите службу OpenVPN на клиенте

Включите службу OpenVPN и запустите ее с помощью этих команд:

$ sudo systemctl -f enable openvpn-server@server.service
$ sudo systemctl start openvpn-server@server.service

Чтобы дважды проверить, активна ли служба OpenVPN, используйте эту команду:

$ sudo systemctl status openvpn-server@server.service
  1. Введите PIN-код пользователя

При запуске клиента OpenVPN необходимо ввести PIN-код Nitrokey:

$ sudo openvpn --client --config client.conf
Fri Sep 11 17:42:01 2020 OpenVPN 2.4.9 x86_64-redhat-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Apr 24 2020
Fri Sep 11 17:42:01 2020 library versions: OpenSSL 1.1.1g FIPS  21 Apr 2020, LZO 2.08
Fri Sep 11 17:42:01 2020 PKCS#11: Adding PKCS#11 provider '/usr/lib64/pkcs11/opensc-pkcs11.so'
Enter User PIN (OpenPGP card) token Password: ******

В некоторых случаях он не запрашивает PIN-код на терминале. Обходным решением может быть использование этой команды для входа в систему с PIN-кодом:

$ telnet 8888 password 'User PIN (OpenPGP card) token' <PIN>

В качестве альтернативы вы можете перекомпилировать клиент OpenVPN с отключенной поддержкой systemd, и он запросит PIN-код, как и ожидалось.

Другим вариантом может быть вход в ваш экземпляр OpenVPN с помощью клиента Viscosity, который обеспечивает лучший пользовательский опыт, особенно для ввода PIN-кода.