Это означает, что openssl не может проверить сертификат хоста

Задаваемые 12 лет, 10 месяцев

Я пишу небольшую программу с библиотекой OpenSSL, которая должна установить соединение с сервером SSLv3. Этот сервер выдает самозаверяющий сертификат, что приводит к сбою рукопожатия с этим сообщением: «ошибка рукопожатия предупреждения sslv3, самозаверяющий сертификат в цепочке сертификатов».

Есть ли способ заставить соединение продолжить? Я пробовал вызывать SSL_CTX_set_verify так:

SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);

Но, похоже, это ничего не меняет.

c++
c
ssl
openssl
ssl-certificate

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

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

Существует 2 альтернативных способа проверить, находится ли SSL-сертификат в списках отзыва:

  • CRL (Certificate Revocation List) – проверяется наличие серийного номера сертификата в списке отзыва.
  • OCSP (Online Certificate Status Protocol) – сертификат отправляется на специализированный сервер, где проверяется его статус.

Рассмотрим оба эти способа более подробно с помощью консоли Ubuntu. А в качестве примера проверим на отзыв сертификат для домена habr.com.

Я думаю, что это более подходит для использования update-ca-certificates команда, входящая в состав ca-certificates пакет, чем dpkg-reconfigure.

В общем, я бы изменил свой полезный ответ на это:

Повторите операцию, если вам нужны другие сертификаты.

Например, если вам нужны сертификаты ЦС для ldaps/starttls с Active Directory, см. здесь как это обработать + используйте openssl для преобразования в pem/crt:

Обратите внимание, что если вы используете машины с частными доменными именами вместо законных имен общедоступных доменов, вам может потребоваться отредактировать /etc/hosts файл, чтобы иметь возможность иметь соответствующий FQDN.

Частенько приходится устанавливать сертификаты и бывают не соответствия, что бы убедится что сертификаты валидны есть openssl который в этом нам поможет.

Это означает, что openssl не может проверить сертификат хоста

Проверка pem,crt — сертификата вместе с цепочкой(если у вас несколько файлов, объедините в один, сначала идет сертификат потом цепочка)

Проверка key — приватного ключа

Проверка csr — ключ запроса сертификата

MD5 у всех должен совпадать — но для работоспособности должны быть одинаковы только у приватного ключа и сертификата, csr вам может пригодится если вы соберетесь продлевать данный сертификат.

Данная команда покажет информацию о сертификате

openssl x509 -in certificate.crt -text -noout

Проверка RSA приватного ключа

openssl rsa -in server.key -check

Посмотреть данные сертификата

openssl x509 -text < name.crt

Показать даты сертификата

openssl x509 -noout-dates < name.crt

Показать сертификат сайта

openssl s_client -proxy 192.168.103.115:3128 -connect clsv.ru:443

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

openssl req -x509 -nodes -newkey rsa:2048 -days 365 -keyout ./key.pem -out cert.pem -subj /C=/ST=/L=/O=/CN=clsv.ru

И в каталоге у вас появится Ключ — key.pem и Сертификат cert.pem и теперь можно их использовать для шифрования трафика вашего сервиса.

Сделать PFX сертификат из имеющихся

openssl pkcs12 -export -out domain.name.pfx -inkey domain.name.key -in domain.name.crt

Для проверки действительности сертификата используется команда

openssl verify СЕРТИФИКАТ

В разделе «Как создать сертификаты SSL (TLS) для сайтов» мы создали сертификат mydomain.com.crt, попробуем проверить его:

openssl verify mydomain.com.crt

C = US, ST = CA, O = «MyOrg, Inc.», CN = mydomain.com
error 20 at 0 depth lookup: unable to get local issuer certificate
error mydomain.com.crt: verification failed

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

С помощью опции -CAfile можно указать сертификат доверенного Центра Сертификации:

openssl verify -CAfile rootCA.crt mydomain.com.crt

Как можно увидеть, проверка подлинности прошла успешно:

Это означает, что openssl не может проверить сертификат хоста

Чтобы было поинтереснее, возьмём реальные сертификаты сайта и промежуточного центра сертификации:

openssl s_client -showcerts -connect w-e-b.site:443 </dev/null

Это означает, что openssl не может проверить сертификат хоста

Вы увидите сертификаты (один или несколько), найдите по полю CN сначала сертификат домена w-e-b.site:

0 s:CN = w-e-b.site

