Как создать цепочку сертификатов
Перейти к содержимому

Как создать цепочку сертификатов

  • автор:

Круг интересов

Full-stack development: Python, PostgreSQL, JavaScript, Linux, Git e t.c.

Создание валидной цепочки SSL сертификатов

Для написания тестов на валидность загружаемых сертификатов мне потребовалось создать несколько вариантов цепочек и приватных ключей. Прошерстив некоторый объем интернета, я собрал всю необходимую информацию о том, как локально сгенерировать корректную цепочку SSL сертификатов, которая будет проходить проверку стандартными средствами.

Чтобы не писать кучу команд всякий раз, напишем bash-скрипт. Для начала, зададим несколько настроечных констант:

Затем пара функций для подготовки и последующей подчистки каталога с настройками:

Все готово к созданию фальшивой, но технически корректной пары корневой сертификат / приватный ключ:

Хорошо, теперь создадим промежуточный сертификат с ключом:

Обратите внимание, что команда на создание промежуточного сертификата берет конфигурацию корневого ( $ROOT_CNF ), т.е. подписывать будем им. Также важно, чтобы срок подписываемого был меньше срока подписывающего.

Ну а теперь, собственно, итог:

Обратите внимение, что проверка осуществляется с указанием не только промежуточного, но всех CA-сертификатов, предварительно собранных в один файл ( $CHAIN_CRT ). И файл запроса, и сертификат создаются с использованием конфигурации промежуточного сертификата.

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

Строго говоря, проверка корректности уже была произведена в процессе создания. Но так как мне нужно было делать это в Python, я использовал библиотеку pyOpenSSL, а именно модуль crypto. Для примера покажу, как это можно сделать без затей:

Для X509Store можно добавить флаги проверок, которые все сломают. К примеру, если добавить вот такой флаг, то получим исключение OpenSSL.crypto.X509StoreContextError :

А все потому, что будет предпринята попытка скачать CRL-файл, указанный в дополнениях сертификата, и эта попытка провалится. Как с этим бороться, как добавить Issuer URL и т.п. — это совсем другая история, которая в принципе вся решается через конфигурацию openssl .

Sorry, you have been blocked

This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.

What can I do to resolve this?

You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.

Cloudflare Ray ID: 7a29671839c82da0 • Your IP: Click to reveal 88.135.219.175 • Performance & security by Cloudflare

Опыты с сертификатами — клиентскими и серверными

Несмотря на то, что в наше время существует letsencrypt и подобные сервисы с утилитами, которые всё делают сами, я считаю что каждый айтишник должен уметь выпускать самоподписанные сертификаты и иметь минимальное базовое понимание их работы.

К тому же, в собственной сети не так важен правильный сертификат, когда на всех клиентских устройствах можно предустановить свой доверенный корневой сертификат и подписывать им сертификаты внутренних ресурсов. Но у автора статьи просто был спортивный интерес и на досуге хотелось вникнуть в тему.

Я изучаю на досуге Java и мне потребовалось дома в локальной сети настроить тестовый полигон для mTLS аутентификации по сертификатам, это когда клиент аутентифицирует сервер, а сервер клиента.

Общение клиента с сервером mTLS

На данной схеме не рассмотрены все тонкости взаимных рукопожатий, но базовые моменты выглядят примерно так.

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

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

Цепочки подписания сертификатов

Для наших опытов будет применяться следующая цепочка подписания сертификатов.

цепочка подписания сертификатов, стрелочки и галочки это подпись

цепочка подписания сертификатов, стрелочки и галочки это подпись

HomeLabCA — это самый корневой сертификат, но конечные сертификаты (клиентские и серверные) им не подписываются, во-первых в данном эксперименте хотелось поиграться с цепочками сертификатов, во-вторых это достаточно распространенная практика — корневой центр сертификации обычно подписывает сертификаты других удостоверяющих центров, а они уже подписывают конечные сертификаты.

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

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

Для наглядного примера можно посмотреть в браузере путь сертификации у сайта habr.com

