SSL stapling позволяет сэкономить для нового посетителя сайта 0,1-1 секунду (за счет экономии 1-2 запросов за промежуточными сертификатами с учетом DNS-запросов, установления соединения и получения данных, каждый из запросов может выполняться до 500 мс в случае 95 перцентиля пользователей). По умолчанию, SSL stapling выполняется для всех сертификатов, загруженных в Айри.
Обычно цепочка SSL-сертификатов, которую должен запросить браузер, выглядит следующим образом:
SSL-сертификат сайта — Промежуточный SSL-сертификат [- Промежуточный SSL-сертификат 2] — Корневой SSL-сертификат
Корневые SSL-сертификаты загружены в браузер (в целях избежания их подделки при передачи по сети). Промежуточные SSL-сертификаты могут быть получены из SSL-сертификата сайта («родительский» сертификат, которым подписан данный сертификат, внесен в соответствующем поле данного сертификата). Как это корректно сделать, чтобы сшить все сертификаты и ускорить загрузку сайта в браузере?
Openssl
Основным рабочим инструментом будет библиотека openssl: она позволяет реализовать преобразование сертификатов и извлечение необходимой информации в текстовом формате (в сертификате информация закодирована либо в бинарном формате (DER), либо в base64 (PEM)).
Если на сервере вы подключаете SSL-шифрование для сайта, то сама библиотека, скорее всего, у вас уже установлена. Проверить, например, для какого домена (Canonical name) выпущен сертификат (если он в PEM формате, обычно в таком формате сертификаты выпускаются и передаются для установки на сервер) можно так:
openssl x509 -in ФАЙЛ_СЕРТИФИКАТА -subject -noout
Здесь
x509
— входящий формат сертификата, in
— ключ для входного файла, subject
— указание вывести CN сертификата, а noout
— запрет на вывод самого сертификата (в PEM формате).Получаем «родительский» сертификат
Алгоритм «сшивки» сертификатов достаточно простой: нам нужно из сертификата извлечь путь к «родительскому» сертификату (тому сертификату, которым подписанный данный) и получить этот «родительский» сертификат по извлеченному пути. Простого набора ключей для
openssl
найти не удалось, поэтому сделаем это с помощью вывода всей информации о сертификате в тестовом формате с помощью ключа text
:openssl x509 -in "ФАЙЛ_СЕРТИФИКАТА" -text -noout
После этого нам нужно лишь выделить поле Issuers и получить из него URL. Это можно сделать, например, так:
openssl x509 -in "ФАЙЛ_СЕРТИФИКАТА" -text -noout | grep Issuers | awk '{sub(/.*http/,"http");print $0}'
Получив URL сертификата, скачиваем его любым удобным образом. Например, через curl:
curl --user-agent "Mozilla/5.0 (compatible; Airee-Speedup/1.0; +http://airee.ru/robots)" $issuer -o /tmp/stapling.crt 2>/dev/null
Запускаем рекурсию
Описанную выше процедуру можно выполнять в цикле, пока из сертификата извлекается путь к «родительскому». Но есть один нюанс. Подписывающие сертификаты удостоверяющих центров обычно хранятся в бинарном формате, поэтому нам нужно будет проверить формат сертификата и преобразовать его к текстовому (чтобы корректно включить в финальную цепочку сертификатов, которая будет записана в PEM формате).
Для проверки формата сертификата воспользуемся
verify
от openssl:openssl verify /tmp/stapling.crt 2>&1 | grep "unable to load")
В случае возникновения ошибки чтения загруженного сертификата нам нужно будет его преобразовать из бинарного формата в base64:
openssl x509 -inform der -in /tmp/stapling.crt -out /tmp/stapling.crt
После преобразования сертификата мы можем спокойной скопировать его в конец нашей цепочки, определить путь к «родительскому» сертификату и продолжить составление цепочки (если требуется).
Правильный порядок сертификатов в цепочке
В финале должен получиться файл с цепочкой сертификатов следующего содержания:
-----BEGIN CERTIFICATE----- сертификат сайта в формате base64 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- промежуточный сертификат в формате base64 -----END CERTIFICATE----- [-----BEGIN CERTIFICATE----- возможно, еще один промежуточный сертификат -----END CERTIFICATE-----] -----BEGIN CERTIFICATE----- корневой сертификат в формате base64 -----END CERTIFICATE-----
Браузерам сам корневой сертификат в цепочке не требуется: он у них уже есть. Но он требуется для верификации цепочки самому nginx с включенной настройкой
ssl_stapling
.Итог
Для составления цепочки сертификатов из данного требуются следующие действия:
1. Скопировать данный сертификат в начало цепочки (cat).
2. Получить URL «родительского» сертификата (openssl + awk / sed).
3. Загрузить «родительский» сертификат (curl / wget).
4. Переформатировать «родительский» сертификат (openssl).
5. Скопировать «родительский» сертификат в цепочку (cat).
6. Повторить шаги 2-5 или завершить.
Комментарии (29)
welcomerooot
09.01.2017 16:44+1Установка SSL-сертификата на сайт требует достаточно сложной технической настройки веб-сервера (nginx, например).
Ну, такое.
Erelecano
09.01.2017 17:41> Установка SSL-сертификата на сайт требует достаточно сложной технической настройки веб-сервера (nginx, например).
Для настройки на nginx'е нового домена с честным ssl-сертификатом от LE и с A+ рейтингом по ssllabs.com у меня уходит в районе 5 минут(из которых минуту оно сертификат получает). Кажется у вас что-то идет не так, если это — сложная техническая настройка.sunnybear
09.01.2017 19:07+2Ту конфигурацию, которую выкладываете за 5 минут, скорее всего, вы собирали несколько часов или даже дней в первый раз. Речь об этом.
Но вы можете выложить вашу конфигурацию nginx относительно ssl — тогда будет понятно, есть ли в ней недоработки или ошибки. Особенно, в части поддерживаемых шифров и обратной совместимости.Erelecano
09.01.2017 19:14Понимаете какая штука. Мне нет нужды выкладывать что-то и доказывать кому-то.
https://www.ssllabs.com/ssltest/analyze.html?d=lindon.pw&latest
A+
https://www.ssllabs.com/ssltest/analyze.html?d=ip.lindon.pw&latest
A+
Да, при этом у меня целенаправлено отключены TLSv1 и TLSv1.1, то есть то, что вы видите, что старые ОС туда не могут зайти это не ошибка конфигурирования, на личных проектах я использую такой вариант, потому что некрофилам ко мне ходить незачем.
Ваши же пляски с cat'ом не тянут на статью. А уж гордая подпись «Технический директор» намекает нам неиллюзорно, что технический директор вы разве что у своего локалхоста и фирмы «Рога и копыта».
Не нужны пляски с кэтом, а тем кому нужны не нужны статьи уровня «Я у мамы какир».
Либо ЦА хабра изменилась настолько, что здесь теперь только полные идиоты, либо вы промахнулись ресурсом для размещения свой бесполезной статьи.
Suvitruf
09.01.2017 19:17-1А там что-то сложное?
Я всегда такое использую:
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers "RC4:HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; ssl_prefer_server_ciphers on;
И, судя по geotrust ssl checker, там всё вполне неплохо.
Или я что-то упускаю?sunnybear
09.01.2017 19:19+1SSLv3 признан небезопасным почти год назад
https://access.redhat.com/articles/1232123Suvitruf
09.01.2017 19:25Правда
Exploiting this vulnerability is not easily accomplished
Я в этих штуках не особо разбираюсь, но мы эти сервера используем только для API сервисов, никакого доступа из браузера. Стоит ли нам беспокоиться по поводу этой уязвимости?sunnybear
09.01.2017 19:28+1Потенциальная дыра. Т.е. те, кто захотят вас взломать, будут иметь на руках преимущество. Беспокоиться или нет — вам решать.
В настройке SSL очень много нюансов. Есть множество статей, как правильно настроить SSL для nginx, но каждая из них упускает какой-то момент из виду: где-то не хватает сшивки, где-то шифров, где-то эллиптического шифрования. И т.д.
mxms
09.01.2017 22:58Действительно, автор преувеличил. Получение SSL сертификата и его настройка на веб-сервере занимает никак не 5 минут, а всего 2. Это потому, что помимо Let's Encrypt есть ещё и Mozilla SSL Configuration Generator.
varnav
10.01.2017 12:41+1Он не идеален. Например, он зачем то выдаёт параметр длины DH в конфигурациях modern, где DH не используется по определению.
mxms
10.01.2017 15:28Well, nobody's perfect
Erelecano
10.01.2017 19:415 минут это с момента, как я решаю «А мне нужен еще один домен который будет что-то отдавать» и до момента, как я запускаю ssllabs на тестирование обычно(я засекал время). То есть это зайти на сервер, скопировать шаблонный конфиг nginx'а для домена, исправить пути, сделать nginx -t, потом сделать ему reload, получить сертификат и включить ssl для домена.
Да, как правильно заметили мозилловский конфигуратор дает несколько странную конфигурацию, потому я использую собственные конфиги, которые инклюдятся во все конфиги для доменов у меня.
varnav
10.01.2017 11:59+2Чтобы уходило 5 минут на настройку, надо несколько недель а то и месяцев потратить на изучение многочисленных тонкостей TLS/SSL/HTTPS и особенности правильных настроек под него.
ValdikSS
09.01.2017 23:29+2Вы путаете понятия Stapling и Chaining. То, что вы описываете — Chaining, а Stapling (и директива
ssl_stapling
nginx) — передача клиенту подписанного OSCP-ответа с сервера владельца корневого сертификата, чтобы клиенту не пришлось самостоятельно к нему обращаться.sunnybear
10.01.2017 00:10вполне возможно. Но Stapling невозможен без chaining?
ValdikSS
10.01.2017 00:14Технически возможен. Но все популярные центры сертификации и так отдают full chain, а если и не отдают, то дают архив со всеми сертификатами в цепочке, и их не нужно качать вручную. Проблема, скорее, надумана, нежели реальна.
sunnybear
10.01.2017 00:17У нас примерно 10% сертификатов приходят одиночными. При наших объемах это актуальная проблема автоматизации: чтобы не из архива доставать или вручную определять, а через сертификат актуальную цепочку получать. Возможно, есть и другие пути автоматизации.
simpleadmin
10.01.2017 10:10+1Проблема, скорее, надумана, нежели реальна.
На хостинг- cdn- сервисах одиночных (или с цепочкой от другого удостоверяющего центра) приходит порядка половины. К сожалению знаю не по наслышке.
$cat issuers.sh#!/usr/local/bin/bash cmd_grep='/usr/bin/grep ' cmd_openssl='/usr/bin/openssl ' cmd_cut='/usr/bin/cut ' cmd_fetch='/usr/bin/fetch ' tmp_der='tmp.der' tmp_cert='tmp.cert' #------------------------------------------------------------------------------ usage () { #printf "function ${FUNCNAME}\n" printf "Error!\nUsage:\t\"$0 certificate.pem\"\n" exit 1 } #------------------------------------------------------------------------------ if [ "X$1" = "X" ] then usage else cp $1 $tmp_cert chain_cert="chain.pem" fi i=0 while : do issuer=`$cmd_openssl x509 -in $tmp_cert -noout -text | $cmd_grep 'CA Issuers' | $cmd_cut -d : -f 2,3` if [ "X$issuer" != "X" ] then echo $i echo $issuer tmp_pem=$1$i.pem $cmd_fetch $issuer --output=$tmp_der is_pem=`$cmd_grep -c CERTIFICATE $tmp_der` printf "IS PEM:\t[$is_pem]\n" #echo "$tmp_der -> $tmp_pem" if [ $is_pem -ne 0 ] then echo "PEM($tmp_der) -> PEM($tmp_pem)" cp -f $tmp_der $tmp_pem else echo "DER($tmp_der) -> PEM($tmp_pem)" echo "$cmd_openssl x509 -inform der -in $tmp_der -out $tmp_pem" $cmd_openssl x509 -inform der -in $tmp_der -out $tmp_pem fi cp $tmp_pem $tmp_cert let "i+=1" #sleep 2 else break fi done if [ $i -gt 0 ] then echo "cat ./$1* > $chain_cert" cat ./$1* > $chain_cert printf "Certificate chain:\n" ls -l $chain_cert #ls | grep -Ev ^ya.pem$ | xargs rm fi
motienko
10.01.2017 11:08кстати, 'CA Issuers' может быть не только в x509 der или pem формате, а еще pkcs7, например, у того же letsencrypt
Получить в PEM так:
wget http://apps.identrust.com/roots/dstrootcax3.p7c openssl pkcs7 -inform der -in dstrootcax3.p7c -print_certs -out dstrootcax3.pem
motienko
10.01.2017 11:14+1тогда надо в скрипт добавить несколько строк
else echo "DER($tmp_der) -> PEM($tmp_pem)" echo "$cmd_openssl x509 -inform der -in $tmp_der -out $tmp_pem" $cmd_openssl x509 -inform der -in $tmp_der -out $tmp_pem if [ $? -ne 0 ] then echo "May be PKCS7" echo "PKCS7 DER($tmp_der) -> PEM($tmp_pem)" echo "$cmd_openssl pkcs7 -inform der -in $tmp_der -print_certs -out $tmp_pem" $cmd_openssl pkcs7 -inform der -in $tmp_der -print_certs -out $tmp_pem fi fi cp $tmp_pem $tmp_cert let "i+=1"
simpleadmin
10.01.2017 11:36так PKS7 и есть DER-контейнер содержащий один или несколько сертификатов (без ключа в отличии от PKS12), и, конечно, в этих сертификатах может присутствовать расширение Authority Information Access и как следствие блок CA Issuers
chaturanga
10.01.2017 09:36+3Чейнинг с автоматизированным скриптом на bash — https://habrahabr.ru/post/304458/
varnav
10.01.2017 11:56У меня stapling работает и без корневого, зато если корневой присутствует, то тест от SSL labs ругается на contains anchor.
kolu4iy
… но если вдруг вы решили не тратиться на EV-сертификат, то старый добрый дядюшка startssl кроме выдачи бесплатного сертификата, заботливо выгрузит вам всю цепочку в архиве, причем в видах пригодных для различных веб-серверов. Вам остаётся только подставить эту цепочку.
Erelecano
Это тот startssl который выкинут из доверенных за мошенничество?
Спасибо, нет.
xvitaly
Сертификаты, выданные удостоверяющим центром StartSSL, уже очень скоро лишатся доверия во всех популярных веб-браузерах.
kolu4iy
Эм… Не проблема. Letsencrypt генерирует fullchain.pem, который точно также не требует сшивания…