И скопируйте содержимое начиная с ——BEGIN CERTIFICATE—— и заканчивая ——END CERTIFICATE——. Затем сохраните это в файл w-e-b.site.crt.

Затем найдите сертификат центра сертификации и сохраните его в файл x3.crt:

Это означает, что openssl не может проверить сертификат хоста

Итак, для наших экспериментов у нас появилось два новых файла: w-e-b.site.crt (сертификат сайта) и x3.crt (сертификат промежуточного Центра Сертификации).

Попробуем проверить действительность сертификата сайта:

openssl verify w-e-b.site.crt

Это означает, что openssl не может проверить сертификат хоста

Поскольку сайт открывается нормально и веб браузер показывает, что с сертификатом сайта всё в порядке, то тот факт, что проверка подлинности не пройдена может показаться странным.

Проверим подлинность промежуточного сертификата организации, которая подписала сертификат сайта:

openssl verify x3.crt

Это означает, что openssl не может проверить сертификат хоста

Как можно увидеть на скриншоте, с этим сертификатом всё в порядке.

Дело в том, что команда openssl verify сверяет подпись в сертификате с коревыми Центрами Сертификации, чьи сертификаты установлены в операционной системе как доверенные. Мы можем убедиться в этом. Следующая команда покажет организацию, подписавшую сертификат x3.crt:

openssl x509 -in x3.crt -noout -issuer

issuer=O = Digital Signature Trust Co., CN = DST Root CA X3

Это означает, что openssl не может проверить сертификат хоста

Имя издателя в поле CN (Common Name) DST Root CA X3.

Убедимся, что сертификат этого CA действительно есть в системе:

Это означает, что openssl не может проверить сертификат хоста

Если мы посмотрим, кто выдал сертификат сайта w-e-b.site:

openssl x509 -in w-e-b.site.crt -noout -issuer

То увидим, что это Let’s Encrypt Authority X3.

Посмотрим имя организации в сертификате x3.crt:

openssl x509 -in x3.crt -noout -subject

Имя совпало — это также Let’s Encrypt Authority X3.

Это означает, что openssl не может проверить сертификат хоста

То есть в целом цепочка понятна — сертификат w-e-b.site.crt выдан организацией Let’s Encrypt Authority X3, а её полномочия по выдаче сертификатов заверяет DST Root CA X3, которая в операционной системе находится среди доверенных корневых Центрах Сертификации.

Чтобы автоматически выполнить проверку всей цепочки с помощью openssl verify, нам нужно указать промежуточный сертификат после опции -untrusted. Если промежуточных сертификатов несколько, то нужно указать их все — опцию -untrusted можно использовать несколько раз.

openssl verify -untrusted x3.crt w-e-b.site.crt

Это означает, что openssl не может проверить сертификат хоста

Опция -show_chain покажет информацию о цепочке сертификатов, которая была построена:

openssl verify -untrusted x3.crt -show_chain w-e-b.site.crt

Это означает, что openssl не может проверить сертификат хоста

Опции -verify_hostname ИМЯ-ХОСТА и -verify_ip IP позволяют проверить, действительно ли сертификат выдан для указанного хоста или IP адреса. Чтобы проверка прошла успешно, имя хоста должно быть в Subject Alternative Name или Common Name в subject сертификата. А IP адрес должен быть в Subject Alternative Name в subject сертификата. Пример:

openssl verify -untrusted x3.crt -verify_hostname w-e-b.site w-e-b.site.crt

Это означает, что openssl не может проверить сертификат хоста

Следующими тремя командами вы можете проверить, соответствует ли SSL сертификат приватному ключу:

Для SSL сертификата выполните команду вида:

Для приватного ключа RSA выполните команду вида:

Замените ФАЙЛ на имя ваших файлов. Для всего перечисленного выше — SSL сертификата, приватного ключа и запроса на подпись — хеш должен быть одинаковым.

Если вы искали руководство по криптографии, лежащей в основе OpenSSL, то вы оказались в правильном месте.

Это означает, что openssl не может проверить сертификат хоста

Эта статья является первой в серии из двух статей, посвященных основам криптографии, используемой в OpenSSL — библиотеке инструментов промышленного уровня, популярной и в среде Linux, и за ее пределами. (Чтобы установить самую последнюю версию OpenSSL, перейдите сюда.) Что касается взаимодействия с библиотекой, то вы можете вызывать ее функции из кода, а также в вашем распоряжении есть утилиты командной строки. Примеры кода для этой статьи приведены на C — на том же языке, на котором написана сама библиотека OpenSSL.

