开启 ssl_prefer_server_ciphers on 是让 Nginx 主导 TLS 1.2 加密套件选择的必要动作,但必须配合精细排序的 ssl_ciphers、禁用弱协议(ssl_protocols TLSv1.2 TLSv1.3)、指定安全椭圆曲线(ssl_ecdh_curve)及正确作用域配置,否则旧客户端仍可能协商出弱套件;该指令对 TLS 1.3 无效,因其套件由协议硬编码。

直接开启 ssl_prefer_server_ciphers on 是让 Nginx 主导 TLS 握手加密套件选择的必要动作,但仅这一步远远不够——它必须和精确排序的 ssl_ciphers、协议版本限制、椭圆曲线指定等配置协同工作,否则客户端(尤其是旧系统)仍可能协商出弱套件。
为什么默认不生效?
Nginx 默认把套件选择权交给客户端。比如 Android 4.4 或 Java 7u25 这类老客户端,哪怕你配置了 ECDHE-RSA-AES256-GCM-SHA384,它也可能优先选自己支持的 AES128-SHA,只因它在客户端列表里靠前。开启 ssl_prefer_server_ciphers on 后,Nginx 才会在 TLS 1.2 握手中坚持按你写的 ssl_ciphers 顺序来匹配。
必须配套的关键配置
单独开开关没用,以下四项需同时到位:
-
显式精细排序 ssl_ciphers:不能用
HIGH:!aNULL:!MD5这类模糊写法。应明确列出强套件并按优先级排列,例如:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305 -
禁用不安全协议:
ssl_protocols TLSv1.2 TLSv1.3;务必去掉 TLSv1.0 和 TLSv1.1,否则弱协议下再强的套件也形同虚设 -
指定安全椭圆曲线:
ssl_ecdh_curve secp384r1:prime256v1,避免密钥交换退化到 ffdhe2048 等低强度参数 -
兼容项放末尾且谨慎启用:如需支持极老客户端,可追加
:ECDHE-RSA-AES128-SHA,但必须用冒号连接,并确保它排在所有强套件之后
验证是否真正生效
别只信 nginx -t 通过,要实测协商结果:
- 用 OpenSSL 检查 TLS 1.2 握手:
openssl s_client -connect example.com:443 -tls1_2 | grep "Cipher is"
确认输出是类似ECDHE-RSA-AES256-GCM-SHA384,而非AES128-SHA或RC4-SHA - 跑一次 SSL Labs Server Test,重点看 “Handshake Simulation” 表格中 Chrome、Firefox、Android 各版本实际协商到的 Cipher Suite
- 若某客户端显示
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,说明你的兼容项被误前置,或ssl_prefer_server_ciphers没在生效作用域(比如被 location 块覆盖)
注意作用范围与 TLS 1.3 的特殊性
ssl_prefer_server_ciphers 只对 TLS 1.2 及以下有效,在 TLS 1.3 中该指令被忽略——因为 1.3 的套件是协议硬编码的,只要启用了 TLSv1.3,天然就只用 AEAD 类强算法。但它仍需保留在配置中,确保 TLS 1.2 流量受控。另外,该指令只在 http 或 server 块中生效,若你在某个 location 里重写了 SSL 配置,或用 include 引入了冲突设置,它就会失效。


















