Docker-образы с поддержкой ГОСТ-сертификатов в openssl, curl, php, nginx

    В этой статье я расскажу о том, как я решал задачу об интеграции в тестовом режиме с сервисами, которые работают с использованием алгоритмов, определенных ГОСТ Р 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


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


    1. Легко поднимать свой веб-сервер с ГОСТ-сертификатом по HTTPS (TLS).
    2. Легко проксировать все запросы на хост с ГОСТ-сертификатом

    Легко – это означает докер-образ. Его нужно создать. Для этого нужно в 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-GOST89GOST2012-GOST8912-GOST8912.
    Образ с nginx + GOST запушен в Docker Hub: https://hub.docker.com/r/rnix/nginx-gost/


    Заключение


    Мной изучена проблема работы с ГОСТ-алгоритмами в системах Linux, предоставлено решение в виде docker-образов, все это сопровождено документацией и примерами. Решение оформлено в виде репозитория на GitHub.


    Стоит сказать о безопасности использования такого решения. Главное, не стоит доверять образам на Docker Hub, даже если там написано Automated Build. Я все равно могу собрать образ с любыми правками всех используемых библиотек и систем и запушить его в свой Docker Hub под любым тегом. Поэтому рекомендую форкать репозиторий на гитхабе, пулить его себе и уже самостоятельно собирать, проверив инструкции в Dockerfile на наличие того, что используются только официальные ресурсы без подозрительных модификацией по ходу сборки.


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


    Ссылки


    1. Репозиторий со всеми решениями на GitHub
    2. Образ на Docker Hub с OpenSSL + GOST + cURL
    3. ГОСТ Р 34.10-2012 на Википедии со списком сертифицированных решений
    4. Репозиторий GOST-engine
    5. О возможностях и ограничениях GOST-engine
    6. Пример того, как решают вопрос в продакшн-окружении
    Поделиться публикацией

    Похожие публикации

    Комментарии 24
      +2
      Кто-нибудь оценивал шансы подобных сборок получить «одобрямс» для использовании в продакшене там, где требуется криптография законом или подзаконными актами?
        +1
        Нулевые. Там если не «сертифицированное СКЗИ», то до свиданья. Это надо же такую крамолу предложить, бесплатно гостовую крипту раздавать! Кто её покупать за сотни денег тогда будет? :)
          0
          Зато роскомпозор с ФСБ не обидятся, т.к. ключи у них уже есть.
        0
        Для ДСТУ 4145-2002 что-то подобное никто не встречал?

          0

          Очень жаль, что не осилили сборку deb-пакетов с openssl и всеми компонентами. Мы таким образом делали сборку пакетов с нашим кодом, а на втором этапе сборки докер-образа разворачивали их поверх штатного образа (как правило — debian или ubuntu).

            0
            Посмотрите тут:
            github.com/crypto-org-ua/openssl-ua
            +1
            не стоит помогать использовать ГОСТ шифрование, оно не безопасно, особенно в качестве одного из шифров для https, вот когда оно войдет в официальную библиотеку — тогда пожалуйста. (никогда)
              +1

              Если вам не сложно, приведите пример небезопасного ГОСТ-шифрования.

                0

                Наверное отсылка к товарищу майору

                0

                Что подразумевается под официальной библиотекой? Несколько ГОСТ алгоритмов входят в OpenSSL, пруф: https://www.openssl.org/docs/man1.1.0/apps/ciphers.html

                +3

                Спасибо, что вложил усилия в прикручивание ГОСТов, может серьезно помочь с автоматизациями.

                  0
                  Упражнение интересное, но подход странный.
                  Для начала отмечу, что в опенсорсной библиотеке ГОСТовый код скорее всего от вендора криптоком, линейка продуктов МагПро. Возможно ли, что какие то из опробованных вами подходов помогут в работе с сертифицированными СКЗИ? Нет. Почему? Я опишу ниже.
                  Зачем тогда вообще работать с ГОСТом?
                  Тестовое окружение? Не факт, что тестовый стенд окажется совместимым с сертифицированными скзи. Если нужен тестовый стенд для ГОСТа (ну вот не уберег Вас Господь) — гораздо разумнее получить триальные версии сертифицированных СКЗИ, все вендоры их дают, а некоторые даже позволяют скачать с сайта.
                  Есть нюанс — даже сертифицированные СКЗИ между собою как правило или совсем несовместимы, или совместимы с бубном. А вы что то там на опенсорсе пробуете…

                  Нет документации? Да полноте, есть она на все. Что нет на сайтах прямо сразу — вендоры дают по первой просьбе. У криптопры даже форум есть, там даже тем, кто первый раз в жизни make запускает рассказывают как его так запустить, что бы ngix с криптопрой собрался.

                  А теперь вишенка на торт… или кучу, тут уж как посмотреть. С сертифицированным средством связываются, когда нужен сертификат. На сертификате написано ( на любом, посмотрите) «безопасность информации обеспечивается при условии выполнения требований формуляра №Формуляра». А в формуляре написано, что инсталлировать СКЗИ можно только с официально полученного дистрибутива. Т.е. не с гитхаба, а с CD диска с номером экземпляра. А еще сказано(ну грубо говоря, сами почитайте )что при встраивании СКЗИ в апач или нжинкс нужно проходить проверку корректности встраивания (ну или оценку влияния прикладного ПО на функции защиты, тоже самое) по тех. заданию, согласованному с 8 центром, что примерно то же самое, что и сертификация нового СКЗИ.
                  Кактотак.
                    0
                    Где требуются сертифицированные средства, там, пожалуйста, заполняем формуляр №, проходим проверки корректности, и, возможно, сертификации. Где не требуется, то решение рабочее. Некоторые вендоры не дают просто так экспортировать ключ в PEM, но решения есть: habrahabr.ru/post/317406

                    Видел я эти форумы. Помогите сообществу, дайте ссылку, где запускают nginx на ГОСТ-2012. Я пробовал эту, не получилось. Может кто-то сделал это в докере?
                      –1
                      (из-под стола)Ээээ… Куда-куда вы ключи запихиваете?

                      Вопрос я ваш не совсем понял.
                      Что конкретно вам нужно получить?
                      nginx, поддерживающий серверные сертификаты, подписанные на ГОСТ Р 34.10-2012?
                      Или какой-то( какой тогда? ) chiper suite?
                      На опенсорсе? Или коммерческие решения тоже устраивают?
                        0
                        У криптопры даже форум есть, там даже тем, кто первый раз в жизни make запускает рассказывают как его так запустить, что бы ngix с криптопрой собрался.

                        Я спрашивал ссылку на то самое обсуждение на форуме, где помогают собрать и запустить nginx с поддержкой сертификатов по ГОСТ Р 34.10-2012. Интересует хотя бы возможность проксирования запросов на хосты с такими сертификатами, но можно и про сам веб-сервер, поддерживающий сертификаты по ГОСТ Р 34.10-2012 своего хоста.

                        Как бы вы могли по-другому понять «запускают nginx на ГОСТ-2012» в контексте этой статьи?
                          0
                          www.cryptopro.ru/forum2/default.aspx?g=posts&m=82530#post82530 вот здесь начинают говорить о ГОСТ-2012 для КриптоПРО и nginx и о такой штуке, как «gostengy». Мои поисковые системы по «gostengy» кроме этой ветки на форуме пока ничего дельного не предлагают. Оттуда же есть ссылка на github.com/deemru/nginx, документация по которому трехлетней давности.

                          Является ли такое решение из opensource openssl + opensource nginx + proprietary КриптоПро сертифицированным или же, как вы высказались, это еще одна куча?
                            +1
                            Сертифицированным из этого является КриптоПро, а остальное — некое прикладное ПО, правила встраивания в которое описано в формуляре. Работать — работает, именно так, через gostengy. Подробности сборки не подскажу, т.к. мне нужно было решение, удовлетворяющее законодательству РФ, а возиться с корректностью встраивания мутно и дорого. А без корректности встраивания это нарушение требований эксплуатационной документации==использование несертифицированного СКЗИ.

                            Ну, тоесть ответ — нет, не является.

                            На основе nginx + openssl + cryptopro есть сертифицированные аппаратные решения. И на основе nginx + openssl + VipNet тоже. По сути — аппаратный реверсивный прокси с веб интерфейсом управления. Про первый могу с уверенностью сказать, что работает.
                            Это — да, является. Но стоит подороже и занимает минимум 1 юнит в стойке.

                            Если нужно дешевле и сертифицированное, и без нарушений — то нужно накатить криптопро на виндовс, а IIS настроить как реверсивный прокси на что угодно.
                            Про IIS в формуляре в явном виде написано, что для него корректность встраивания подтверждать ненужно.
                            Но нужно таки прочитать формуляр и выполнить остальные требования из серии наличия сертифицированного антивируса и т.д.

                            Есть еще вариант — в коробке с криптопрой лежит stunnel какой-то древней версии, собранный с поддержкой госта. На него тоже не нужно корректности встраивания, но остальные требования тоже нужно соблюдать. В некоторых случаях это помогает.
                              0
                              Обновленная инструкция…
                              Настройка nginx для работы с сертификатами ГОСТ 2012 года
                              Библиотека OpenSSL качается с update.cryptopro.ru/support/nginx-gost
                              Есть скрипт авто установки, но КриптоПро для linux надо достать скачать самому…

                              Как прокси работает…
                              Решение пока никак не дружит с nGinx Plus…
                              Если область действия сертификата содержит пробелы — надо экранировать строку параметр в конфиге nGinx правильно (ssl_certificate_key 'engine:gostengy: Петя Петров';)…

                              github.com/deemru/nginx — сборки обновляются, но только под Windows :-(

                        0
                        Если нужен тестовый стенд для ГОСТа (ну вот не уберег Вас Господь) — гораздо разумнее получить триальные версии сертифицированных СКЗИ, все вендоры их дают, а некоторые даже позволяют скачать с сайта.

                        И каждые 3 месяца менять ключи. А у КриптоПРО есть еще подлянка в серверных лицензиях, пользуешь linux — в большинстве случаев покупай серверную. Разница только в цене. Функционал тот же.

                        А вот в каких случаях требуется именно сертифицированное средство? Допустим если получить доступ к сайту, который по госту работает…
                          0
                          В случае, если вы являетесь оператором информационной системы, обрабатывающей информацию, подлежащую защите в соответствии с законодательством РФ, и таковая информация передается вне контролируемой зоны.

                          Пример конкретный приведите, общими словами можно долго перекидываться.
                            0
                            ну вот например есть сайт НБКИ, который работает по ГОСТ. Для доступа к нему необходимо сертифицированное средство, или пойдет обычный openssl + gost?
                              0
                              НБКИ — коммерческая организация, являющаяся оператором ИСПДн, и в соответствии со ст. 7 N 218-ФЗ обеспечивает защиту информации при ее обработке, хранении и передаче сертифицированными средствами защиты в соответствии с законодательством Российской Федерации.

                              Таким образом, если вас связывают с НБКИ договорные отношения, в этом договоре должно быть предусмотрено обязательства для вас по защите информации.
                              Если НБКИ вам это не прописал, то вы никому ничего не должны и можете пользоваться обычным openssl + gost, вы ничего не нарушаете, а нарушение законодательства допустил НБКИ.

                              Если такие требования в договоре есть, то НБКИ закон выполнил, а вы нарушаете договор.

                              Нарушаете ли вы закон в этом случае ( кроме нарушения договора) зависит от того, чьи данные вы оттуда вытягиваете. Если вы физ. лицо и вытягиваете свои данные, то закон не нарушаете, только договор. Если вы физ. лицо и вытягиваете данные другого физ. лица, либо вы юр.лицо и вытягиваете данные физ. лиц, то вы нарушаете требования 152-фз и всей линейки 1119-пп, 21 приказа фстек и 378 приказа фсб.
                              Если вы вытягиваете данные юр.лиц, то это нарушение в области банковской, налоговоой или коммерческой тайны ( в зависимости от состава данных и обстоятельств), что бы сослаться на подзаконные акты нужно разбираться конкретнее.
                        0

                        Вангую, что ГОСТ сделал нам Pastafarianist

                          0
                          Может кому сгодиться…
                          Docker контейнер с CryptoPro 4 и nginx.
                          КриптоПро для linux надо достать скачать самому…

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                          Самое читаемое