Читать также:  На что можно потратить земельный сертификат для многодетных в ленинградской области

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

Начнем же мы с обзора SSL, которому библиотека OpenSSL обязана своим именем (большей его части).

Краткая история

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

SSL имеет разные версии (например, SSLv2 и SSLv3), а в 1999 году на основе SSLv3 был реализован аналогичный протокол Transport Layer Security (TLS, протокол защиты транспортного уровня). TLSv1 и SSLv3 похожи, но не настолько, чтобы работать друг с другом. Тем не менее, принято называть SSL/TLS одним и тем же протоколом. Например, функции OpenSSL часто содержат SSL в имени, даже если используется TLS, а не SSL. Кроме того, вызов утилит командной строки OpenSSL начинается со строки openssl.

HTTPS-клиент

(Прим. переводчика: этот код оказался нерабочим, исправленную версию можно посмотреть здесь)

Эту программу можно скомпилировать и запустить из командной строки (обратите внимание на строчную букву L в -lssl и -lcrypto):

gcc -o client client.c -lssl -lcrypto

Эта программа пытается установить безопасное соединение с сайтом www.google.com. В рамках TLS-рукопожатия с сервером Google программа-клиент получает один или несколько цифровых сертификатов, которые она затем пытается проверить (в моей системе они проверку не проходят). Тем не менее, далее программа-клиент получает по защищенному каналу домашнюю страницу Google. Эта программа полагается на упомянутые ранее артефакты безопасности, хотя в коде можно выделить только цифровой сертификат. Остальные же артефакты пока остаются за кадром, подробнее о них мы поговорим чуть дальше.

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

const SSL_METHOD* method = TLSv1_2_client_method(); /* TLS 1.2 */

Если вызов выполнен успешно, то указатель method передается библиотечной функции, создающей контекст типа SSL_CTX:

SSL_CTX* ctx = SSL_CTX_new(method);

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

BIO* bio = BIO_new_ssl_connect(ctx);

Обратите внимание, что аргументом является наша чрезвычайно важная переменная с контекстом. Тип BIO — это обертка OpenSSL для типа FILE в C. Эта обертка защищает потоки ввода/вывода между программой-клиентом и сервером Google.

BIO_get_ssl(bio, &ssl); /* получает сессию TLS */SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* для надежности */BIO_set_conn_hostname(bio, name); /* подготовка к соединению с Google */

Само безопасное соединение устанавливается с помощью этого вызова:

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

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

Почему проверка сертификата Google не заканчивается успехом? Типичная установка OpenSSL имеет каталог /etc/ssl/certs, который включает файл ca-certificates.crt. Каталог и файл содержат цифровые сертификаты, которым OpenSSL доверяет из коробки и, соответственно, составляют хранилище доверенных сертификатов (truststore). Хранилище доверенных сертификатов можно обновлять по мере необходимости, в частности, включать новые доверенные сертификаты и удалять ненадежные.

Программа-клиент получает три сертификата от сервера Google, но хранилище доверенных сертификатов OpenSSL на моей машине не содержит точных совпадений с ними. Как я в скором времени расскажу, программа-клиент не занимается, например, проверкой цифровой подписи на сертификате Google (подпись, подтверждающая сертификат). Если этой подписи доверяют, то сертификату, содержащему ее, также следует доверять. Тем не менее клиентская программа продолжает загрузку, а затем отображение домашней страницы Google. В следующем разделе мы рассмотрим это более подробно.

Скрытые механизмы безопасности в программе-клиенте

Начнем с артефакта безопасности, который мы видим в примере с клиентом — цифрового сертификата — и рассмотрим, как другие артефакты безопасности с ним связаны. Превалирующим стандартом структуры цифрового сертификата является X509, а сертификат производственного уровня выдаются центром сертификации (CA, certificate authority), таким как Verisign.

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

Хеш-значение получается в результате сопоставления произвольного количества битов с хеш-суммой (digest) фиксированной длины. Что представляют собой биты (бухгалтерский отчет, роман или, может быть, фильм) не имеет значения. Например, хеш-алгоритм Message Digest версии 5 (MD5) отображает входные биты любой длины в 128-битное хеш-значение, тогда как алгоритм SHA1 (Secure Hash Algorithm версии 1) отображает входные биты в 160-битное значение. Различные входные биты приводят к разным — действительно, статистически уникальным — значениям хеш-функции. В следующей статье мы рассмотрим это более подробно и сосредоточимся на том, что именно делает хеш-функцию криптографической.

