Изменения

Настройка ГОСТ-TLS через КриптоПро

18 713 байтов добавлено, 15:43, 26 мая 2017
Новая страница: «В протоколе https:// можно использовать криптографию ГОСТ (ГОСТ Р 34.10-2001, ГОСТ Р 34.10-94). Для эт…»
В протоколе https:// можно использовать криптографию ГОСТ (ГОСТ Р 34.10-2001, ГОСТ Р 34.10-94).

Для этого на Linux сервере есть 2 варианта реализации:
* Opensource, добавленная в OpenSSL 1.0.* и входящая в комплект его поставки, и отделённая в https://github.com/gost-engine/engine, начиная с OpenSSL 1.1. Реализована компанией КриптоКом, НЕ сертифицирована.
* Реализация через КриптоПро CSP и gost_capi. КриптоПро сертифицировано ФСБ, есть 3.9 и 4.0, 4.0 отличается дополнительным наличием поддержки чуть более нового стандарта ГОСТ Р 34.10-2012, однако для совместимости со старыми версиями КриптоПро (3.6, 3.9) и opensource реализацией его использовать не надо.

== Настройка OpenSource реализации (КриптоКом) ==

Самая простая в установке реализация ГОСТ — opensource. Установка сводится к 2 пунктам:
# Найти в комплекте поставки ИЛИ собрать engine «/usr/lib64/openssl/libgost.so»
# Включить её в конфигурации OpenSSL

Если ваша версия OpenSSL 1.0.x, ГОСТ может быть уже в комплекте поставки. Нужно найти директорию с engines OpenSSL (Debian: /usr/lib/x86_64-linux-gnu/openssl*/engines или /usr/lib/x86_64-linux-gnu/engines-1.1, RHEL: /usr/lib64/openssl/engines) и посмотреть, есть ли там файл с именем «libgost.so» или «libgost_engine.so». Если есть — можно переходить к редактированию конфигурации. Если нет — нужно скачать исходные коды вашего пакета OpenSSL и включить gost в его конфигурации сборки.

Если ваша версия OpenSSL 1.1.x, нужно склонировать репозиторий https://github.com/gost-engine/engine, установить пакеты cmake и libssl-dev (Debian) или openssl-devel (RHEL), зайти в склонированную директорию и выполнить команды
<pre>
mkdir build
cd build
cmake ..
make -j4
</pre>

После чего взять libgost_engine.so из поддиректории bin клонированного репозитория и скопировать его в папку engines.

Далее отредактировать конфигурацию — добавить перед первой секцией INI-файла openssl.cnf следующий блок:

<pre>
openssl_conf = openssl_def

[openssl_def]
engines = engine_section

[engine_section]
gost = gost_section

[gost_section]
soft_load = 1
dynamic_path = /usr/lib/x86_64-linux-gnu/engines-1.1/libgost_engine.so
engine_id = gost
default_algorithms = ALL
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
</pre>

После этого всё ПО, использующее OpenSSL (в частности, nginx) сможет использовать ГОСТ в протоколе TLS.

Самоподписанный ГОСТ-сертификат можно сгенерировать так:
<pre>openssl req -days 3650 -x509 -newkey gost2001 -pkeyopt paramset:A -nodes -keyout gost_test.key -out gost_test.crt</pre>

Чтобы сконвертировать ключевой контейнер КриптоПро в нормальный ASN.1/PEM формат, нужно использовать утилиту http://svn.yourcmc.ru/vitalif/trunk/scripts/cryptopro-key-to-openssl.c?view=co (источник: https://habrahabr.ru/post/275039/)

== Установка КриптоПро на RHEL 7.2 ==

Инструкция по установке КриптоПро CSP на сервер RHEL 7.2 в nginx.

=== Установка пакетов ===

* Установить nginx >= 1.11 с официального сайта http://nginx.org/
* Установить пакет redhat-lsb-core
* Скачать дистрибутив КриптоПро CSP, например, 3.9
* Установить пакеты КриптоПро: lsb-cprocsp-base, lsb-cprocsp-capilite-64, lsb-cprocsp-kc1-64, lsb-cprocsp-kc2-64, lsb-cprocsp-pkcs11-64, lsb-cprocsp-rdr-64, cprocsp-curl-64, cprocsp-cpopenssl-64, cprocsp-cpopenssl-base, cprocsp-cpopenssl-gost, опционально: lsb-cprocsp-devel, cprocsp-cpopenssl-devel
* Убедиться, что сервис cryptsrv запущен (ps ax|grep cryptsrv), если нет — запустить (service cprocsp start), убедиться, что включён автозапуск (systemctl enable cprocsp)
* Выполнить команду <pre>/opt/cprocsp/sbin/amd64/cpconfig -ini '\config\apppath' -add string libcurl.so /usr/lib64/libcurl.so.4</pre>

=== Установка сертификата и ключа ===

