ssl_prefer_server_ciphers on 在现代 tls 中天然受限:tlsv1.3 下完全无效;tlsv1.2 下需配合 ssl_protocols tlsv1.2 严格限定、ssl_ciphers 显式启用客户端支持的强套件(如 ecdhe-rsa-aes128-gcm-sha256),并排除弱算法,否则仍被客户端优先级覆盖。

确认 TLS 协议版本是否禁用了旧协议
如果 `ssl_protocols` 仍包含 TLSv1.0 或 TLSv1.1,即使设置了 `ssl_prefer_server_ciphers on`,客户端也可能降级协商到弱协议+弱套件,此时服务端优先级完全失效。
- 必须显式限定为
ssl_protocols TLSv1.2 TLSv1.3; - TLSv1.3 不再支持传统 cipher suite 协商机制,
ssl_prefer_server_ciphers对其无效;但它的存在可防止降级到 TLSv1.2 的弱套件 - 验证方式:
openssl s_client -connect example.com:443 -tls1_1应返回连接失败或 handshake error
检查 ssl_ciphers 是否实际包含客户端支持的强套件
即使 `ssl_prefer_server_ciphers on` 生效,若 `ssl_ciphers` 列表里没有客户端在 ClientHello 中声明的任何套件,协商就会失败或回退到默认行为(如 OpenSSL 的内置顺序)。
- 推荐显式启用前向安全、AEAD 类型套件,例如:
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384 - 务必排除
NULL、MD5、RC4、DES、EXPORT等已淘汰套件 - 用
nmap --script ssl-enum-ciphers -p 443 example.com扫描真实启用的套件,比配置文件更可信
注意 ssl_prefer_server_ciphers 在 TLSv1.3 下无意义
TLSv1.3 彻底移除了 cipher suite 协商中的“服务端优先”概念:所有合法套件由 RFC 固定,服务端仅能接受或拒绝,不能排序。所以只要启用了 TLSv1.3,该指令对这部分连接完全不参与作用。
- 这不是 bug,而是协议设计使然
- 真正要保障的是:TLSv1.2 连接也只提供强套件,避免被降级利用
- 可通过
ssl_protocols TLSv1.2;临时关闭 TLSv1.3 来验证该指令在纯 v1.2 下是否生效(仅用于调试)
验证是否被其他模块或代理覆盖
Nginx 配置可能被 include 文件、stream 模块、或前置 LB(如 ALB、Cloudflare)覆盖。常见干扰场景:
- 使用了 CDN 或反向代理,实际 TLS 终止在边缘节点,Nginx 只处理 HTTP 内网流量
- 多个 server 块中存在冲突的 ssl_ciphers / ssl_prefer_server_ciphers 设置
- 启用了
ssl_buffer_size或ssl_session_cache等高级参数,间接影响协商路径 - 检查最终生效配置:
nginx -T 2>/dev/null | grep -A5 "server.*443.*ssl"