Цифровые сертификаты различаются по типу (например, корневой/root, промежуточный/intermediate и конечный/end-entity сертификаты) и образуют иерархию, отражающую эти типы. Как следует из названия, корневой сертификат находится на вершине иерархии, а сертификаты под ним наследуют любое доверие, которое имеет корневой сертификат. Библиотеки OpenSSL и большинство современных языков программирования имеют тип X509, как и функции, которые работают с такими сертификатами. Сертификат от Google имеет формат X509, и клиент проверяет, является ли этот сертификат X509_V_OK.

Сертификаты X509 основаны на инфраструктуре открытых ключей (PKI, public-key infrastructure), которая включает в себя алгоритмы (в основном доминирует RSA) для создания пар ключей: публичный ключ и его парный приватный ключ. Публичный ключ — это идентификационные данные (identity): публичный ключ Amazon идентифицирует его, а мой публичный ключ идентифицирует меня. Приватный ключ должен храниться его владельцем в секрете.

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

Читать также:  Что такое сертификат ветерану войны на квартиру

В первом примере Алиса открывает свой публичный ключ всему миру, включая Боба. Затем Боб шифрует сообщение с помощью публичного ключа Алисы, отправляя ей зашифрованное сообщение. Сообщение, зашифрованное публичным ключом Алисы, расшифровывается ее приватным ключом, который (по идее) есть только у нее, вот так:

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

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

Предположим, что Алиса подписывает цифровой подписью контракт, отправленный Бобу. Затем Боб может использовать публичный ключ Алисы для проверки подписи:

Невозможно подделать подпись Алисы без ее приватного ключа: следовательно, в интересах Алисы сохранить ее приватный ключ в тайне.

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

OpenSSL из командной строки

А пока давайте взглянем на инструменты командной строки OpenSSL: в частности, утилиту для проверки сертификатов с сервера во время  TLS-рукопожатия. Вызов утилит OpenSSL начинается с команды openssl а затем добавляется комбинация аргументов и флагов для указания желаемой операции.

Рассмотрим эту команду:

Результатом является список связанных алгоритмов, составляющих набор шифров (cipher suite). Ниже приведено начало списка с комментариями для разъяснения аббревиатур:

Следующая команда, используя аргумент s_client, открывает безопасное соединение с www.google.com и выводит на экран информацию об этом соединении:

openssl s_client -connect www.google.com:443 -showcerts

Такие крупные сайты как Google, как правило, отправляют несколько сертификатов для аутентификации.

Выходные данные заканчиваются сводной информацией о сессии TLS, включая сведения о наборе шифров:

В программе-клиенте используется протокол TLS1.2, а Session-ID однозначно идентифицирует соединение между утилитой openssl и сервером Google. Запись Cipher может быть проанализирована следующим образом:

  • ECDHE (протокол Диффи-Хеллмана на эллиптических кривых) — эффективный и действенный алгоритм для управления TLS-рукопожатием. В частности, ECDHE решает проблему распределения ключей, гарантируя, что обе стороны соединения (например, программа-клиент и веб-сервер Google) используют один и тот же ключ шифрования/дешифрования, известный как ключ сессии (session key). Следующая часть серии детальнее раскроет эту тему.
  • RSA (Rivest Shamir Adleman) — доминирующая криптосистема с публичным ключом, названная в честь трех ученых, впервые описавших эту систему в конце 1970-х годов. Пары ключей генерируются с помощью алгоритма RSA.
  • AES128 (Advanced Encryption Standard) — это блочный шифр, который шифрует и расшифровывает блоки битов. (Альтернативой является потоковый шифр, который шифрует и расшифровывает биты по одному.) Шифр ​​является симметричным в том смысле, что для шифрования и дешифрования используется один и тот же ключ, что в первую очередь поднимает проблему распределения ключей. AES поддерживает размеры ключей 128 (используется здесь), 192 и 256 бит: чем больше ключ, тем лучше защита.

Размеры ключей для симметричных криптосистем, таких как AES, как правило, меньше, чем для асимметричных систем (на основе пары ключей), таких как RSA. Например, 1024-битный ключ RSA относительно мал, тогда как 256-битный ключ в настоящее время является самым большим для AES.