Генерация сертификатов

Предупреждение: Если такое будете повторять на проде — нужно внимательно подойти к тонким настройкам, моей целью было просто настроить несколько виртуальных машин на домашнем компе, сделать взаимодействие между сервисами с mTLS, в общем, всё только в учебных целях, организация тестового полигона для опытов, в проде, вероятно, лучше задействовать LetsEncrypt. К тому же нужно предусмотреть отзыв сертификатов.

Вернемся к первой картинке, будем выполнять всё по схеме

у нас два ЦС, один серверный и два клиентских сертификата

у нас два ЦС, один серверный и два клиентских сертификата

Структура каталогов нашего игрушечного центра сертификации:

Для всех манипуляций нам потребуется только одна утилита openssl, можно воспользоваться git bash под Windows, либо WSL, либо на виртуалке с линуксом

Я буду использовать в WSL с Debian, поэтому, корневая папка будет /mnt/d/cert

Далее зайдем в созданную папку и создам всю структуру каталогов и файлов из схемы выше

Корневой центр сертификации

Откроем файл ca_root/openssl.conf и впишем в него следующее

Дальше перейдем в папку с корневым ЦС и сгенерируем приватный ключ, у нас спросит пароль, не забывайте его, он будет требоваться для дальнейших манипуляций

Создадим самоподписанный корневой сертификат

Основываясь на нашей договоренности из первой схемы у корневого сертификата будет CommonName=HomeLabCA

Корневой сертификат готов, теперь переходим к промежуточному ЦС — HomeLabCA1

Промежуточный ЦС

Подготовим конфигурационный файл в ca1 — ca1/openssl.conf

И снова генерируем приватный ключ, только уже для промежуточного ЦС, запоминаем пароль для ключа

Дальше мы уже будем создавать подписанный сертификат, поэтому, создаем запрос на подписание сертификата, тут нам понадобится пароль от ключа priv/ca1.key

Не забываем указать cname=HomeLabCA1 по изначальной схеме на картинке выше.

Далее подписываем промежуточный сертификат корневым

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

Генерация серверного сертификата

Итак, мы находимся в папке промежуточного центра сертификации, нам нужно выпустить сертификат для сервера с адресом srv1.loc и ip-адресом 192.168.200.10.

Основной момент при генерации сертификатов для сервера — это вписать SAN, это альтернативные имена для нашего сертификата, на практике выяснилось, что браузеры не особо смотрят на cname, а ориентируются на SAN. Если вы внимательно почитали конфиг то увидели в разделе [ server_cert ] следующую строку:

Эта строчка подставляет из переменной окружения SAN значение в атрибут subjectAltName.

Первым делом, заходим в папку ca1 нашего промежуточного центра сертификации и генерируем приватный ключ, только тут упущена опция -aes256, поэтому ключ будет без пароля, это всё чтобы не вводить пароль при перезагрузке nginx

Дальше всё по аналогии, создаем запрос на подпись, указываем cname=srv1.loc

Теперь подписываем промежуточным сертификатом наш серверный srv1.loc, но предварительно заполним переменную окружения SAN

созданный сертификат в картинках

тип сертификата правильный, для проверки подлинности сервератип сертификата правильный, для проверки подлинности сервера дополнительное имя субъекта это и есть указанный SANдополнительное имя субъекта это и есть указанный SAN

Цепочки сертификатов

Цепочка сертификатов включает себя все промежуточные центры сертификации вплоть до корневого.

Каждый сертификат начинается с ——BEGIN CERTIFICATE—— и заканчивается ——END CERTIFICATE——

В данном случае полная цепочка для серверного сертификата будет выглядеть так:

Создадим сперва цепочку для промежуточного, добавив туда корневой (открытый) сертификат:

Далее создадим цепочку для серверного сертификата

 если установить по очереди корневой и промежуточные сертификаты в доверенные, то увидим путь сертификации

