В этой статье я расскажу о том, как я решал задачу об интеграции в тестовом режиме с сервисами, которые работают с использованием алгоритмов, определенных ГОСТ Р 34.10-2001 (устарел) и ГОСТ Р 34.10-2012. Приведу примеры некоторых проблем, с которыми столкнулся при решении задачи, дам ссылки на готовое решение и покажу несколько примеров их использования.
Причины
Для начала стоит сказать, что для продакшн-окружения существуют сертифицированные средства от компаний «Криптоком», «Крипто-Про», «Сигнал-КОМ» и других. Мне же нужно было реализовать взаимодействие в тестовом (девелоперском) окружении на Linux, покупать для этого лицензии не очень-то удобно, но что хуже, в открытом доступе отсутствуют документации по этому вопросу. По запросу «https гост» не так много решений. Среди них упоминается использование OpenSSL + Крипто CSP, я не помню деталей, но эта связка у меня не завелась с поддержкой ГОСТ Р 34.10-2012. Другим результатом, который часто встречался, было предложение использовать OpenSSL 1.0, в котором GOST-engine встроен внутрь, но такое решение тоже не содержало в себе поддержку GOST2012-GOST8912-GOST8912
.
Рабочим решением оказалась сборка OpenSSL 1.1.0g + вынесенный в отдельно подключаемый динамический движок GOST-engine. В интернете часто встречается упоминание, что некая российская компания приложила усилия по его разработке, но в самом репозитории нет сведений об авторах продукта. Пользуясь случаем, выражаю авторам благодарность за движок в open source. На этой странице сказано, что до OpenSSL 1.1.0 использовался встроенный движок GOST, сейчас для GOST используется сторонний от OpenSSL продукт. Судя по конфигурации, скорее всего, это одна и та же библиотека.
Сборка 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' ..
Но master-ветка так собираться перестала, появились ошибки об отсутствии DOPENSSL_ROOT_DIR
и подобное. В итоге решение было найдено и зафиксировано.
Для сборки cURL с кастомной сборкой OpenSSL гораздо больше документации, тем не менее, документация успевала устаревать, и с опциями пришлось много экспериментировать.
Результат работы выложен здесь.
Образ запушен в Docker Hub.
Примеры использования OpenSSL + GOST-engine
Не буду сильно вдаваться в подробности работы с докер-образами, лишь приведу одну команду для начала работы внутри образа:
docker run --rm -i -t rnix/openssl-gost bash
Для начала можно убедиться, что алгоритмы GOST2012-GOST8912-GOST8912
и GOST2001-GOST89-GOST89
есть в списке поддерживаемых:
openssl ciphers
Если вам известен хост, который работает по HTTPS на основе ГОСТ-алгоритмов, то посмотреть его сертификат и попробовать подключиться можно командой:
openssl s_client -connect gost.example.com:443 -showcerts
Создать закрытый ключ и сертификат по ГОСТ Р 34.10-2012:
openssl req -x509 -newkey gost2012_256 -pkeyopt paramset:A -nodes -keyout key.pem -out cert.pem
Подписать файл ранее созданными сертификатами:
openssl cms -sign -signer cert.pem -inkey key.pem -binary -in file.txt -nodetach -outform DER -nocerts -noattr -out signed.sgn
Извлечь содержимое подписанного файла, сертификатом, который был подписан самим собой:
openssl cms -verify -in signed.sgn -certfile cert.pem -CAfile cert.pem -inform der -out data.txt
С подписями самих сертификатов все немного сложнее. Пока мне не попался сервис, у которого сертификат выдан доверенным центром сертификации. Обычно, требуется дополнительно указывать сертификат удостоверяющего центра при работе с выданными им сертификатами. Это можно сделать глобально для системы (в образе), либо явно указывать в каждой команде.
Программа cURL в использовании не изменилась, просто поддерживает хосты с ГОСТ-сертификатами.
Использование образа в работе с языками программирования
Если язык программирования позволяет исполнять установленные в системе программы, то задача использования ГОСТ-алгоритмов проще всего решается копированием бинарников собранных 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
, это можно сделать в любой каталог, а затем вызывать из вашей программы, передав полный путь и все аргументы.
Поддержка ГОСТ-алгоритмов в PHP
PHP, конечно, позволяет делать вызовы системных команд, используя, например, exec
. Но, глядя на то, как собирается PHP-FPM в Dockerfile, мне показалось, что можно легко собрать PHP с кастомными сборками OpenSSL и cURL. Как оказалось дальше, я ошибся, что это легко. Всё равно собрал.
По какой-то причине, я начал с PHP-FPM 7.1. Идея была в том, чтобы использовать multi-stage build. Для этого надо заменить в их Dockerfile инструкцию FROM
на мою FROM rnix/openssl-gost AS openssl-gost
, затем прописать копирования собранных openssl и curl до начала сборки самого php и, наконец, указать в опции сборки путь до этих библиотек --with-openssl-dir=/usr/local/ssl
и --with-curl=/usr/local/curl
заменив оригинальные.
Сюрпризы ждали отовсюду. Одним из значительных было то, что при сборки php 7.1 используется pkg-config, а явная установка libcurl4-openssl-dev, libssl-dev прописывали в pkg-config версии из пакетов. В результате собиралось не то, что нужно. Если убрать их установку, то /configure
php падал, ссылаясь на отсутствие openssl в pkg-config. Пришлось дополнительно копировать из кастомных сборок openssl и curl их lib/pkgconfig /*
. После десятков таких сюрпризов сборка начала проходить. Дальше выяснилось, что зависимости устанавливали openssl, тем самым перезатирая ранее скопированный бинарник моей кастомной сборки. Пришлось дополнительно копировать его в самом конце. Но это не всё.
В собранном php появились алгоритмы хешей openssl_get_md_methods()
: GOST R 34.11-2012 with 256 bit hash
, GOST R 34.11-2012 with 512 bit hash
, GOST R 34.11-94
. Это значило, что php подключил GOST-engine. А вот использование расширения curl в php почему-то говорило, что таких алгоритмов не знает, соединяясь с хостом по GOST-HTTPS. Я потратил несколько часов, пытаясь найти причину этого. Я смотрел исходники, как устроено расширение curl в php, как устроен сам curl, как они связываются с openssl. Я искал место, где могут определяться поддерживаемые алгоритмы или подключатся движки. Я искал по master-веткам, много гуглил, но ничего, что решило бы сразу проблему, не нашел. Тогда я вспомнил, что я собираю не последнюю версию PHP.
Я попробовал собрать PHP-FPM 7.2. Пришлось внести некоторые правки в мой скрипт корректировки оригинального Dockerfile PHP-FPM, но сборка начала проходить без большого количества сюрпризов. Главной новостью стало то, что теперь расширение curl внутри php умело общаться по ГОСТ-алгоритмам с хостами, но была одна неприятность. Каждый вызов php писал в stdout GOST engine already loaded
. Очень неприятно. Я не сразу понял, кто это делает, но такую строчку нашел в исходниках GOST-engine. Я до сих пор не знаю, в какой части системы случилась ошибка: php, php-curl, curl, openssl. Но, видимо, в php 7.1 php-curl не подключал движок совсем, теперь в php 7.2 начал подключать его дважды. Так как все работало корректно, только был вывод, я решил его убрать правкой исходника инструкцией в Dockerfile:
sed -i 's|printf("GOST engine already loaded\\n");|goto end;|' gost_eng.c
Там строчкой ниже уже есть goto end;
, поэтому ничего серьезного я не сделал. Зато, пересобрав весь зоопарк, все начало работать, как и хотелось.
Образ с PHP-FPM + OpenSSL + GOST + cURL запушен в Docker Hub.
Поддержка ГОСТ-сертификатов в nginx
Возможность работать из языков программирования это уже много, но хотелось еще две возможности:
- Легко поднимать свой веб-сервер с ГОСТ-сертификатом по HTTPS (TLS).
- Легко проксировать все запросы на хост с ГОСТ-сертификатом
Легко – это означает докер-образ. Его нужно создать. Для этого нужно в Dockerfile собрать nginx с кастомным OpenSSL и GOST-engine. Открыв документацию сборки nginx, я увидел одну опцию о ssl — --with-http_ssl_module
, которая просто булева. Но nginx популярный продукт, инструкций по сборке с openssl много, поэтому я нашел еще опцию --with-openssl=[DIR]
. Как показала практика, nginx хочет, чтобы здесь были исходники openssl, а сборкой скрипты nginx займутся сами. Это не совсем то, что я хотел бы (я хотел использовать multi-stage build). Я ознакомился с help-выводом сборщика nginx, но ничего, что мне там помогло бы, я не нашел.
Пришлось дублировать инструкции выкачивания исходников OpenSSL, распаковки, сборки GOST-engine, включения GOST-engine в конфиги. Всё это начало собираться, но поддержки ГОСТ-алгоритмов в nginx все ещё не было. Это я проверял указанием в конфиге ssl_ciphers GOST2001-GOST89-GOST89:HIGH:MEDIUM;
. Выполнение nginx -t
говорило, что не знает этого алгоритма.
Как оказалось, openssl, собранный nginx, не поддерживал динамические движки, т.е. ./Configure
выводил no-dynamic-engine [forced]
. Здесь пришлось внимательно почитать документацию сборки OpenSSL, чтобы выяснить, что проставило forced
. Причина нашлась в аргументах сборки openssl, которые вызывал nginx, а именно no-shared
. Если это указано, то нет никаких флагов, чтобы включить поддержку загрузки движков. Пришлось править инструкцию сборки:
sed -i 's|--prefix=$ngx_prefix no-shared|--prefix=$ngx_prefix|' auto/lib/openssl/make
Всё это собралось, но nginx начал ругаться, что не может найти gost.so
по пути /usr/lib/x86_64-linux-gnu/
, это довольно странно, потому что тот же собранный openssl ищет и находит движки совсем в другом месте, а именно там, где и собирался ./lib/engines-1.1
. Добавил инструкцию копирования собранных движков в /usr/lib/x86_64-linux-gnu/
, чтобы угодить nginx. Заработало.
Рядом с основным Dockerfile в репозитории я положил демонстрационный Dockerfile, который при сборке создает себе ГОСТ-сертификаты и использует их, обрабатывая соединения на https://gost.example.com. Придется поработать с DNS или docker network, чтобы из одного контейнера попробовать подключится к этому демонстрационному, но все это я описал в документации.
Демонстрационный хост использует ключи по gost2001
, другие варианты это gost2012_256
, gost2012_512
. А вместо GOST2001-GOST89-GOST89
— GOST2012-GOST8912-GOST8912
.
Образ с nginx + GOST запушен в Docker Hub: https://hub.docker.com/r/rnix/nginx-gost/
Заключение
Мной изучена проблема работы с ГОСТ-алгоритмами в системах Linux, предоставлено решение в виде docker-образов, все это сопровождено документацией и примерами. Решение оформлено в виде репозитория на GitHub.
Стоит сказать о безопасности использования такого решения. Главное, не стоит доверять образам на Docker Hub, даже если там написано Automated Build
. Я все равно могу собрать образ с любыми правками всех используемых библиотек и систем и запушить его в свой Docker Hub под любым тегом. Поэтому рекомендую форкать репозиторий на гитхабе, пулить его себе и уже самостоятельно собирать, проверив инструкции в Dockerfile на наличие того, что используются только официальные ресурсы без подозрительных модификацией по ходу сборки.
Собирая образ самостоятельно, вы можете убедиться, что в код не попали злонамеренные правки, потому что сборка происходит только из открытого кода, который доступен для просмотра всем желающим. Тем не менее, это не гарантирует, что в нем нет ошибок и уязвимостей. Использование проприетарных сертифицированных средств так же не гарантирует отсутствие ошибок и уязвимостей, но к тому же их код от вас закрыт.
Ссылки
Комментарии (24)
andreykp
15.04.2018 15:52Для ДСТУ 4145-2002 что-то подобное никто не встречал?
gecube
15.04.2018 19:25Очень жаль, что не осилили сборку deb-пакетов с openssl и всеми компонентами. Мы таким образом делали сборку пакетов с нашим кодом, а на втором этапе сборки докер-образа разворачивали их поверх штатного образа (как правило — debian или ubuntu).
shifttstas
15.04.2018 22:38не стоит помогать использовать ГОСТ шифрование, оно не безопасно, особенно в качестве одного из шифров для https, вот когда оно войдет в официальную библиотеку — тогда пожалуйста. (никогда)
tmin10
16.04.2018 06:46Что подразумевается под официальной библиотекой? Несколько ГОСТ алгоритмов входят в OpenSSL, пруф: https://www.openssl.org/docs/man1.1.0/apps/ciphers.html
kirmorozov
16.04.2018 00:37Спасибо, что вложил усилия в прикручивание ГОСТов, может серьезно помочь с автоматизациями.
elobachev
16.04.2018 12:58Упражнение интересное, но подход странный.
Для начала отмечу, что в опенсорсной библиотеке ГОСТовый код скорее всего от вендора криптоком, линейка продуктов МагПро. Возможно ли, что какие то из опробованных вами подходов помогут в работе с сертифицированными СКЗИ? Нет. Почему? Я опишу ниже.
Зачем тогда вообще работать с ГОСТом?
Тестовое окружение? Не факт, что тестовый стенд окажется совместимым с сертифицированными скзи. Если нужен тестовый стенд для ГОСТа (ну вот не уберег Вас Господь) — гораздо разумнее получить триальные версии сертифицированных СКЗИ, все вендоры их дают, а некоторые даже позволяют скачать с сайта.
Есть нюанс — даже сертифицированные СКЗИ между собою как правило или совсем несовместимы, или совместимы с бубном. А вы что то там на опенсорсе пробуете…
Нет документации? Да полноте, есть она на все. Что нет на сайтах прямо сразу — вендоры дают по первой просьбе. У криптопры даже форум есть, там даже тем, кто первый раз в жизни make запускает рассказывают как его так запустить, что бы ngix с криптопрой собрался.
А теперь вишенка на торт… или кучу, тут уж как посмотреть. С сертифицированным средством связываются, когда нужен сертификат. На сертификате написано ( на любом, посмотрите) «безопасность информации обеспечивается при условии выполнения требований формуляра №Формуляра». А в формуляре написано, что инсталлировать СКЗИ можно только с официально полученного дистрибутива. Т.е. не с гитхаба, а с CD диска с номером экземпляра. А еще сказано(ну грубо говоря, сами почитайте )что при встраивании СКЗИ в апач или нжинкс нужно проходить проверку корректности встраивания (ну или оценку влияния прикладного ПО на функции защиты, тоже самое) по тех. заданию, согласованному с 8 центром, что примерно то же самое, что и сертификация нового СКЗИ.
Кактотак.getId Автор
16.04.2018 13:14Где требуются сертифицированные средства, там, пожалуйста, заполняем формуляр №, проходим проверки корректности, и, возможно, сертификации. Где не требуется, то решение рабочее. Некоторые вендоры не дают просто так экспортировать ключ в PEM, но решения есть: habrahabr.ru/post/317406
Видел я эти форумы. Помогите сообществу, дайте ссылку, где запускают nginx на ГОСТ-2012. Я пробовал эту, не получилось. Может кто-то сделал это в докере?elobachev
16.04.2018 14:15(из-под стола)Ээээ… Куда-куда вы ключи запихиваете?
Вопрос я ваш не совсем понял.
Что конкретно вам нужно получить?
nginx, поддерживающий серверные сертификаты, подписанные на ГОСТ Р 34.10-2012?
Или какой-то( какой тогда? ) chiper suite?
На опенсорсе? Или коммерческие решения тоже устраивают?getId Автор
16.04.2018 14:54У криптопры даже форум есть, там даже тем, кто первый раз в жизни make запускает рассказывают как его так запустить, что бы ngix с криптопрой собрался.
Я спрашивал ссылку на то самое обсуждение на форуме, где помогают собрать и запустить nginx с поддержкой сертификатов по ГОСТ Р 34.10-2012. Интересует хотя бы возможность проксирования запросов на хосты с такими сертификатами, но можно и про сам веб-сервер, поддерживающий сертификаты по ГОСТ Р 34.10-2012 своего хоста.
Как бы вы могли по-другому понять «запускают nginx на ГОСТ-2012» в контексте этой статьи?getId Автор
16.04.2018 15:24www.cryptopro.ru/forum2/default.aspx?g=posts&m=82530#post82530 вот здесь начинают говорить о ГОСТ-2012 для КриптоПРО и nginx и о такой штуке, как «gostengy». Мои поисковые системы по «gostengy» кроме этой ветки на форуме пока ничего дельного не предлагают. Оттуда же есть ссылка на github.com/deemru/nginx, документация по которому трехлетней давности.
Является ли такое решение из opensource openssl + opensource nginx + proprietary КриптоПро сертифицированным или же, как вы высказались, это еще одна куча?elobachev
16.04.2018 15:57+1Сертифицированным из этого является КриптоПро, а остальное — некое прикладное ПО, правила встраивания в которое описано в формуляре. Работать — работает, именно так, через gostengy. Подробности сборки не подскажу, т.к. мне нужно было решение, удовлетворяющее законодательству РФ, а возиться с корректностью встраивания мутно и дорого. А без корректности встраивания это нарушение требований эксплуатационной документации==использование несертифицированного СКЗИ.
Ну, тоесть ответ — нет, не является.
На основе nginx + openssl + cryptopro есть сертифицированные аппаратные решения. И на основе nginx + openssl + VipNet тоже. По сути — аппаратный реверсивный прокси с веб интерфейсом управления. Про первый могу с уверенностью сказать, что работает.
Это — да, является. Но стоит подороже и занимает минимум 1 юнит в стойке.
Если нужно дешевле и сертифицированное, и без нарушений — то нужно накатить криптопро на виндовс, а IIS настроить как реверсивный прокси на что угодно.
Про IIS в формуляре в явном виде написано, что для него корректность встраивания подтверждать ненужно.
Но нужно таки прочитать формуляр и выполнить остальные требования из серии наличия сертифицированного антивируса и т.д.
Есть еще вариант — в коробке с криптопрой лежит stunnel какой-то древней версии, собранный с поддержкой госта. На него тоже не нужно корректности встраивания, но остальные требования тоже нужно соблюдать. В некоторых случаях это помогает.
HomeDimoN
16.04.2018 16:14Обновленная инструкция…
Настройка nginx для работы с сертификатами ГОСТ 2012 года
Библиотека OpenSSL качается с update.cryptopro.ru/support/nginx-gost
Есть скрипт авто установки, но КриптоПро для linux надодостатьскачать самому…
Как прокси работает…
Решение пока никак не дружит с nGinx Plus…
Если область действия сертификата содержит пробелы — надо экранировать строку параметр в конфиге nGinx правильно (ssl_certificate_key 'engine:gostengy: Петя Петров';)…
github.com/deemru/nginx — сборки обновляются, но только под Windows :-(
SchmeL
16.04.2018 17:51Если нужен тестовый стенд для ГОСТа (ну вот не уберег Вас Господь) — гораздо разумнее получить триальные версии сертифицированных СКЗИ, все вендоры их дают, а некоторые даже позволяют скачать с сайта.
И каждые 3 месяца менять ключи. А у КриптоПРО есть еще подлянка в серверных лицензиях, пользуешь linux — в большинстве случаев покупай серверную. Разница только в цене. Функционал тот же.
А вот в каких случаях требуется именно сертифицированное средство? Допустим если получить доступ к сайту, который по госту работает…elobachev
17.04.2018 11:30В случае, если вы являетесь оператором информационной системы, обрабатывающей информацию, подлежащую защите в соответствии с законодательством РФ, и таковая информация передается вне контролируемой зоны.
Пример конкретный приведите, общими словами можно долго перекидываться.SchmeL
18.04.2018 10:40ну вот например есть сайт НБКИ, который работает по ГОСТ. Для доступа к нему необходимо сертифицированное средство, или пойдет обычный openssl + gost?
elobachev
18.04.2018 12:53НБКИ — коммерческая организация, являющаяся оператором ИСПДн, и в соответствии со ст. 7 N 218-ФЗ обеспечивает защиту информации при ее обработке, хранении и передаче сертифицированными средствами защиты в соответствии с законодательством Российской Федерации.
Таким образом, если вас связывают с НБКИ договорные отношения, в этом договоре должно быть предусмотрено обязательства для вас по защите информации.
Если НБКИ вам это не прописал, то вы никому ничего не должны и можете пользоваться обычным openssl + gost, вы ничего не нарушаете, а нарушение законодательства допустил НБКИ.
Если такие требования в договоре есть, то НБКИ закон выполнил, а вы нарушаете договор.
Нарушаете ли вы закон в этом случае ( кроме нарушения договора) зависит от того, чьи данные вы оттуда вытягиваете. Если вы физ. лицо и вытягиваете свои данные, то закон не нарушаете, только договор. Если вы физ. лицо и вытягиваете данные другого физ. лица, либо вы юр.лицо и вытягиваете данные физ. лиц, то вы нарушаете требования 152-фз и всей линейки 1119-пп, 21 приказа фстек и 378 приказа фсб.
Если вы вытягиваете данные юр.лиц, то это нарушение в области банковской, налоговоой или коммерческой тайны ( в зависимости от состава данных и обстоятельств), что бы сослаться на подзаконные акты нужно разбираться конкретнее.
HomeDimoN
16.04.2018 18:18Может кому сгодиться…
Docker контейнер с CryptoPro 4 и nginx.
КриптоПро для linux надодостатьскачать самому…
VolCh
Кто-нибудь оценивал шансы подобных сборок получить «одобрямс» для использовании в продакшене там, где требуется криптография законом или подзаконными актами?
stork_teadfort
Нулевые. Там если не «сертифицированное СКЗИ», то до свиданья. Это надо же такую крамолу предложить, бесплатно гостовую крипту раздавать! Кто её покупать за сотни денег тогда будет? :)
thatsme
Зато роскомпозор с ФСБ не обидятся, т.к. ключи у них уже есть.