导致 NGINX 无法启动的后量子 ssl_ecdh_curve¶
Gixy 检查 ID:ssl_ecdh_curve
如今每一篇「为 nginx 添加后量子 TLS」的文章都以同一行结尾:
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)会列出所链接的库真正接受的群集合。
同样的问题也适用于旧版 BoringSSL 构建和 2024 年前后的指南所使用的标准化之前的
X25519Kyber768Draft00 名称。
错误示例¶
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;(nginx 默认值),或只列出经典曲线。
如果同一份配置要下发到版本混杂的服务器群,请在构建时决定是否启用该指令,而不要
指望 ? 能救你。
本检查不会标记的情况¶
ssl_ecdh_curve auto;—— nginx 的默认值;群列表由 OpenSSL 选择。- 仅使用经典曲线(
X25519:prime256v1:secp384r1)。 - 已经带有
?前缀的后量子群。