Вначале устанавливаем закрытый ключ — для этого нужно взять директорию с ключами (см. [[#Формат ключа]]) и скопировать в <tt>/var/opt/cprocsp/keys/root/</tt> под именем XXXXXXXX.000 (любое имя вида «8 латинских букв, точка, 3 цифры»). «Контейнер ключа/ключей» в терминологии КриптоПро — это и есть ключ.

Далее — установка сертификата.

Если сертификат НЕ в формате X.509/PEM, его нужно сконвертировать в этот формат.

В частности, один из наших тестовых сертификатов был получен в формате PEM (кусок текста в кодировке base64), но без заголовка — в этом случае нужно добавить заголовок, то есть в начало добавить строку {{Cmd|-----BEGIN CERTIFICATE-----}}, а в конец — строку {{Cmd|-----END CERTIFICATE-----}}.

Второй вариант — сертификат может быть в бинарном формате (X509/DER, расширение обычно *.cer) — тогда его надо сконвертировать в PEM командой <pre>/opt/cprocsp/cp-openssl/bin/amd64/openssl x509 -inform der -in file.cer -out file.pem</pre>

Получив сертификат в формате PEM, нужно скопировать его в /etc/nginx/ssl-gost.pem и выполнить <pre>/opt/cprocsp/bin/amd64/certmgr -inst -file /etc/nginx/ssl-gost.pem -ask-cont</pre>

КриптоПро должно предоставить выбор ключевого контейнера, в списке должен быть 1 элемент (ключ, скопированный на предыдущем шаге). Следует ввести цифру 1 и нажать Enter, таким образом выбрав единственный вариант. Если ключ защищён паролем, будет предложено ввести пароль.

Если ключ защищён паролем (если пароль запрашивался на предыдущем шаге), пароль нужно снять — командой <pre>/opt/cprocsp/bin/amd64/csptest -passwd -container '<ИмяКонтейнера>' -change '' -passwd '<старый_пароль>'</pre>

&lt;ИмяКонтейнера&gt; взять с прошлого шага из списка.

Проверить установку сертификата можно командой {{Cmd|/opt/cprocsp/bin/amd64/certmgr -list}}. Должен быть выведен сертификат со строкой <tt>PrivateKey Link: Yes</tt> и указан ключевой контейнер — это будет означать, что сертификат установлен корректно.

=== Настройка nginx ===

Далее добавить в конфигурацию виртуального хоста nginx строки (то, что начинается с # — комментарии/пояснения, можно не добавлять):
<pre>
listen 443 ssl;
# ГОСТ сертификат
ssl_certificate /etc/nginx/ssl-gost.pem;
# "Иванов" - первое слово (без пробелов) имени сертификата (поля CN)
ssl_certificate_key engine:gost_capi:Иванов;
# RSA сертификат
ssl_certificate /etc/nginx/ssl-rsa.pem;
# RSA ключ
ssl_certificate_key /etc/nginx/ssl-rsa.key;
# шифры, приоритет ГОСТ, потом шифры семейства RSA высокой стойкости
ssl_ciphers GOST2001-GOST89-GOST89:HIGH;
ssl_prefer_server_ciphers on;
# gost_capi работает только с TLS 1.0
ssl_protocols TLSv1;
# параметры сессии
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
</pre>

Такая конфигурация говорит о том, что:
* Для клиентов, поддерживающих ГОСТ — будет использоваться ГОСТ
* Для остальных — будет использоваться RSA

Далее нужно перенаправить nginx на библиотеку OpenSSL, поставляемую с КриптоПро — для этого надо скопировать файл /usr/lib/systemd/system/nginx.service в /etc/systemd/system/nginx.service и отредактировать его, добавив в секцию [Service] строку <pre>Environment=LD_LIBRARY_PATH=/opt/cprocsp/lib/amd64:/opt/cprocsp/cp-openssl/lib/amd64</pre>

Кроме того, нужно выполнить команды:
<pre>
ln -s libcrypto.so.1.0.0 /opt/cprocsp/cp-openssl/lib/amd64/libcrypto.so.10
ln -s libssl.so.1.0.0 /opt/cprocsp/cp-openssl/lib/amd64/libssl.so.10
</pre>

А также
<pre>
touch /var/opt/cprocsp/tmp/openssl.log
chown nginx:nginx /var/opt/cprocsp/tmp/openssl.log
</pre>

После этого выполнить команду
<pre>
systemctl daemon-reload
</pre>

'''Примечание:''' так получается сделать по той причине, что и в КриптоПро, и в RHEL 7.2 используется OpenSSL 1.0.x, то есть версии совместимы. При несовместимости версий нужно будет собирать nginx из исходных кодов, следующими командами:
<pre>
./configure --user=nginx --group=nginx --prefix=/usr --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --with-http_ssl_module --with-cc-opt='-I/opt/cprocsp/cp-openssl/include/' --with-ld-opt=-L/opt/cprocsp/cp-openssl/lib/amd64/
make -j4
make install
</pre>
Однако для RHEL/CentOS 7.2 этого можно не делать.

=== Настройка SELinux и прав доступа ===

Далее, если на сервере не отключён SELinux (по умолчанию в RHEL 7.2 включён), нужно установить политику SELinux: http://svn.yourcmc.ru/vitalif/trunk/cryptopro-nginx-rhel7. Команды для установки:
<pre>
semodule -i cpro_nginx.pp
restorecon -R /var/opt
</pre>

После этого — перезапустить nginx: {{cmd|systemctl restart nginx}}.

Альтернативный путь (упрощённый): остановить nginx, если запущен ({{cmd|systemctl stop nginx}}), установить пакет policycoreutils-python и далее повторять следующие 3 команды до тех пор, пока nginx не стартует:
<pre>
systemctl start nginx
grep denied /var/log/audit/audit.log | audit2allow -a -M cryptopro-nginx
semodule -i cryptopro-nginx.pp
</pre>

=== Проверка работы ===

Для проверки нужно использовать {{cmd|openssl s_client}} на сервере.

Для проверки работы RSA: {{cmd|/usr/bin/openssl s_client -connect localhost:443}} (с помощью системной OpenSSL без поддержки ГОСТ).

Для проверки работы ГОСТ: {{cmd|/opt/cprocsp/cp-openssl/bin/amd64/openssl s_client -connect localhost:443}} (с помощью OpenSSL КриптоПро).

При условии нормальной работы TLS на экран в обоих случаях должен быть выведен сертификат сервера, детали соединения (Cipher — шифр, в первом случае вида …RSA…, во втором GOST2001-GOST89-GOST89), и openssl должен остаться включённым с приглашением ко вводу, то есть, при вводе «GET / <Enter>» должен быть выведен HTTP ответ сервера, а следующую команду должно быть можно ввести только после отправки запроса (GET /) или нажатия Ctrl-C.

Если обе проверки удаются — соединение из клиентского браузера тоже будет работать.

В случае, если первый s_client (RSA) выводит строки «no peer certificate available» и «New, (NONE), Cipher is (NONE)» — следует проверить наличие в <tt>/etc/nginx/conf.d/tms.conf</tt> строк ssl_certificate и ssl_certificate_key с RSA-сертификатом и ключом.

В случае, если первый s_client (RSA) отрабатывает и выводит приглашение ко вводу, а второй (ГОСТ) выводит детали соединения и шифр GOST2001-GOST89-GOST89, но после этого сразу выходит в терминал — следует проверить права на файл <tt>/var/opt/cprocsp/tmp/openssl.log</tt> — владельцем файла должен быть пользователь <tt>nginx</tt>, а права должны стоять 644 (см. выше команду по смене владельца chown). Несмотря на то, что КриптоПро в инструкции по установке требует запускать nginx именно под пользователем root, наличия прав доступа к <tt>openssl.log</tt> должно быть достаточно для выполнения nginx под пользователем nginx.

Если права корректны, но ГОСТ s_client всё равно сразу выходит в терминал — следует поменять {{cmd|user nginx;}} на {{cmd|user root;}} в <tt>/etc/nginx/nginx.conf</tt>, перезапустить nginx и проверить s_client ещё раз.

==== Некритичные ошибки ====

При запуске или перезапуске nginx возможны сообщения:
<pre>/usr/sbin/nginx: /opt/cprocsp/cp-openssl/lib/amd64/libssl.so.10: no version information available (required by /usr/sbin/nginx)
/usr/sbin/nginx: /opt/cprocsp/cp-openssl/lib/amd64/libcrypto.so.10: no version information available (required by /usr/sbin/nginx)</pre>

— данные ошибки некритичные, работе не мешают.

В журнале ошибок nginx /var/log/nginx/error.log возможно сообщение: <pre>[alert] ignoring stale global SSL error (SSL: error:140DD112:SSL routines:SSL_CERT_DUP:library bug) while handshaking</pre>

— это известное поведение библиотеки КриптоПро, работе не мешает.

При выполнении s_client в строке «Verify return code», в зависимости от сертификата, допустимы сообщения:

<pre>Verify return code: 21 (unable to verify the first certificate)</pre>
<pre>Verify return code: 18 (self-signed certificate)</pre>

— эти ошибки некритичные, означают лишь то, что на сервере не установлены корневые сертификаты, которыми подписаны сертификаты TLS. Но для работы сервера установка корневых сертификатов необязательна.

== Формат ключа ==

Формат ключа КриптоПро — не стандартный ASN1/PEM (<tt>-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----</tt>), а директория, содержащая файлы header.key, masks.key, masks2.key, name.key, primary.key, primary2.key.

Под Windows ключи хранятся аналогично, но в реестре, в ветке <tt>HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Crypto Pro\Settings\Users\<Пользователь>\Keys</tt> и в hex-кодировке. Для конвертации нужно выгрузить эту ветку в файл и подветки превратить в директории, а ключи с именами, аналогичными файлам выше — превратить в файлы путём перекодирования из hex в бинарный формат. Автоматически это можно сделать скриптом http://svn.yourcmc.ru/vitalif/trunk/scripts/convert-cryptopro.sh?view=co (скормив ему выгруженный файл *.reg)

Также под Windows есть поддержка экспорта сертификата и ключей в формат *.pfx. Но такие ключи потом невозможно импортировать в Linux-версию КриптоПро.

[[Категория:Разработка]]