The Jerusalem PostJerusalem Orchestra East & West youth division to perform at UNוואלה164 קמ"ש במקום 60: נהגת חדשה בת 18 נתפסה במהירות קיצונית בלב חיפהRTP DesportoPresidente do V. Guimarães agastado com início de época "frustrante"Daily MaverickStudent opens fire outside school in Turkey, eight pupils wounded, NTV reportsThe South AfricanBombshell: Springboks may play Malcolm Marx in new positionStraits Times SportLa Liga president hits out at Real Madrid refereeing ‘conspiracy’ claimsХабрИИ режет не рутину, а расходы. Поэтому подушка теперь базовый минимумOnetPolski "Niedźwiedź" pokazał się światu. Żołnierze powinni być zachwyceniIl Fatto QuotidianoMorto Grigory Ponomarev: l’addio improvviso a 31 anni di “Grizzly”, ex lottatore MMA. L’ipotesi di un legame con l’infortunio del 2023CNN بالعربيةأستراليا تؤكد تحويل أجزاء من مقاتلات F-35 الأمريكية إلى هونغ كونغ بالخطأSportstarLIVE India vs Sri Lanka, Asian Games 2026 hockey: IND 10 - 0 SL, Abhishek, Jugraj score two eachVilaWebLa UE tanca la discussió sobre l’oficialitat del català en set minuts i sense adoptar cap decisió
The Daily Newsstand · Free, Always
Tuesday, September 22, 2026

Ваш ssl_stapling больше ничего не делает

Translate

TLS‑блок в конфиге nginx — самая копируемая часть всей конфигурации. Его берут из генератора Mozilla, из статьи с хорошим рейтингом или из соседнего проекта, вставляют один раз и больше не открывают. Работает же. Сертификат валиден, замочек зелёный, SSL Labs рисует букву A.

За последние пару лет в этом блоке устарело сразу несколько вещей, причём по‑разному.

  • Одна директива перестала работать вообще и теперь только пишет предупреждение в лог.

  • Другой популярный совет из тех же гайдов сегодня скорее вредит, чем помогает, потому что nginx научился делать это сам.

  • Третья настройка по умолчанию выключена, хотя все уверены в обратном.

Заметно ничего не ломается. Сайт открывается, ошибок нет. Понять, что часть конфига превратилась в декорацию, можно, только если пойти и проверить специально.

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

OCSP stapling: механизма больше нет

Начнём с самого показательного случая.

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

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

Проблема в том, что такой запрос делает браузер, а значит удостоверяющий центр видит, кто на какой сайт заходит.

Плюс это дополнительный сетевой вызов в момент установки соединения, и если сервис отвечает медленно, страдает время открытия страницы.

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

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

ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 valid=300s;

А потом в Let's Encrypt посчитали нагрузку. Их OCSP‑сервис обрабатывал порядка двенадцати миллиардов запросов в сутки, и каждый такой запрос сообщал центру, какой пользователь с какого адреса открывает какой сайт.

В декабре 2024 они объявили, что от OCSP отказываются полностью, в пользу списков отозванных сертификатов.

Даты стоит запомнить, потому что по ним видно, касается это вас или ещё нет:

  • 30 января 2025 — перестали работать запросы с расширением OCSP Must‑Staple.

  • 7 мая 2025 — из новых сертификатов убрали ссылку на OCSP‑сервис, вместо неё туда добавили ссылку на CRL.

  • 6 августа 2025 — OCSP‑сервисы выключены совсем.

Практическое следствие для nginx выглядит так:

[warn] "ssl_stapling" ignored, no OCSP responder URL in the certificate

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

Что с этим делать, зависит от удостоверяющего центра. Обе строчки со stapling для сертификатов Let's Encrypt можно смело убирать: они уже ничего не дают. У коммерческих центров, которые пока продолжают отдавать OCSP, stapling остаётся рабочей оптимизацией. Трогать его незачем.

Отдельно стоит проверить options-ssl-nginx.conf, который кладёт certbot. Во многих установках директивы живут именно там, и человек, правивший свой конфиг, их не находит.

Отзыв заменили сроком жизни

История с OCSP интереснее, чем кажется, потому что за ней стоит смена подхода целиком.

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

Работает это так: если сертификат живёт меньше недели, отзывать его практически незачем — он и так истечёт раньше, чем информация об отзыве разойдётся по клиентам.

Let's Encrypt сделал шестидневные сертификаты общедоступными 15 января 2026 года, срок жизни у них ровно 160 часов.

Заодно появились сертификаты на IP‑адреса, но только в коротком варианте, потому что адреса меняются чаще доменов.

Общее направление задаёт не отдельный центр, а правила отрасли: с 15 марта 2029 года максимальный срок жизни сертификата составит 47 дней. Let's Encrypt планирует опустить свой предел до 45 дней к февралю 2028-го, оставаясь пока на девяноста днях по умолчанию.

Для конфигурации nginx отсюда следует одно, зато очень важное.

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

Пригодится директива, появившаяся в версии 1.27.4:

ssl_certificate_cache max=1000 inactive=20s valid=1m;

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

Возобновление сессии выключено по умолчанию

Теперь к настройке, про которую большинство уверено, что она работает сама.

Полное рукопожатие TLS — это дополнительный обмен пакетами и криптография с открытым ключом. Возобновление сессии позволяет клиенту, который уже был на сайте, пропустить дорогую часть. Экономия заметная. Особенно на мобильных сетях с большой задержкой.

