Постквантовый ssl_ecdh_curve, из-за которого NGINX не запускается¶
Идентификатор проверки Gixy: ssl_ecdh_curve
Каждая статья «добавьте постквантовый TLS в nginx» заканчивается одной и той же строкой:
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1;
Скопируйте её на машину, где OpenSSL старше 3.5, и сайт упадёт. Не «потеряет поддержку постквантовой криптографии» — именно упадёт.
Почему это полный отказ, а не деградация¶
nginx передаёт значение прямо в OpenSSL:
/* src/event/ngx_event_openssl.c */
if (SSL_CTX_set1_curves_list(ssl->ctx, &conf->ecdh_curve...) == 0) {
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
"SSL_CTX_set1_curves_list(\"%V\") failed", &conf->ecdh_curve);
return NGX_ERROR;
}
Здесь неудачно складываются два свойства:
- OpenSSL отвергает весь список, если хотя бы одно имя группы ему
неизвестно. Частичного применения не существует —
X25519MLKEM768:X25519:prime256v1отклоняется целиком, хотя две из трёх групп поддерживаются повсеместно. - nginx пишет об этом с уровнем
NGX_LOG_EMERGи возвращает ошибку, так что мастер-процесс не завершает разбор конфигурации. Это отказ при запуске, а не откат на уровне отдельного соединения.
Проверено на OpenSSL 3.6.3:
$ openssl s_client -groups bogusgroup -connect 127.0.0.1:1
Call to SSL_CONF_cmd(-groups, bogusgroup) failed
$ openssl s_client -groups '?bogusgroup:X25519' -connect 127.0.0.1:1
connect:errno=61 # список принят, не удалось только TCP-соединение
X25519MLKEM768 и родственные группы появились в OpenSSL 3.5. Дистрибутивы,
на которых работает большая часть продакшен-инсталляций nginx, поставляют более
старые версии:
| Дистрибутив | OpenSSL | X25519MLKEM768 |
|---|---|---|
| Debian 12 (bookworm) | 3.0 | ✗ nginx не запустится |
| Ubuntu 24.04 LTS | 3.0 | ✗ nginx не запустится |
| RHEL / AlmaLinux / Rocky 9 | 3.2 | ✗ nginx не запустится |
Прежде чем называть любую постквантовую группу, проверьте, что у вас на самом
деле установлено, командой openssl version; openssl list -tls-groups
(OpenSSL 3.x) покажет точный набор, который примет слинкованная библиотека.
То же самое относится к достандартным именам X25519Kyber768Draft00, которые
используют старые сборки на BoringSSL и руководства 2024 года.
Плохой пример¶
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.pem;
ssl_certificate_key /etc/ssl/private/example.com.key;
# Одно неизвестное имя — и мастер-процесс откажется стартовать
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1;
}
Хороший пример¶
Добавьте постквантовым группам префикс ?. Тогда OpenSSL пропускает имена,
которые не распознаёт, вместо того чтобы отвергнуть весь список:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.pem;
ssl_certificate_key /etc/ssl/private/example.com.key;
ssl_ecdh_curve ?X25519MLKEM768:X25519:prime256v1;
}
Машина с OpenSSL 3.5+ согласует X25519MLKEM768, а более старая незаметно
откатится на X25519 и продолжит обслуживать запросы.
У префикса ? есть собственное ограничение по версии¶
? появился в OpenSSL 3.3. На OpenSSL 3.0 и 3.2 сама строка
?X25519MLKEM768 является неразбираемым именем группы и приводит ровно к тому
же отказу. Поэтому:
- OpenSSL 3.5+ — перечисляйте постквантовые группы напрямую или с
?. - OpenSSL 3.3 / 3.4 — используйте
?, чтобы конфигурация была совместима с будущими версиями. - OpenSSL 3.0 / 3.2 (Debian 12, Ubuntu 24.04, RHEL 9) — не указывайте
постквантовые группы вообще. Оставьте
ssl_ecdh_curve auto;(значение по умолчанию) или перечислите только классические кривые.
Если одна конфигурация раскатывается на смешанный парк серверов, включайте
директиву на этапе сборки, а не рассчитывайте на то, что ? вас спасёт.
Что эта проверка не помечает¶
ssl_ecdh_curve auto;— значение nginx по умолчанию; список групп выбирает OpenSSL.- Только классические кривые (
X25519:prime256v1:secp384r1). - Постквантовые группы, у которых уже есть префикс
?.