Сшиваем SSL-сертификаты правильно на bash
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 или завершить.
Комментарии (17)
9 января 2017 в 16:26
0↑
↓
…, но если вдруг вы решили не тратиться на EV-сертификат, то старый добрый дядюшка startssl кроме выдачи бесплатного сертификата, заботливо выгрузит вам всю цепочку в архиве, причем в видах пригодных для различных веб-серверов. Вам остаётся только подставить эту цепочку.9 января 2017 в 16:42
+3↑
↓
Это тот startssl который выкинут из доверенных за мошенничество?
Спасибо, нет.9 января 2017 в 16:47
0↑
↓
Сертификаты, выданные удостоверяющим центром StartSSL, уже очень скоро лишатся доверия во всех популярных веб-браузерах.9 января 2017 в 17:56
0↑
↓
Эм… Не проблема. Letsencrypt генерирует fullchain.pem, который точно также не требует сшивания…
9 января 2017 в 16:44
0↑
↓
Установка SSL-сертификата на сайт требует достаточно сложной технической настройки веб-сервера (nginx, например).
Ну, такое.9 января 2017 в 17:41
0↑
↓
> Установка SSL-сертификата на сайт требует достаточно сложной технической настройки веб-сервера (nginx, например).Для настройки на nginx’е нового домена с честным ssl-сертификатом от LE и с A+ рейтингом по ssllabs.com у меня уходит в районе 5 минут (из которых минуту оно сертификат получает). Кажется у вас что-то идет не так, если это — сложная техническая настройка.
9 января 2017 в 19:07
+1↑
↓
Ту конфигурацию, которую выкладываете за 5 минут, скорее всего, вы собирали несколько часов или даже дней в первый раз. Речь об этом.
Но вы можете выложить вашу конфигурацию nginx относительно ssl — тогда будет понятно, есть ли в ней недоработки или ошибки. Особенно, в части поддерживаемых шифров и обратной совместимости.9 января 2017 в 19:14
0↑
↓
Понимаете какая штука. Мне нет нужды выкладывать что-то и доказывать кому-то.
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’ом не тянут на статью. А уж гордая подпись «Технический директор» намекает нам неиллюзорно, что технический директор вы разве что у своего локалхоста и фирмы «Рога и копыта».
Не нужны пляски с кэтом, а тем кому нужны не нужны статьи уровня «Я у мамы какир».
Либо ЦА хабра изменилась настолько, что здесь теперь только полные идиоты, либо вы промахнулись ресурсом для размещения свой бесполезной статьи.9 января 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, там всё вполне неплохо.
Или я что-то упускаю?
9 января 2017 в 19:19 (комментарий был изменён)
0↑
↓
SSLv3 признан небезопасным почти год назад
https://access.redhat.com/articles/12321239 января 2017 в 19:25
0↑
↓
ПравдаExploiting this vulnerability is not easily accomplished
Я в этих штуках не особо разбираюсь, но мы эти сервера используем только для API сервисов, никакого доступа из браузера. Стоит ли нам беспокоиться по поводу этой уязвимости?9 января 2017 в 19:28 (комментарий был изменён)
+1↑
↓
Потенциальная дыра. Т.е. те, кто захотят вас взломать, будут иметь на руках преимущество. Беспокоиться или нет — вам решать.В настройке SSL очень много нюансов. Есть множество статей, как правильно настроить SSL для nginx, но каждая из них упускает какой-то момент из виду: где-то не хватает сшивки, где-то шифров, где-то эллиптического шифрования. И т.д.
9 января 2017 в 22:58 (комментарий был изменён)
0↑
↓
Действительно, автор преувеличил. Получение SSL сертификата и его настройка на веб-сервере занимает никак не 5 минут, а всего 2. Это потому, что помимо Let’s Encrypt есть ещё и Mozilla SSL Configuration Generator.
9 января 2017 в 23:29
+1↑
↓
Вы путаете понятия Stapling и Chaining. То, что вы описываете — Chaining, а Stapling (и директиваssl_stapling
nginx) — передача клиенту подписанного OSCP-ответа с сервера владельца корневого сертификата, чтобы клиенту не пришлось самостоятельно к нему обращаться.10 января 2017 в 00:10
0↑
↓
вполне возможно. Но Stapling невозможен без chaining?10 января 2017 в 00:14
0↑
↓
Технически возможен. Но все популярные центры сертификации и так отдают full chain, а если и не отдают, то дают архив со всеми сертификатами в цепочке, и их не нужно качать вручную. Проблема, скорее, надумана, нежели реальна.10 января 2017 в 00:17
0↑
↓
У нас примерно 10% сертификатов приходят одиночными. При наших объемах это актуальная проблема автоматизации: чтобы не из архива доставать или вручную определять, а через сертификат актуальную цепочку получать. Возможно, есть и другие пути автоматизации.