Наборы шифров находятся в постоянном развитии. Не так давно, например, Google использовала потоковый шифр RC4 (Ron’s Cipher версии 4 в честь Рона Ривеста из RSA). В RC4 теперь онаружены уязвимости, которые предположительно частично объясняют переход Google на AES128.

Подытожим

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

Приглашаем всех желающих на открытое занятие «Встраиваем интерпретатор в приложение на C». На этом открытом уроке мы рассмотрим встраивание интерпретатора и виртуальной машины языка программирования высокого уровня в программу на C на примере скриптового языка Lua. Регистрируйтесь по ссылке.

6 ответы

По умолчанию OpenSSL проходит по цепочке сертификатов и пытается проверить на каждом этапе. SSL_set_verify() не меняет этого, см. справочную страницу. Цитирую:

Фактическая процедура проверки выполняется либо с использованием встроенной процедуры проверки, либо с использованием функции проверки, предоставленной другим приложением, установленной с помощью SSL_CTX_set_cert_verify_callback(3).

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

ответ дан 22 окт ’13, 09:10

Вы пытались предоставить своему приложению сертификат ЦС сервера, чтобы ваше приложение может проверить цепочку сертификатов?

Создан 13 фев.

Это означает, что openssl не может проверить сертификат хоста

Если вы запустите это с установкой по умолчанию, вы получите ошибку сертификата (хотя вы можете использовать флаг -i, чтобы обойти проверку сертификата).

Создан 18 фев.

Вы пытались установить SSL_set_verify?

SSL_set_verify(s, SSL_VERIFY_NONE, NULL);

Это означает, что openssl не может проверить сертификат хоста

Мой пример кода клиента (ссылке) отлично работает с самоподписанным сертификатом сервера. У меня есть приведенный ниже код после SSL_connect, и я полностью контролирую приемлемость самозаверяющих сертификатов в моем клиенте.

ответ дан 08 мая ’10, 22:05

Не тот ответ, который вы ищете? Просмотрите другие вопросы с метками

c++
c
ssl
openssl
ssl-certificate

or задайте свой вопрос.

OCSP

Выведем на экран сертификат интересующего нас домена и цепочки промежуточных (Intermediate) сертификатов:

Сохраним в файлы сертификат домена и промежуточный сертификат (код между строками ——BEGIN CERTIFICATE—— и ——END CERTIFICATE——):

openssl x509 -in /tmp/habr.com.crt -noout -ocsp_uri

Отправим запрос OCSP-серверу проверить сертификат на предмет отзыва:

Если всё указали правильно, то OCSP-сервер должен вернуть информацию по сертификату.

Здесь интерес представляют последние строчки:

Response verify OK
/tmp/habr.com.crt: good

Об отсутствии сертификата в списке отозванных говорит значение «good», если же сертификат отозвали, то значение будет «revoked».

Практика Self-signed certificate

Начнем с классики криптографии OpenSSL. Сейчас широко используется версия 1.1.1, но ее поддержка заканчивается в 2023. Следующая версия 3.0 будет поддерживаться до 2026 года. Проверка установленной версии:

OpenSSL 1.1.1k FIPS 25 Mar 2021

Если OpenSSL не установлен, то его можно установить на всех востребованных платформах.

Реализация TLS

openssl req -x509 -new -key root_ca.key -days 365 -out root_ca.crt

openssl x509 -text -in root_ca.crt

openssl req -new -key server.key -subj «/CN=xx.xx.xx.xx/CN=server/CN=server.example.com» -out server.csr

openssl req -text -in server.csr

openssl x509 -req -in server.csr -CA root_ca.crt -CAkey root_ca.key -CAcreateserial -out server.crt -days 365 -extensions SAN -extfile openssl.cnf

sudo yum groupinstall ‘Development Tools’

sudo yum install nodejs

При первом запросе возникнет ошибка:

curl: (60) SSL certificate problem: self signed certificate in certificate chain

Это значит, что самоподписанный корневой сертификат нашего CA (root_ca.crt) не находится в хранилище доверительных сертификатов. Процесс загрузки сертификатов в это хранилище специфичен для операционной системы. Приведу алгоритм для RH Linux:

Читать также:  Пароль сертификата электронной подписи где взять для физического лица для налоговой

openssl x509 -in root_ca.crt -out root_ca.pem -outform PEM

