1. 1
  2. 2
  3. 3
  4. 4
  5. 5

# теория · шаг 1 из 5

Протоколы, шифры и мёртвые строки

Коротко

Настройки TLS - та часть конфига, которую чаще всего копируют из статьи пятилетней давности. Половина строк оттуда сегодня повторяет умолчания, а одна не делает ничего.

  • ssl_protocols TLSv1.2 TLSv1.3 - и есть умолчание: замер показывает, что 1.0 и 1.1 сервер не принимает.
  • Включить их обратно одной директивой нельзя: мешает уровень безопасности самого OpenSSL.
  • Возобновление сессий работает из коробки - на билетах. Замер: с умолчаниями сессия переиспользуется, с ssl_session_tickets off без кеша - нет.
  • ssl_stapling с сертификатами Let's Encrypt мёртв с августа 2025 и пишет предупреждение при каждом старте.

Если знаешь, что умолчания протоколов уже хорошие, и различаешь билеты и кеш сессий - листай до «Теперь сам».

Сначала ответь сам

В конфиге нет ни одной строки про протоколы. Какие версии TLS согласует свежий nginx?

Проверено: по попытке openssl s_client -tls1, -tls1_1, -tls1_2, -tls1_3 на каждую версию, сводка по тому, удалось ли согласовать:

↳  выводсводка по openssl s_client -tlsN, по попытке на версию
tls1     не согласовано
tls1_1   не согласовано
tls1_2   согласовано
tls1_3   согласовано

Только 1.2 и 1.3. Строка ssl_protocols TLSv1.2 TLSv1.3; в свежем конфиге не меняет ничего - она фиксирует то, что и так есть. Смысл появляется, только когда ты сознательно сужаешь набор до одного TLSv1.3.

На что это похоже

Замок на подъездной двери, который сменили десять лет назад. В инструкции, висящей рядом, до сих пор написано «поверните ключ дважды и потяните на себя» - и это не вредный совет, просто теперь дверь открывается и без второго поворота.

Беда начинается, когда человек читает ту же инструкцию и решает, что «надо поставить старый замок обратно, ведь так написано».

Механизм: где на самом деле решается вопрос версии

ssl_protocols в конфиге что мы РАЗРЕШИЛИ сборка OpenSSL и SECLEVEL что библиотека вообще умеет итог - пересечение двух списков, а не то, что написано в конфиге разрешил TLSv1 в конфиге, а рукопожатие всё равно обрывается предупреждением 70 «protocol version» - это второй список открыть его можно только строкой ssl_ciphers 'DEFAULT@SECLEVEL=0'
Директива разрешает, библиотека решает. На современной сборке старые протоколы закрыты с двух сторон.

Правило

/etc/nginx/nginx.confhttp
ssl_session_cache   shared:SSL:10m;   # общий кеш на все воркеры; 10 МБ - около 40 тысяч сессий (≈250 байт каждая)
ssl_session_timeout 1h;

Настраивать стоит не протоколы, а возобновление сессий - и то не всегда. Именно shared, а не builtin: встроенный кеш живёт внутри одного воркера, и клиент, попавший к другому, пойдёт на полное рукопожатие.

Со списком шифров та же история, что с протоколами: умолчание HIGH:!aNULL:!MD5 (читается «шифры категории HIGH, но без анонимных aNULL и без MD5»; ! запрещает, : разделяет) разумно, а длинные строки из руководств времён TLS 1.0 в лучшем случае повторяют его, в худшем - запрещают то, что давно считается нормальным. Нет требования регулятора - не трогай.

Разбор: старый протокол не включается директивой

Стенд, блок с явным разрешением всех версий:

/etc/nginx/conf.d/old.confhttp server
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

nginx -t доволен. Клиент, которому разрешили древний протокол, всё равно получает отказ:

↳  выводopenssl s_client -tls1 -cipher 'DEFAULT@SECLEVEL=0'
tlsv1 alert protocol version:SSL alert number 70
New, (NONE), Cipher is (NONE)

Отказ прислал сервер: OpenSSL в свежей сборке работает на уровне безопасности, где TLS 1.0 не разрешён никакими шифрами. Добавим на сервер понижение уровня:

/etc/nginx/conf.d/old.confhttp server
ssl_ciphers 'DEFAULT@SECLEVEL=0';
↳  выводopenssl s_client -tls1
New, TLSv1.0, Cipher is ECDHE-RSA-AES256-SHA
Protocol: TLSv1

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

Разбор: возобновление сессий уже работает

Распространённое заблуждение - «кеш сессий выключен, значит рукопожатие каждый раз полное». Кеш и правда выключен, но билеты сессий включены. Замер: сохраняем сессию, подключаемся второй раз, смотрим на первую строку.

настройки блока TLS 1.2 TLS 1.3
умолчания Reused Reused
ssl_session_tickets off New New
ssl_session_tickets off плюс ssl_session_cache shared Reused Reused

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

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

Что ломается без этого

Строка, которая сегодня не делает ничего:

ssl_stapling on;
ssl_stapling_verify on;

OCSP stapling позволял серверу прикладывать к рукопожатию свежий ответ о том, что сертификат не отозван. Let's Encrypt убрал ссылку на OCSP из сертификатов в мае 2025 и выключил респондеры в августе 2025 - проверка отзыва переехала на списки, которые скачивает сам браузер.

Практический эффект виден при каждой проверке конфига:

↳  выводnginx -t
[warn] "ssl_stapling" ignored, no OCSP responder URL in the certificate
"/certs/shop.fullchain.crt"

Сертификаты от Let's Encrypt - убирай обе строки. От другого центра, который ещё держит OCSP, - оставляй, но знай, что отрасль движется туда же.

Зачем это в работе

Проверять набор целиком удобно не глазами, а инструментом. Внешние проверялки дают оценку и список того, что клиенты реально смогут согласовать; локально то же самое покажет сканер nmap с готовым скриптом: nmap --script ssl-enum-ciphers -p 443 shop.local - без выхода в интернет и без очереди.

Смотреть стоит не на букву оценки, а на список несовместимых клиентов. Старый Android или платёжный шлюз в этом списке - повод не сужать протоколы, даже если за это дают на балл меньше.

Теперь сам

Аудит требует «отключить устаревшие протоколы». Ты открываешь конфиг и не находишь ни строки ssl_protocols. Что ответить аудитору и что сделать?

Ответить, что они уже отключены: умолчание свежего nginx - только 1.2 и 1.3, и это проверяется одной командой снаружи (openssl s_client -tls1_1 не подключится). Сделать - добавить строку ssl_protocols TLSv1.2 TLSv1.3; явно. Поведение она не изменит, зато аудитор увидит намерение в конфиге, а не поверит на слово; заодно конфиг переживёт смену умолчаний в будущих версиях.

Главное

ssl_protocols TLSv1.2 TLSv1.3 и HIGH:!aNULL:!MD5 - это умолчания, копировать их незачем. Включить старые протоколы обратно одной директивой нельзя: уровень безопасности OpenSSL отвергнет их даже при явном разрешении, и открывается это только сознательным ssl_ciphers 'DEFAULT@SECLEVEL=0'. Возобновление сессий работает из коробки на билетах; кеш shared нужен, когда билеты выключены или серверов несколько. ssl_stapling с сертификатами Let's Encrypt мёртв с августа 2025 и на каждый старт пишет предупреждение - строки убирают.

Комментарии

Пока нет комментариев. Будь первым!

Оставить комментарий

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