Almost Over

Тонкая настройка SSL

Тонкая настройка SSL

$DOMAIN — основной домен сайта (например, almostover.ru).
$SUB.DOMAIN — поддомен сайта (например, cdn.almostover.ru).

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

В данном руководстве постараюсь описать наиболее интересные и сложные SSL-опции, а также попытаюсь максимально практично настроить их.

OCSP Stapling

Online Certificate Status Protocol (OCSP) Stapling даёт возможность Вашему серверу кэшировать ответы из ЦА, выдавшего сертификат. При инициации SSL/TLS-подтверждения на Ваш сервер, возвращается ответ от сервера к клиенту с прикреплённым закэшированным OCSP-ответом в сообщении CertificateStatus. Для использования OCSP stapling, клиент должен иметь “status_request” расширение с его SSL/TSL “Hello” сообщением.
Иными словами, уменьшается время загрузки страницы у клиентов, потому как им не приходится проверять промежуточные сертификаты дополнительными запросами.

Основные преимущества OCSP stapling:

  • Доверяющая сторона получает статус сертификата веб-серверов, когда это необходимо (во время SSL/TLS-подтверждения).
  • Не требуются дополнительные HTTP-соединения с ЦА.
  • OCSP stapling обеспечивает дополнительную безопасность за счет уменьшения числа векторов атак.

Документация:

  • NGINX SSL Stapling
  • NGINX Resolver

Добавляем ssl-stapling.conf

$ nano /etc/nginx/global/ssl-stapling.conf
1
2
3
4
5
6
7
8
9
10
11
12
# OCSP Stapling.
ssl_stapling on;
ssl_stapling_verify on;

# If the ssl_certificate file does not contain intermediate certificates, the certificate
# of the server certificate issuer should be present in the ssl_trusted_certificate file.
#ssl_trusted_certificate /path/to/ca.crt;

# If you want to specify a DNS resolver for stapling, you can uncomment the below line.
# If you leave it commented, nginx will use your system resolver, which will probably work just fine!
resolver 8.8.8.8 8.8.4.4 216.146.35.35 216.146.36.36 valid=300s;
resolver_timeout 5s;
  • ssl_stapling — глобальное включение/выключение.
  • ssl_stapling_verify — разрешает или запрещает проверку сервером ответов OCSP.
  • ssl_trusted_certificate — если в заданном директивой ssl_certificate файле не содержится промежуточных сертификатов, то сертификат издателя сертификата сервера следует поместить в файл, заданный директивой ssl_trusted_certificate.
    Например, при получении и настройки Let’s Encrypt сертификата, мы указывали в качестве сертификата файл fullchain.pem. И если его открыть, то мы увидим 2 сертификата (цепочка), а не 1. Иными словами, в файле содержится промежуточный сертификат и указывать эту директиву в нашем случае не нужно.
  • resolver — необязательная директива при использовании OCSP Stapling. Задаёт IP-адреса DNS-серверов для кэширования ответов из ЦА. Если директива не задана, Nginx будет использовать системные резольверы. Указаны публичные Google DNS и Failover DYN DNS.
    Второй опциональный параметр valid задаёт время кэширования этих ответов; и если эта директива не задана, Nginx будет брать значения из TTL-ответа. До версии 1.1.9 этой директивы не было и Nginx всегда кэшировал ответы на 5 минут (300s).
  • resolver_timeout — таймаут для преобразования имени в адрес. По-умолчанию 30s.

Подключаем ssl-stapling.conf

$ nano /etc/nginx/sites/$DOMAIN
1
2
3
4
5
6
7
8
server {
# if SSL
ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
include /etc/nginx/global/ssl.conf;
include /etc/nginx/global/ssl-hsts.conf;
+ include /etc/nginx/global/ssl-stapling.conf;
}
$ service nginx reload

Проверяем OCSP Stapling