Это значит, что мы установили TLS соединение только с проверкой сертификата сервера, а не клиента. Переходим к mTLS.

Реализация mTLS

Алгоритм генерации клиентских сертификатов аналогичен серверным.

openssl req -new -key client.key -subj «/CN=xx.xx.xx.xx/CN=client/CN=client.example.com» -out client.csr

openssl x509 -req -in client.csr -CA root_ca.crt -CAkey root_ca.key -CAcreateserial -out client.crt -days 365 -extensions SAN -extfile openssl.cnf

Файл openssl.cnf — такой же как и для сервера, только вместо «server» пишем «client».

  • Копируем следующие файлы на компьютер, на котором будет работать клиент:
  • Теперь если просто вызвать curl:

curl: (35) error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure

Это значит, что мы установили mTLS соединение с проверкой сертификата как сервера, так и клиента. Теперь установим mTLS из браузера.

Реализация mTLS в браузере

Это означает, что openssl не может проверить сертификат хоста

Для загрузки в браузер клиентский сертификат и приватный ключ надо сконвертировать в формат p12. Этот формат определяется стандартом PKCS #12 и является архивом для хранения нескольких объектов. В нашем случае файл будет хранить клиентский сертификат и его приватный ключ. Понятно, что приватный ключ — это чувствительная к разглашению информация и ее владелец не должен выкладывать p12 сертификат в открытый доступ. Для конвертации тоже используем OpenSSL:

openssl pkcs12 -inkey client.key -in client.crt -export -out client.p12

Импортируем client.p12 в браузер. Для этого, например в Chrome, идем в меню: Settings / Privacy and security / Manage certificates, в открывшемся окне нажимаем Import, выбираем наш файл client.p12 и место хранения «Personal». Видим, что клиентский сертификат, выданный нашим удостоверяющим центром «My CN», появился  в хранилище персональных сертификатов:

Это означает, что openssl не может проверить сертификат хоста

Вызываем запрос заново, уже лучше, но браузер все равно пишет, что соединение не безопасно. Это из-за того, что клиентский сертификат выдан удостоверяющим центром «My CN», которого нет в списке доверительных CA (Trusted Root Certification Authorities).

Это означает, что openssl не может проверить сертификат хоста

Добавляем корневой сертификат нашего CA (root_ca.crt) в Trusted Root Certification Authorities. Делается с помощью того же вызова Import, что и для клиентского сертификата, но хранилище указываем Trusted Root Certification Authorities. Проверяем, что наш CA «My CN» появился в хранилище:

Это означает, что openssl не может проверить сертификат хоста

Это означает, что openssl не может проверить сертификат хоста

Дальнейшие вызовы проходят без запросов на подтверждение клиентского сертификата:

Это означает, что openssl не может проверить сертификат хоста

Если щелкнуть на замочке а адресной строке, то можно посмотреть сертификат сервера и убедиться, что мы взаимодействуем с правильным сервером (Issued to: server.example.com), сертификат которому выдан нашим удостоверяющим центром (Issued by: My CN) и время действия сертификата еще не прошло (Valid to: 31.05.2023):

Это означает, что openssl не может проверить сертификат хоста

Таким образом мы организовали mTLS соединение из браузера. Далее приведу для справки несколько дополнительных возможностей OpenSSL, которые могут пригодиться в процессе работы.

Дополнительные возможности OpenSSL

openssl x509 -outform der -in client.crt -out client.der

openssl x509 -inform der -in client.cer -out client.pem

Отладка с помощью OpenSSL

openssl verify -verbose -x509_strict -CAfile root_ca.pem server.crt

openssl s_server -accept 9443 -cert server.crt -key server.key

openssl s_client -connect xx.xx.xx.xx:9443 -prexit -showcerts -state -status -tlsextdebug -verify 10

  • При вызове curl параметр:-k — позволяет подсоединяться к серверу без проверки цепочки сертификатов (certificate path validation). —ssl-no-revoke  — предотвращает проверку отозванных сертификатов
  • -k — позволяет подсоединяться к серверу без проверки цепочки сертификатов (certificate path validation).
  • —ssl-no-revoke  — предотвращает проверку отозванных сертификатов

Автоматизация

Проверять SSL-сертификаты на предмет отзыва вручную не всегда удобно, поэтому процесс проверки можно автоматизировать.

Для этого берём с Github готовый скрипт ssl-check-revoc.sh, который осуществляет проверку сертификатов методом CRL:

