При подготовке одного из учебных инцидентов для Linux-тренажёра я задумался над довольно неприятной ситуацией: сертификат на сервере уже обновлён, но пользователи по-прежнему получают ошибку о его истечении.
На первый взгляд кажется, что проблема в Certbot. Но сертификат может быть совершенно нормальным. Вопрос в другом: какой именно сертификат сервер отдаёт клиенту?
Разберём такую ситуацию на примере Nginx.
Сертификат на диске и сертификат в браузере
Предположим, сертификат обновили через Certbot. Проверяем его:
openssl x509 \
-in /etc/letsencrypt/live/example.com/fullchain.pem \
-noout -dates -serialСрок действия нормальный, сертификат новый.
Но браузер всё равно показывает предупреждение.
В этот момент полезно проверить сертификат не на диске, а непосредственно через TLS-соединение:
openssl s_client \
-connect example.com:443 \
-servername example.com \
</dev/null 2>/dev/null |
openssl x509 -noout -dates -serialЗдесь мы получаем сертификат, который реально предъявляется сервером при подключении к example.com:443.
Если серийные номера отличаются, значит сервер отдаёт не тот сертификат, который мы проверяли на диске.
И вот здесь начинается диагностика.
Причина №1. Nginx не перечитал сертификат
Одна из возможных причин — сертификат обновился, а Nginx продолжает использовать ранее загруженный.
Сначала проверяем конфигурацию:
sudo nginx -tЕсли ошибок нет, перечитываем её:
sudo systemctl reload nginxЗатем снова выполняем openssl s_client и сравниваем сертификаты.
Почему это важно?
Обновление файла на диске не означает, что работающий Nginx автоматически начнёт использовать его новую версию. Обычно для этого требуется перезагрузка конфигурации.
При штатном reload Nginx создаёт новые рабочие процессы с обновлённой конфигурацией, а старые постепенно завершают обслуживание существующих соединений.
Причина №2. Nginx смотрит не на тот файл
Другая ситуация: сертификат обновился, Nginx перезагрузили, но ничего не изменилось.
Проверяем активную конфигурацию:
sudo nginx -T 2>&1 |
grep -nE 'server_name|ssl_certificate'Например, можно обнаружить, что Nginx использует:
ssl_certificate /etc/nginx/ssl/old-cert.pem;А Certbot обновляет совсем другой файл:
/etc/letsencrypt/live/example.com/fullchain.pemВсё работает как настроено. Просто обновляется не тот сертификат, который используется для HTTPS.
После исправления путей нужно снова проверить конфигурацию и выполнить reload.
Причина №3. Сертификат вообще отдаёт не этот Nginx
Это моя любимая часть подобных задач.
Предположим, локально сертификат правильный, конфигурация корректная, Nginx перезагружен.
Но браузер всё равно видит старый.
Возможно, TLS завершается вообще на другом узле.
Перед приложением может находиться балансировщик, CDN или ещё один reverse proxy.
В таком случае сертификат на сервере приложения никак не влияет на то, что получает браузер.
Полезно сравнить сертификаты на разных точках подключения, явно указывая IP и SNI:
openssl s_client \
-connect 203.0.113.10:443 \
-servername example.com \
</dev/null 2>/dev/null |
openssl x509 -noout -serial -datesЗдесь 203.0.113.10 — пример адреса проверяемого узла.
Если разные узлы предъявляют разные сертификаты, причина может быть в конфигурации балансировщика или в том, что сертификат обновили не везде.
Отдельно стоит проверить и DNS: домен может указывать на несколько серверов.
Что в итоге?
У этой проблемы довольно простой вывод.
Проверять сертификат на диске и проверять HTTPS-соединение — не одно и то же.
Файл может быть актуальным, но Nginx использует старую версию. Конфигурация может указывать на другой файл. А иногда запрос вообще проходит через промежуточный сервер, о котором в начале расследования забыли.
Поэтому при подобных ошибках я бы начинал не с повторного запуска Certbot, а со сравнения сертификата на диске с тем, что действительно видит клиент.
И только после этого менял конфигурацию.

Комментарии 0