- Введение:
- Описание docker-entrypoint
- 1 Подготовка CA
- 2. Создание клиентского закрытого ключа и запроса на сертификат (CSR)
- 3. Подпись запроса на сертификат (CSR) с помощью доверенного сертификата (CA).
- 4. Создание сертификата в формате PKCS#12 для браузера клиента
- Важное замечание по openssl
- Использование образа в работе с языками программирования
- Использованное по
- Исходные данные
- Как добавить поддержку гост 34.10 2021 в centos/redhat 7
- Как установить ssl-сертификат на nginx
- Конфиг nginx
- Криптопро | tls с гост на nginx/apache
- Настройка opensource реализации (криптоком)
- Некритичные ошибки
- Общий план работ
- Ошибки
- Поддержка гост-сертификатов в nginx
- Полезные команды и информация
- Полезные ссылки
- Примеры использования openssl gost-engine
- Проверка работы
- Сборка curl
- Сборка gost engine
- Сборка openssl
- Сборка openssl, gost-engine, curl
- Создание docker образа для связки cryptopro и nginx
- Ссылки
- Установка криптопро на rhel 7.2
- Установка сертификата и ключа
- Формат ключа
- Шаг 1. создание собственного самоподписанного доверенного сертификата.
- Шаг 2. сертификат сервера
- Заключение
Введение:
Потребовалось мне тут как-то написать небольшой API, в котором необходимо было помимо обычных запросов принимать запросы с «высокой степенью секретности».
Не я первый с этим столкнулся и мир давно уже использует для таких вещей
Поскольку на моём сервере используется nginx, то был установлен модуль SSLГугл не выдал ни одного работоспособного howto, но информация в сети есть по частям.
Итак, пошаговое руководство по настройке nginx на авторизацию клиентов через SSL-сертификаты.
Внимание! В статье для примера используются самоподписанные сертификаты!
Перед стартом создадим папку в конфиге nginx, где будут плоды наших трудов:
cd /path/to/nginx/config/
mkdir ssl && cd sslОписание docker-entrypoint
Запускаем сервис CryptoPro:
Указываем CryptoPro где находится библиотека Curl:
/opt/cprocsp/sbin/amd64/cpconfig -ini \config\apppath -add string libcurl.so /usr/lib64/libcurl.so
Перековертируем сертификат из формата X509/DER в X.509/PEM:
1 Подготовка CA
Создадим конфигnano ca.config
со следующим содержимым:
[ ca ]
default_ca = CA_CLIENT # При подписи сертификатов # использовать секцию CA_CLIENT
[ CA_CLIENT ]
dir = ./db # Каталог для служебных файлов
certs = $dir/certs # Каталог для сертификатов
new_certs_dir = $dir/newcerts # Каталог для новых сертификатов
database = $dir/index.txt # Файл с базой данных подписанных сертификатов
serial = $dir/serial # Файл содержащий серийный номер сертификата (в шестнадцатеричном формате)
certificate = ./ca.crt # Файл сертификата CA
private_key = ./ca.key # Файл закрытого ключа CA
default_days = 365 # Срок действия подписываемого сертификата
default_crl_days = 7 # Срок действия CRL
default_md = md5 # Алгоритм подписи
policy = policy_anything # Название секции с описанием политики в отношении данных сертификата
[ policy_anything ]
countryName = optional # Поля optional - не обязательны, supplied - обязательны
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = optional
emailAddress = optionalДалее надо подготовить структуру каталогов и файлов, соответствующую описанной в конфигурационном файле
2. Создание клиентского закрытого ключа и запроса на сертификат (CSR)
Для создания подписанного клиентского сертификата предварительно необходимо создать запрос на сертификат, для его последующей подписи. Аргументы команды полностью аналогичны аргументам использовавшимся при создании самоподписанного доверенного сертификата, но отсутствует параметр -x509.
3. Подпись запроса на сертификат (CSR) с помощью доверенного сертификата (CA).
При подписи запроса используются параметры заданные в файле ca.config
openssl ca -config ca.config -in client01.csr -out client01.crt -batchВ результате выполнения команды появится файл клиентского сертификата client01.crt.
Для создания следующих сертификатов нужно повторять эти два шага.
4. Создание сертификата в формате PKCS#12 для браузера клиента
Это на тот случай, если к вашему серверу подключаются не бездушные машины, как в моём случае, а живые люди через браузер.
Запароленный файл PKCS#12 надо скормить браузеру, чтобы он смог посещать ваш сайт.
openssl pkcs12 -export -in client01.crt -inkey client01.key -certfile ca.crt -out client01.p12 -passout pass:q1w2e3Важное замечание по openssl
После пары дней работы заметил, что начал при работе с сервисами (использующие SSL/TLS) ошибку вроде:
Думал где-то в коде проблема, а оказалось в другом. OpenSSL хранит некоторое количество сертификатов (корневые) и при сборке из исходников они не подтягиваются. Т.к. у нас установлен openssl в любом случае (системный), то актуальный список сертификатов у нас есть, а значит его мы можем симлинками подкинуть в нашу версию openssl. Приведу несколько команд, без комментариев. Сутя такая, что удаляем пустые папки и на их место кидаем симлинки.
Использование образа в работе с языками программирования
Если язык программирования позволяет исполнять установленные в системе программы, то задача использования ГОСТ-алгоритмов проще всего решается копированием бинарников собранных openssl и curl в конце Dockerfile языка программирования с использованием multi-stage build. Например:
FROM rnix/openssl-gost AS openssl-gost
# Replace with any other image based on Debian x86_64
FROM debian:stretch-slim
COPY --from=openssl-gost /usr/local/ssl /usr/local/ssl
COPY --from=openssl-gost /usr/local/ssl/bin/openssl /usr/bin/openssl
COPY --from=openssl-gost /usr/local/curl /usr/local/curl
COPY --from=openssl-gost /usr/local/curl/bin/curl /usr/bin/curl
COPY --from=openssl-gost /usr/local/bin/gostsum /usr/local/bin/gostsum
COPY --from=openssl-gost /usr/local/bin/gost12sum /usr/local/bin/gost12sumДаже необязательно копировать в /usr/bin, это можно сделать в любой каталог, а затем вызывать из вашей программы, передав полный путь и все аргументы.
Использованное по
Ubuntu Server 10.10 (Linux 2.6.35-22-server #35-Ubuntu SMP x86_64 GNU/Linux)
nginx 0.9.3
OpenSSL 0.9.8o 01 Jun 2021
Исходные данные
Начнем с того, что у меня было:
- 1 сервер на CentOS 7 (площадка разработки)
- 3 сервера на Redhat 7 (боевые площадки)
- OpenSSL 1.0.2k – последняя доступная версия в репозиториях Centos/Redhat 7
- PHP 7.1.33 (FPM) из репозитория Remi (в режиме MultiVersion)
- Подключены репозитории EPEL/Remi
- На Redhat серверах ограничен доступ внешним ресурсам, поэтому часть того, что на CentOS 7 была скачана wget`ом, тут была загружена с помощью копирования скаченного архива на сервер.
- В PHP была добавлена поддержка БД MySQL и PostgreSQL (MariaDB 10 и PostgreSQL 10 соответственно).
Как добавить поддержку гост 34.10 2021 в centos/redhat 7
Именно с такой задачей я столкнулся несколько дней назад на работе. Требовалось организовать поддержку ГОСТовых алгоритмов шифрования в CentOS/Redhat 7, чтобы работать с сайтом госуслуг. Сразу оговорюсь, поддержка была добавлена в OpenSSL, curl и PHP 7.1 путем сборки из исходников.
Поддержка ГОСТ алгоритмов осуществляется с помощью модуля GOST Engine, добавляемого в OpenSSL.
Инструкция является сборной солянкой из найденного в интернете и адаптирована под CentOS 7, права на оригинальные инструкции, части которых были использованы принадлежат их авторам.
Как установить ssl-сертификат на nginx
После активации сертификата вам будут доступны необходимые данные для его установки, подробнее в статье Где взять данные для установки SSL-сертификата.
Также вы можете использовать для установки сертификат, купленный в сторонней компании.
Рассмотрим, как выполняется установка и настройка Nginx SSL:
- 1.
- 2.Создайте файл your_domain.key и скопируйте в него содержание приватного ключа сертификата.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.Сохраните и закройте конфигурационный файл Nginx.
- 11.
- 12.
Готово, вы установили SSL-сертификат на Nginx.
Конфиг nginx
listen *:443;
ssl on;
ssl_certificate /path/to/nginx/ssl/server.crt;
ssl_certificate_key /path/to/nginx/ssl/server.nopass.key;
ssl_client_certificate /path/to/nginx/ssl/ca.crt;
ssl_verify_client on;
keepalive_timeout 70;
fastcgi_param SSL_VERIFIED $ssl_client_verify;
fastcgi_param SSL_CLIENT_SERIAL $ssl_client_serial;
fastcgi_param SSL_CLIENT_CERT $ssl_client_cert;
fastcgi_param SSL_DN $ssl_client_s_dn;Криптопро | tls с гост на nginx/apache
Решения nginx и Apache HTTP Server (далее — Apache) — два самых широко распространенных веб-сервера с открытым исходным кодом в мире. Каждый из них обладает собственными преимуществами, при этом одной из основных функциональных возможностей обоих серверов является построение защищенного с использованием протокола TLS соединения между клиентом и сервером с обеспечением целостности и конфиденциальности передаваемых данных, в том числе с применением российских криптографических алгоритмов ГОСТ.
Возможность использования TLS с ГОСТ обеспечивается с помощью вызова функций СКЗИ КриптоПро CSP (далее — СКЗИ):
Таким образом, СКЗИ можно эксплуатировать совместно с серверами nginx и Apache определенных версий для реализации TLS с ГОСТ без проведения исследований по оценке влияния указанных серверов на СКЗИ, что делает возможным использование данного решения для обеспечения криптографической защиты передаваемых между клиентом и сервером конфиденциальных данных (в том числе персональных данных) в соответствии с требованиями законодательства РФ по информационной безопасности. При эксплуатации иных версий nginx/Apache или СКЗИ проведение оценки влияния является обязательным во всех случаях, предусмотренных законодательством. Подробнее о работе TLS с ГОСТ можно ознакомиться в нашей статье.
Процесс установки и настройки совместной работы СКЗИ с веб-серверами nginx описан в Руководстве администратора безопасности к соответствующей версии СКЗИ. Необходимые компоненты для работы решения можно скачать в составе СКЗИ. Программное обеспечение nginx и Apache не входит в комплект поставки СКЗИ. Исходные тексты nginx необходимо скачать с официального сайта с последующей проверкой контрольной суммы, а дистрибутив Apache обычно входит в состав ОС.
По сравнению со штатным использованием серверов nginx и Apache, при реализации TLS с ГОСТ на nginx или Apache в качестве криптографического ядра вместо OpenSSL используется СКЗИ КриптоПро CSP и поэтому функциональность решения имеет некоторые особенности:
Для реализации TLS с ГОСТ на nginx или Apache необходимо приобрести годовую или бессрочную клиентскую лицензию (обязательно при реализации двухстороннего TLS с ГОСТ), специальную бессрочную серверную лицензию с поддержкой TLS и при необходимости сертификаты технической поддержки на указанные лицензии. С полным перечнем необходимых для реализации решения лицензий и сертификатов технической поддержки можно ознакомиться на нашем сайте.
В настоящее время в состав СКЗИ КриптоПро CSP версий 5.0 R2 KC1 (исполнение 1-Base) и 5.0 R2 КС2 (исполнение 2-Base) входят следующие версии компонентов решения для ОС семейства Linux:
Отдельно стоит отметить возможность реализации TLS с ГОСТ на веб-сервере Apache Tomcat, используемом для исполнения веб-приложений, написанных на Java. Для решения данной задачи можно использовать криптопровайдер КриптоПро JCP, реализующий SSL и TLS протоколы на базе российских криптографических алгоритмов ГОСТ. При этом, в случае использования КриптоПро JCP 2.0 R4, проведение оценки влияния Apache Tomcat на СКЗИ не потребуется.
В качестве альтернативы предлагаем также рассмотреть более функциональное и производительное решение — TLS-шлюз и VPN КриптоПро NGate, сертифицированный ФСБ России и позволяющий одновременно реализовать TLS с ГОСТ для большого количества веб-серверов, также без необходимости проведения оценки влияния среды функционирования.
Настройка opensource реализации (криптоком)
Самая простая в установке реализация ГОСТ — opensource. Установка сводится к 2 пунктам:
- Найти в комплекте поставки ИЛИ собрать engine «/usr/lib64/openssl/libgost.so»
- Включить её в конфигурации OpenSSL
Некритичные ошибки
При запуске или перезапуске nginx возможны сообщения:
— данные ошибки некритичные, работе не мешают.
В журнале ошибок nginx /var/log/nginx/error.log возможно сообщение:
— это известное поведение библиотеки КриптоПро, работе не мешает.
При выполнении s_client в строке «Verify return code», в зависимости от сертификата, допустимы сообщения:
— эти ошибки некритичные, означают лишь то, что на сервере не установлены корневые сертификаты, которыми подписаны сертификаты TLS. Но для работы сервера установка корневых сертификатов необязательна.
Общий план работ
- Создание резервной копии директории /etc
- Обновить ОС на сервере
- Сборка OpenSSL 1.1.х
- Сборка GOST Engine
- Сборка Curl
- Сборка PHP
- Фиксация версий
Ошибки
В случае, если первый s_client (RSA) выводит строки «no peer certificate available» и «New, (NONE), Cipher is (NONE)» — следует проверить наличие в конфигурации nginx (/etc/nginx/nginx.conf, /etc/nginx/conf.d/*.conf) строк ssl_certificate и ssl_certificate_key с RSA-сертификатом и ключом.
В случае, если первый s_client (RSA) отрабатывает и выводит приглашение ко вводу, а второй (ГОСТ) выводит детали соединения и шифр GOST2001-GOST89-GOST89, но после этого сразу выходит в терминал — следует проверить права на файл /var/opt/cprocsp/tmp/openssl.log — владельцем файла должен быть пользователь nginx, а права должны стоять 644 (см. выше команду по смене владельца chown).
Поддержка гост-сертификатов в nginx
Возможность работать из языков программирования это уже много, но хотелось еще две возможности:
Полезные команды и информация
Запуск контейнера осуществляется командой:
docker run —rm -p 443:443 -p 80:80 —name cprocsp6 —privileged —security-opt seccomp=unconfined —tmpfs /run —tmpfs /run/lock -v /sys/fs/cgroup:/sys/fs/cgroup:ro -d crypto
Полезные ссылки
Надеюсь, был кому-то полезен.
P.S. Этот пост был моей первой публикацией 16 января 2021 года, старая копия удалена (по желанию администрации сайта и потому, что она не была привязана к моему аккаунту).
Примеры использования openssl gost-engine
Не буду сильно вдаваться в подробности работы с докер-образами, лишь приведу одну команду для начала работы внутри образа:
docker run --rm -i -t rnix/openssl-gost bashДля начала можно убедиться, что алгоритмы GOST2021-GOST8912-GOST8912 и GOST2001-GOST89-GOST89 есть в списке поддерживаемых:
openssl ciphersПроверка работы
Для проверки нужно использовать openssl s_client на сервере.
Для проверки работы RSA: /usr/bin/openssl s_client -connect localhost:443 (с помощью системной OpenSSL без поддержки ГОСТ).
Для проверки работы ГОСТ: /opt/cprocsp/cp-openssl/bin/amd64/openssl s_client -connect localhost:443 (с помощью OpenSSL КриптоПро).
Сборка curl
Перейдем в директорию, где будем выполнять сборку:
Теперь загрузим нужную версию Curl. У меня заработало только с 7.59.0. Если доступ к внешним ресурсам ограничен, то загрузите архив любым доступным вам способом с именем curl-7.59.0.tar.gz
Перейдем в распакованную директорию
Сконфигурируем Curl для работы с нужной версией OpenSSL
Теперь соберем и установим Curl:
Переименуем оригинальный (системный) curl в curl_real:
Сделаем симлинк на свежесобранный curl в /usr/bin/curl
Ну и проверим версию собранного curl:
В результате вы должны получить нечто подобное:
На этом и сборку Curl мы закончили.
Теперь соберем PHP
Сборка gost engine
Перейдем в директорию, где будем осуществлять сборку:
Скачиваем архив с GOST Engine, к сожалению у меня не заработала последняя версия, поэтому загружаем архив, с которым все успешно собиралось. Если доступ к внешним ресурсам ограничен, то загрузите архив любым доступным вам способом и именем gost-engine.zip в эту же директорию.
Переходим в директорию распакованного архива
При сборке и работе могут дублироваться сообщения о том, что GOST Engine уже загружен, поэтому спрячем это сообщение сразу в исходниках:
Создадим директорию build, где будем осуществлять сборку и сразу перейдем в нее:
Сконфигурируем систему сборки:
И теперь соберем наш GOST Engine:
Выйдем в директорию bin выше уровнем
Скопируем утилиту gost12sum в директорию /usr/local/bin/
Выйдем еще выше уровнем
Скопируем собранный движок gost.so в директорию engines-1.1 openssl
Добавим конфигурацию для GOST Engine в файл конфигурации OpenSSL:
Теперь проверим, что движок GOST подключился:
В результате должен появиться список из доступных движков, где будет присутствовать gost:
Проверим список доступных шифров и найдем среди них интересующий нас GOST:
В результате вы должны получить следующий список:
Как видите, теперь OpenSSL умеет работать с ГОСТ шифрами. При генерации ключа нужный гост вызывается через -newkey gost2021_256
Сборка openssl
Для начала установим необходимые компоненты, а именно: подключим репозиторий EPEL (если не подключен), cmake3
Сборка openssl, gost-engine, curl
Сборка стороннего продукта для тех, кто делает это редко, может быть нетривиальной задачей. Для сборки OpenSSL, GOST-engine и cURL пришлось разобраться с кучей опций и перепробовать несколько комбинаций версий. Если в Dockerfile вы заметите странное, то, скорее всего, это осталось от таких экспериментов.
Я зафиксировал все версии проектов для сборки, чтобы исключить ситуацию, что из-за обновления что-то перестанет работать. Например, я собирал OpenSSL 1.1.0h GOST-engine и команда openssl ciphers не содержала GOST-алгоритмов, хотя openssl engine показывала GOST-engine в списке.
Указав предыдущую версию OpenSSL 1.1.0g, все работало, как ожидалось. Это было очень странно, я повторил это еще раз, потом пытался выяснить причины, но в итоге решил остаться на 1.1.0g.Собирая сам GOST-engine, я не сразу обратил внимание на наличие файла INSTALL.md в master-ветке, потому что собирал из ветки openssl_1_1_0 по неизвестно откуда взятой документации. Та версия собиралась с кастомной сборкой OpenSSL командой
cmake -DCMAKE_C_FLAGS='-I/usr/local/ssl/include -L/usr/local/ssl/lib' ..Создание docker образа для связки cryptopro и nginx
Вторая стадия — копирование в базовый образ nginx-gost-base всех необходимых конфигурационных файлов: копируем контейнер (по усмолчанию контейнеры CryptoPro размещаются по пути /var/opt/cprocsp/keys/. , где . имя пользователя, от которого создавался контейнер.
Ссылки
- Репозиторий со всеми решениями на GitHub
- Образ на Docker Hub с OpenSSL GOST cURL
- ГОСТ Р 34.10-2021 на Википедии со списком сертифицированных решений
- Репозиторий GOST-engine
- О возможностях и ограничениях GOST-engine
- Пример того, как решают вопрос в продакшн-окружении
Установка криптопро на rhel 7.2
Инструкция по установке КриптоПро CSP на сервер RHEL 7.2 в nginx.
Установка сертификата и ключа
Вначале устанавливаем закрытый ключ — для этого нужно взять директорию с ключами (см. #Формат ключа) и скопировать в /var/opt/cprocsp/keys/root/ под именем XXXXXXXX.000 (любое имя вида «8 латинских букв, точка, 3 цифры»). «Контейнер ключа/ключей» в терминологии КриптоПро — это и есть ключ.
Далее — установка сертификата.
Если сертификат НЕ в формате X.509/PEM, его нужно сконвертировать в этот формат.
В частности, один из наших тестовых сертификатов был получен в формате PEM (кусок текста в кодировке base64), но без заголовка — в этом случае нужно добавить заголовок, то есть в начало добавить строку —–BEGIN CERTIFICATE—–, а в конец — строку —–END CERTIFICATE—–.
Второй вариант — сертификат может быть в бинарном формате (X509/DER, расширение обычно *.cer) — тогда его надо сконвертировать в PEM командой Получив сертификат в формате PEM, нужно скопировать его в /etc/nginx/ssl-gost.pem и выполнить
КриптоПро должно предоставить выбор ключевого контейнера, в списке должен быть 1 элемент (ключ, скопированный на предыдущем шаге). Следует ввести цифру 1 и нажать Enter, таким образом выбрав единственный вариант. Если ключ защищён паролем, будет предложено ввести пароль.
Если ключ защищён паролем (если пароль запрашивался на предыдущем шаге), пароль нужно снять — командой
Проверить установку сертификата можно командой /opt/cprocsp/bin/amd64/certmgr -list. Должен быть выведен сертификат со строкой PrivateKey Link: Yes и указан ключевой контейнер — это будет означать, что сертификат установлен корректно.
Формат ключа
Формат ключа КриптоПро — не стандартный ASN1/PEM (—–BEGIN PRIVATE KEY—– . —–END PRIVATE KEY—–), а директория, содержащая файлы header.key, masks.key, masks2.key, name.key, primary.key, primary2.key.
Шаг 1. создание собственного самоподписанного доверенного сертификата.
Собственный доверенный сертификат (Certificate Authority или CA) необходим для подписи клиентских сертификатов и для их проверки при авторизации клиента веб-сервером.С помощью приведенной ниже команды создается закрытый ключ и самоподписанный сертификат.
Шаг 2. сертификат сервера
Создадим сертификат для nginx и запрос для него
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csrПодпишем сертификат нашей же собственной подписью
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crtЧтобы nginx при перезагрузке не спрашивал пароль, сделаем для него беспарольную копию сертификата
openssl rsa -in server.key -out server.nopass.keyЗаключение
Мной изучена проблема работы с ГОСТ-алгоритмами в системах Linux, предоставлено решение в виде docker-образов, все это сопровождено документацией и примерами. Решение оформлено в виде репозитория на GitHub. Стоит сказать о безопасности использования такого решения.
Главное, не стоит доверять образам на Docker Hub, даже если там написано Automated Build . Я все равно могу собрать образ с любыми правками всех используемых библиотек и систем и запушить его в свой Docker Hub под любым тегом. Поэтому рекомендую форкать репозиторий на гитхабе, пулить его себе и уже самостоятельно собирать, проверив инструкции в Dockerfile на наличие того, что используются только официальные ресурсы без подозрительных модификацией по ходу сборки.
Собирая образ самостоятельно, вы можете убедиться, что в код не попали злонамеренные правки, потому что сборка происходит только из открытого кода, который доступен для просмотра всем желающим. Тем не менее, это не гарантирует, что в нем нет ошибок и уязвимостей.
Источник
