Глава 12 / 51
Том 2 · Конфигурация и сборка

Управление сертификатами: от PEM до горячей замены

TLS-сертификаты — самая ошибкоопасная часть конфигурации, а тихие ошибки здесь опаснее всего. XServer превращает каждую проверку сертификата в именованную диагностику и поддерживает замену сертификатов без простоя.

Обзор

Позиционирование: у сертификатов три дела — формат верен (12.2), пара сходится (12.3), обновление возможно (12.4). Все образцы ошибок взяты из TLS-матрицы диагностики func_test и воспроизводимы.

12.1 Введение

Классическое переживание сертификатных проблем — «рукопожатие провалилось, причина неизвестна»: может, путь неверный, может, формат битый, может, key не подходит к cert, может, цепочка неполная. Позиция XServer — превратить каждый провал в именованную диагностику: всё, что проверяемо при старте, проверяется при старте; обновление в рантайме идёт атомарной заменой. За этим стоит преимущество собственного TLS-стека: разбор, сопоставление и раздача — в своих руках.

12.2 Строгий разбор PEM

Файлы закрытых ключей разбираются по трём меткам PEM при правилах строгой парности:

  • Метки BEGIN/END обязаны сходиться по счёту — «expects exactly one supported PEM block»
  • Несколько блоков или битый хвостовой блок никогда молча не игнорируются: старт падает с указанием файла
  • Три поддерживаемые метки закрытых ключей покрывают формы вывода mainstream-инструментов (семейство OpenSSL)

Цепочки сертификатов так же собираются целиком при сборке (построение цепочки с backtracking-стеком кадров); неполная цепочка не ждёт рукопожатия, чтобы всплыть.

12.3 Диагностика семейств алгоритмов

Самый классический кейс TLS-матрицы func_test: взять закрытый ключ PKCS#8 RSA и переписать объявление типа PEM на EC — ожидаемое сообщение обязано назвать обе стороны:

Форма ошибки (дословное утверждение теста)
certificate uses RSA but private key uses EC

Почему важно двустороннее именование: оно сразу сообщает «что за сертификат» и «за что приняли ключ» — чаще всего перепутаны файлы или правлена метка, и это видно мгновенно. Несовпадение семейства кривых (cert P-256 + key P-384) получает такую же именованную диагностику.

12.4 Таблица SNI и горячая замена

при сборке: hosts[] (набор доменов, cert, key) → построение таблицы SNI │ reload (эндпоинты/структура не изменились, файлы сертификатов изменились) ▼ горячая замена сертификатов TlsTableRefresh: атомарная подмена таблицы под блокировкой старые личности под защитой счётчика ссылок → освобождение после завершения рукопожатий в полёте │ ▼ все новые рукопожатия используют новый сертификат (без окна, без рестарта)

Принимая намерение, координатор reload выполняет разводку на уровне конфигурации: структурное сравнение не изменилось (эндпоинты, слушатели, топология те же) → горячая замена сертификатов плюс перезагрузка скрипта; иначе действуют правила структурных изменений из главы 13. То есть продление сертификата — ровно два действия: «перезаписать файл + подать reload».

12.5 Контракт

  • Проверки: парность PEM, совпадение семейств алгоритмов и построение цепочки завершаются при старте с именованной диагностикой.
  • Раздача: сертификаты входят в таблицу SNI по конфигурации хоста и выбираются по SNI в рукопожатии, согласованно с маршрутизацией HTTP-слоя.
  • Обновление: reload с неизменной структурой идёт путём горячей замены — атомарная подмена таблицы под блокировкой; старые личности под защитой ссылок до конца рукопожатий в полёте.

Частые ошибки

fullchain и key перепутаны местами
Симптом
Старт падает; диагностика сообщает, что содержимое файла не ожидаемого типа.
Причина
В tls_cert попал файл закрытого ключа (или наоборот). Строгий разбор PEM вскрывает это при старте, а не в рукопожатии.
После замены сертификата — рестарт
Симптом
При продлении сертификата разорвались все соединения.
Причина
Незнание пути горячей замены — перезапишите файл и подайте reload, рестарт процесса не нужен.
✗ Излишне
cp new-cert.pem host/tls/
systemctl restart xs   /* разрывы */
✓ Правильно
cp new-cert.pem host/tls/
/* подать reload: горячая замена сертификатов */

Упражнения

БазовыйПоднять HTTPS-сайт

Сгенерируйте cert/key любым самоподписанным инструментом, включите TLS-порт у демо и проверьте curl -k.

Приёмка: TLS-эндпоинт проходит рукопожатие и отвечает на /json.
ПродвинутыйВоспроизвести матрицу диагностики

По очереди создайте: ключ с переписанной меткой, несовпадение семейств cert/key, битый блок PEM — зафиксируйте все три сообщения.

Приёмка: каждое сообщение называет «какой файл, в чём проблема».
ВызовЗамена сертификата без простоя

Держите длинное соединение (curl --http1.1 -k в цикле запросов), посреди него перезапишите файл сертификата и подайте reload; следите, не рвётся ли соединение.

Приёмка: ноль неудач в цикле; новые рукопожатия используют новый сертификат (сравните два запуска openssl s_client).

Итоги

ТезисВывод
Строгий разборМетки PEM считаются парами; битые блоки не молчат
Именованная диагностикаНесовпадение семейств называет обе стороны (cert — X, key — Y)
Раздача SNIСертификаты уровня хоста → выбор в рукопожатии, согласовано с HTTP-маршрутизацией
Горячая заменаReload с неизменной структурой: атомарная подмена таблицы + защита ссылками, ноль разрывов
Что дальше по xrt