Далее делаем скрипт исполняемым:

chmod a+x ssl-check-revoc.sh

Теперь можно проверять как уже установленные сертификаты для домена, так и сохранённые локально в файлы (опция -f):

./ssl-check-revoc.sh habr.com -v

Анонс

Схема PKI остаётся той же, только изменяются компоненты:

Это означает, что openssl не может проверить сертификат хоста

Zabbix

Скрипт ssl-check-revoc.sh может проверять сертификаты не только из консоли, он также вполне подходит в качестве чекера для Zabbix, поэтому всю грязную работу по отслеживанию попадания сертификатов в список отзыва можно поручить системе мониторинга.

Заходим в конфиг Zabbix /etc/zabbix/zabbix_server.conf и смотрим, где лежат скрипты для внешних проверок:

Копируем в этот каталог наш скрипт и рестартуем Zabbix:

sudo cp ssl-check-revoc.sh /etc/zabbix/externalscripts/
sudo systemctl restart zabbix-server

Это означает, что openssl не может проверить сертификат хоста

Также понадобятся два триггера:

Это означает, что openssl не может проверить сертификат хоста

Это означает, что openssl не может проверить сертификат хоста

Это означает, что openssl не может проверить сертификат хоста

И всё! Можно спать спокойно: если SSL-сертификат вашего домена по какой-либо причине попадёт в список отозванных, Zabbix сразу же вам сообщит.

Практика CA Smallstep

CA Smallstep — это open source CA, который можно развернуть локально для автоматического получения X.509 сертификатов. На официальном сайте есть ряд инструкций по его установке и настройке.  Для экспериментов я использовал вариант с docker:

sudo yum -y update

sudo yum install -y yum-utils

sudo yum -y install docker-ce

sudo systemctl start docker

sudo docker run hello-world

sudo docker pull smallstep/step-ca

docker run -it -v step:/home/step smallstep/step-ca step ca init

должна вернуться строка:

На этом же или другом компьютере по инструкции  устанавливаем утилиту CLI step. Краткая выжимка:

tar -xf step_linux_0.19.0_386.tar.gz

step ca health

Все готово для генерации ключей и сертификатов.

Генерация ключей и сертификатов

Также как и в случае с OpenSSL, сначала генерируем ключ и сертификат для сервера и установки TLS соединения, потом для клиента и установки mTLS.

step certificate create —csr —no-password —insecure —kty=RSA —size=2048 «xx.xx.xx.xx» server.csr server.key

step ca sign server.csr server.crt

step certificate inspect server.crt

step ca root root_ca.crt

step certificate inspect root_ca.crt

Все нормально, теперь генерируем ключ и сертификат для клиента.

step certificate create —csr —no-password —insecure —kty=RSA —size=2048 «xx.xx.xx.xx» client.csr client.key

step ca sign client.csr client.crt

step certificate inspect client.crt

  • Копируем на клиента:
  • Для проверки вызываем curl с параметрами:

Отлично — mTLS тоже работает с выданными CA Smallstep сертификатами!

Дополнительные возможности CA Smallstep

С помощью CLI step можно проверить необходимость обновления сертификата:

step certificate needs-renewal server.crt

certificate does not need renewal

step ca renew server.crt server.key

step ca revoke —cert server.crt —key server.key

step certificate inspect server.crt —bundle

STEPDEBUG=1 step /команда/

CRL

Скачаем сертификат интересующего нас домена:

Смотрим детали сертификата:

openssl x509 -noout -text -in /tmp/habr.com.crt

Здесь нас интересует в разделе «X509v3 CRL Distribution Points» пункт «Full Name».

Скачиваем по этой ссылке список CLR:

Выдираем серийный номер сертификата:

openssl x509 -in /tmp/habr.com.crt -noout -serial

Смотрим, есть ли этот номер в списке CRL:

Если ничего не нашлось, значит сертификат не является отозванным.

Заключение

В данной статье мы рассмотрели две возможности генерации ключей и сертификатов для клиента и сервера:

  • С помощью OpenSSL.
  • Используя CA Smallstep.

И двумя способами установили TLS и mTLS соединения:

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

Теперь у нас есть понимание, как организовать свою систему PKI с помощью CA любого производителя, т.к. логика взаимодействия у всех аналогичная. Более того, большинство CA используют под капотом OpenSSL, оборачивая его в свой API.

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

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