Механизмов два.

  1. Первый, по идентификатору сессии, хранит состояние на сервере. Клиент присылает идентификатор, сервер ищет его в своём кэше и достаёт параметры. Настраивается директивой ssl_session_cache.

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

Неприятность в том, что первый механизм по умолчанию выключен.

Значение ssl_session_cache по умолчанию — none, и это означает буквально следующее: nginx говорит клиенту, что сессию можно возобновить, а сам её не сохраняет.

Клиент приходит с идентификатором, попадает в пустоту и делает полное рукопожатие заново.

Включается кэш одной строкой:

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;

Слово shared здесь обязательно. Встроенный кэш OpenSSL, который включается вариантом builtin, живёт внутри одного рабочего процесса: клиент, попавший на другой воркер, свою сессию не найдёт.

При восьми воркерах шансы попасть на нужный — примерно один к восьми. Общий кэш лежит в разделяемой памяти и виден всем.

Размер считается просто: один мегабайт вмещает около четырёх тысяч сессий, так что десять мегабайт это сорок тысяч.

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

Совет «выключить тикеты» устарел

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

Отсюда и совет: либо ротируйте ключи скриптом через ssl_session_ticket_key, либо выключайте тикеты вовсе.

Начиная с версии 1.23.2 nginx делает это сам.

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

Никаких скриптов и файлов, если только вам не нужно синхронизировать ключи между несколькими серверами вручную.

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

Строчка ssl_session_tickets off в конфигурации, где клиенты ходят по TLS 1.3, не просто убирает один способ возобновления — она убирает возобновление целиком.

То есть современный адекватный вариант выглядит наоборот:

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets on;

Ручная ротация через ssl_session_ticket_key остаётся нужной ровно в одном случае: когда за балансировщиком стоит несколько машин с nginx и клиент может попасть на любую из них. Тогда ключ должен быть общим, и раскладывать его придётся самостоятельно.

0-RTT: быстро, но не для всего

Раз уж речь зашла про возобновление, стоит сказать и про его агрессивную версию.

TLS 1.3 разрешает клиенту отправить данные приложения вместе с самым первым пакетом, не дожидаясь завершения рукопожатия. Это экономит целый круг обмена, что на мобильной сети означает десятки, а иногда и сотни миллисекунд.

В nginx включается одной строкой:

ssl_early_data on;

Проблема у механизма одна, зато серьёзная.

Ранние данные не защищены от повтора: злоумышленник, перехвативший этот первый пакет, может отправить его ещё раз, и сервер выполнит запрос повторно.

Для чтения это безобидно, для операции, которая что‑то меняет, — нет.

Решение принято на уровне протокола и состоит в том, что ранние данные разрешают только для идемпотентных запросов.

Сервер обязан сообщить приложению, что запрос пришёл в ранних данных, а приложение решает, выполнять его или потребовать повтора по нормальному соединению:

server {
    ssl_early_data on;

    location / {
        proxy_pass http://backend;
        proxy_set_header Early-Data $ssl_early_data;
    }

    location /api/payments {
        if ($ssl_early_data = 1) {
            return 425;
        }
        proxy_pass http://backend;
    }
}

Код 425 придуман специально для этого случая и означает «повтори запрос по установленному соединению». Клиенты, поддерживающие 0-RTT, обрабатывают его корректно.

Разбираться с идемпотентностью в приложении некогда? Ну, тогда лучше оставить ssl_early_data выключенным. Выигрыш в один круг обмена того не стоит, если ценой будет повторно проведённый платёж.

Мелочи, которые тоже поменялись

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

Шифры TLS 1.3 не настраиваются директивой ssl_ciphers, она относится только к более старым версиям протокола. Начиная с 1.19.4 для этого есть ssl_conf_command, который передаёт параметр напрямую в OpenSSL:

ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;

Трогать это, впрочем, почти никогда не нужно: набор в TLS 1.3 короткий, и все варианты в нём приемлемые.

  • В 1.27.2 появилась ssl_key_log для отладки шифрованного трафика. Она пишет сессионные ключи в файл в том формате, который понимает Wireshark, и позволяет посмотреть содержимое соединения. Вещь полезная и очень опасная: файл с ключами даёт возможность расшифровать записанный трафик, поэтому на боевом сервере ей не место.

  • И ssl_reject_handshake on — способ аккуратно отклонять соединения к серверному блоку по умолчанию, вместо того чтобы отдавать первый попавшийся сертификат клиенту, который пришёл с незнакомым именем в SNI.

В итоге

Общая мысль во всём этом такая.

TLS‑блок кажется той частью конфига, которую настроил один раз и забыл, потому что криптография меняется медленно.

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

Раз в год туда стоит заглядывать, хотя бы чтобы убедиться, что половина директив всё ещё что‑то значит.

А у вас в конфиге ещё живёт ssl_stapling?

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

Продолжить разбор актуальных практик работы с веб‑серверами, сертификатами и инфраструктурой можно на бесплатных уроках:

  • 5 октября в 19:00. «Автоматические TLS‑сертификаты: модуль ACME (Angie)». Записаться

  • 20 октября в 19:00. «Балансировка HTTP и L4 сервисов в Angie (Angie)». Записаться

Больше бесплатных уроков и материалов по инфраструктуре можно найти в этом посте.

View the original on Хабр

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.