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

(Nitrokey FIDO2 - Windows)

Note

Това ръководство е в процес на разработване и ще бъде актуализирано според случая. Моля, вземете предвид този статус.

Това ръководство показва как да конфигурирате клиентите на OpenVPN да влизат в системата с помощта на Nitrokey Pro 2 или Nitrokey Storage 2. За управление на софтуерни ключове ще използваме Easy-RSA, помощна програма, която се развива успоредно с OpenVPN.

За подписване на сертификатите ще използваме Nitrokey HSM 2, създаден като Сертификационен орган, това ръководство обаче не обхваща настройката на самия CA (тя е ясна и добре документирана тук).

Ще използваме Easy-RSA, тъй като изглежда осигурява известна гъвкавост и позволява управление на ключове чрез външни PKI. Ще го използваме на сървъра, за да подадем заявка за подписване, и ще повторим същия процес на клиента. Исканията за подписване на удостоверения ще бъдат подписани от УО на HSM на Nitorkey и ще бъдат изпратени повторно до сървъра и клиента.

Предварителни условия#

В следващата документация ще ни трябват 3 различни машини, както следва:

  • OpenVPN сървър (версия 2.5) на Debian 10 (виртуална машина EC2 - AWS)

  • Клиент на OpenVPN (версия 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 тук.

Ще използваме следните Nitrokeys за управление на физически ключове:

Напомняме ви, че за да изградите удостоверяващ орган на 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. Извличане на тарбала

$ 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. Иницииране на PKI

След като сте попълнили файла vars, можете да продължите със създаването на директорията PKI. За да направите това, стартирайте скрипта easyrsa с опцията init-pki:

$ ./easyrsa init-pki

След като сте инициализирали PKI на OpenVPN сървъра, можете да преминете към следващата стъпка, а именно създаване на заявка за сертификат и частен ключ на OpenVPN сървъра.

4. Създаване на server.req и server.key#

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

Най-общо казано, в системите, в които генерираме ключ и заявка, тези файлове се оставят некриптирани чрез аргумента nopass, тъй като сървърите обикновено трябва да се стартират без въвеждане на парола. Това генерира некриптиран ключ, така че имайте предвид, че защитете внимателно достъпа до него и разрешенията за файлове.

Tip

Бележки за конфигурацията от OpenVPN:

  1. Сървърът и всеки клиент трябва да разполагат със собствен файл със сертификат и ключ. Сървърът и всички клиенти ще използват един и същ 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 сървъра.

Tip

Заявки за подписване на ключови сертификати

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

Ще използваме взаимозаменяемо и двете разширения, като се уверим, че сме прехвърлили правилните файлове към удостоверяващия орган и ще генерираме окончателно удостоверение с разширение .crt.

В следващия раздел на това ръководство ще подпишем .req файл с нашия CA, разположен на устройството 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

Warning

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

В горния случай CA връща подписаното северно удостоверение и включва удостоверението на CA 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. След това създаваме като некоренна директория за 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.

След като бъде прехвърлен, на машината на CA подписваме файла със заявката за подписване на сертификат с тази команда

$ 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 низ. Сериализираният идентификационен низ на искания сертификат трябва да бъде посочен в конфигурационния файл. Можем да направим това, като добавим опцията 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 удостоверяване, можете също така да добавите няколко реда за управление на ключовете, въпреки че това не е задължително.

Note

Кликнете, за да видите кода

# 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 и да коментирате/отменяте съответните редове според нуждите си:

Note

Кликнете, за да видите кода

# 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. Въведете потребителския си ПИН код

При стартиране на OpenVPN клиента е необходимо да се въведе ПИН кодът на 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: ******

В някои случаи не се изисква въвеждане на ПИН код на терминала. Един от възможните начини за заобикаляне на ситуацията е да използвате тази команда, за да влезете в системата с ПИН код:

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

Алтернативно, можете да прекомпилирате OpenVPN клиента с изключена поддръжка на systemd и той ще ви поиска ПИН кода, както се очаква.

Друг вариант е да влезете в OpenVPN инстанцията си с клиента Viscosity, който осигурява по-добро потребителско изживяване, особено при въвеждането на ПИН кода.