$ openssl s_client -servername $DOMAIN -connect $DOMAIN:443 -status 2> /dev/null | grep -A 17 'OCSP response:'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
OCSP response:
======================================
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
Produced At: Apr 17 15:10:00 2017 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: 7EE66AE7729AB3FCF8A220646C16A12D6071085D
Issuer Key Hash: A84A6A63047DDDBAE6D139B7A64565EFF3A8ECA1
Serial Number: 036B56427AAD0E35C76A7C167BDFB7F3DF39
Cert Status: good
This Update: Apr 17 15:00:00 2017 GMT
Next Update: Apr 24 15:00:00 2017 GMT

Инструменты для проверки OCSP Stapling онлайн:

  • DigiCert® SSL Installation Diagnostic Tool.
  • SSL Server Test.

Возможные ошибки

Всё сделал по инструкции — OCSP Stapling не определяется никакими сервисами. В чём проблема?

Следует закомментировать сервер по-умолчанию (default.conf) или переопределить его SSL-конфигурацию.

«Многие настройки SSL работают до обработки SNI, и, соответственно, имеют смысл только на сервере по умолчанию даже в случае использования SNI. E.g., разные ssl_protocols для разных виртуальных серверов - задать не получится.» — Странное поведение OCSP Stapling и параметров ssl

OCSP-ответ определяется не с первого раза. Что делать?

После перезагрузки/перезапуска, Nginx не отдаёт OCSP-ответ при самом первом запросе. При первом запросе он асинхронно пытается его получить и если ему это удаётся, все последующие запросы будут отдаваться с OCSP-ответом.

Подробнее об этом есть в комментариях на Хабре и на Let's Encrypt Community.


HSTS

Заголовок HTTP Strict Transport Security (HSTS) предназначен для принудительного перенаправления с HTTP на HTTPS. Стоит любому первому посетителю открыть сайт через HTTPS, как все последующие соединения будут обрабатываться через HTTPS. Выглядит как-то так:

1
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload" always;

Знак ; после последней указанной опции, перед ", ставить не нужно.

HSTS имеет следующие опции:

  • max-age=31536000 — время кэширования заголовка в секундах после любого первого обращения к домену через HTTPS.
    Счётчик обнуляется при каждом последующем визите. То есть, если сегодня установлен интервал на год и клиент зайдёт завтра, счётчик при заходе завтрашнего клиента скинется, и завтра вновь будет интервал на год. Иными словами, интервал в год — это бесконечный интервал даже для слабопосещаемого ресурса.
  • includeSubdomains — включает HSTS основного домена для всех его поддоменов. Я решил воздержаться от этой опции, т.к. для нужных мне поддоменов я просто вкладываю ssl-hsts.conf конфиг.
  • preload — когда сайт посылает заголовок с директивой “preload”, запрашивается включение в список предварительной загрузки (Chrome preload list) и может быть одобрен в автоматическом режиме, если соблюдены требования к подаче запроса на сервисе HSTS preload list от Lucas’а Garron’а из Google.
    Как альтернативный вариант, домен можно добавить/удалить/запросить вручную через Chrome браузер по этому адресу.
    Имейте ввиду, что если по каким-либо причинам Вам нужно будет исключить домен с поддоменами из списка, операция может длиться несколько месяцев до тех пор, пока Chrome не обновится (причём, никто не ручается за другие браузеры). Более того, обязательным условием для приёма в список и работоспособности “preload” является параметр includeSubdomains, а параметр max-age должен быть как минимум восемнадцать недель! Поэтому подумайте дважды, прежде чем решить включить эту опцию.
  • always — если указан этот параметр, то поле заголовка будет добавлено независимо от кода ответа. Подробнее в официальной документации Nginx.

В общем, лично я отказался от includeSubdomains и тем более от preload однозначно.
Зачем вкладывать поддомены, если в нужные поддомены можно вложить конфиг HSTS?
И зачем запрашивать участие на то, что твой домен со всеми его поддоменами будут в списке как минимум на полтора года, когда max-age=31536000 — априори практически бесконечный интервал HSTS-заголовка.