если установить по очереди корневой и промежуточные сертификаты в доверенные, то увидим путь сертификации

Цепочка серверного сертификата понадобится нам при настройке сервера, но это будет дальше, сейчас мы сделаем два клиентских сертификата.

Генерация клиентских сертификатов

Всё по аналогии, сперва генерируем приватный ключ, всё будем в параллели делать сразу для двух ключей

Теперь создаем запросы на подпись, не забываем указывать cname = client1 и client2 соответственно

Подписываем оба сертификата по очереди

клиентский сертификат отличается по свойствам от серверного

клиентский сертификат отличается по свойствам от серверного

Создание ключевой пары

В систему просто так не инсталлировать отдельно ключ и отдельно открытый сертификат, их нужно объединить в ключевую пару p12, создадим две ключевые пары для двух сертификатов — client1 и client2. Помните, выше мы создавали цепочку ca1_chain.crt нам она сейчас пригодится, это цепочка подписантов.

Тоже самое повторим для второго клиентского ключа

На выходе у нас будет два файла, которые можно установить в систему

указываем пароль из команды генерации ключевой парыуказываем пароль из команды генерации ключевой пары

На данном этапе у нас установлены ca.crt, ca1.crt, и два клиентских сертификата, но чтобы провести первые эксперименты, потребуется настроить тестовый сервер.

Настройка тестового сервера Nginx с TLS

Данный этап будет проходить уже на Linux-машине, я скопирую всю папку туда, соответствие файлов будет по аналогии, положу всю папку cert в /opt/ssl/

Помимо nginx я установил php-fpm, мне потребуется простейший скрипт для отладки.

Тестовый скрипт /www/index.php

Дальше проверяем конфиг и перезагружаем nginx

Открываем приватное окно в хроме или яндекс браузере, для firefox отдельная история с собственными хранилищами.

При входе на сайт у нас идет запрос сертификата, как мы помним, сервер сообщает о поддержки аутентификации и поэтому браузер запрашивает.

в скрипте видно с каким сертификатом мы пришлив скрипте видно с каким сертификатом мы пришли

С серверным сертификатом тоже всё отлично, браузеры не ругаются

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

Чтобы curl не ругался на сертификат, ему нужно указать цепочку доверенных

Далее можно указать пару ключей для авторизации по ключу и проверить с каким ключом мы пришли

сервер показывает CN сертификата с которым к нему пришлисервер показывает CN сертификата с которым к нему пришли признак аутентификации клиентапризнак аутентификации клиента

Но если указать сертификат, который подписан отличным от нашего ЦС, то приложению не будет передана информация о сертификате и X-SSL-VERIFIED будет NONE.

Можно указать не опциональную, а строгую проверку сертификатов в nginx, так, чтобы нельзя было без сертификата ничего прислать

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

А еще утилита openssl умеет отлаживать настройку серверных сертификатов, но это уже тема для отдельной статьи

если на сервере не включена клиентская аутентификация по сертификатам, то такого блока не будет

если на сервере не включена клиентская аутентификация по сертификатам, то такого блока не будет

Спасибо за внимание, если тема будет интересной, то в следующей статье постараюсь углубиться в другие тонкости сертификатов и утилиты openssl.

Как создать цепочку сертификатов

Установка SSL-сертификата является важным этапом при переходе на протокол безопасного соединения HTTPS — он обеспечивает сохранность персональных данных. Такой сайт вызывает больше доверия у пользователей. Также защищенность веб-ресурса может влиять на его позиции в поисковой выдаче.

Как правило для шифрования информации, пересылаемой между браузером посетителя и сервером, достаточно одного сертификата. Однако некоторые ресурсы требуют большей надежности и многоуровневой защиты. Например, банковский ресурс предполагает проведение крупных финансовых операций. В этом случае необходим SSL-сертификат, который содержит не только сертификат для домена, но цепочку сертификатов (CA Bundle).

Цепочка сертификатов SSL включает в себя сертификаты поручителей, подтверждающие валидность документа в целом.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *