ssl_prefer_server_ciphers on 是强制Nginx按服务端配置的加密套件顺序协商的关键开关,否则客户端(如Android 4.4、Java 7u25)可能降级使用弱套件;它必须与精细排序的ssl_ciphers、禁用TLSv1.0/1.1、指定ssl_ecdh_curve等协同生效才真正有效。

ssl_prefer_server_ciphers on 是强制套件顺序的关键开关
不加这句,ssl_ciphers 里排再好的顺序也没用。Nginx 默认把协商权交给客户端,而很多旧客户端(比如 Android 4.4、Java 7u25)会优先选自己支持的弱套件,哪怕服务器配置了 ECDHE-ECDSA-AES256-GCM-SHA384。只有设为 on,Nginx 才会在 TLS 1.2 握手时坚持按你写的 ssl_ciphers 顺序来挑——这是强加密能落地的前提。
ssl_ciphers 排序必须手动精细控制,不能只靠 HIGH
HIGH:!aNULL:!MD5 这类模糊写法看似省事,但实际会混入不带前向保密(PFS)的 RSA-AES 套件,也容易漏掉 ChaCha20-Poly1305 这类对移动设备更友好的算法。真正可控的做法是显式列出并排序:
- 把
ECDHE-ECDSA-AES128-GCM-SHA256、ECDHE-RSA-AES256-GCM-SHA384、ECDHE-RSA-CHACHA20-POLY1305放最前面 - 兼容性降级项(如
ECDHE-RSA-AES128-SHA)必须用冒号接在末尾,且仅限必要场景 - 绝对避免出现
DES、3DES、RC4、MD5、SHA1、aNULL、eNULL
必须搭配 ssl_protocols 和 ssl_ecdh_curve 才完整
光靠 ssl_prefer_server_ciphers on 和 ssl_ciphers 不足以保证强加密生效:
-
ssl_protocols TLSv1.2 TLSv1.3:必须禁掉TLSv1.0和TLSv1.1,否则弱协议下即使套件强也白搭 -
ssl_ecdh_curve secp384r1:prime256v1:指定曲线才能让 ECDHE 密钥交换真正走高安全椭圆曲线,否则可能退化到不安全的ffdhe2048或更糟 - TLS 1.3 下
ssl_prefer_server_ciphers无效,但它的套件是协议硬编码的,所以只要协议开对,1.3 天然就强
验证是否真生效,别信 nginx -t
语法检查通过 ≠ 浏览器真用了你写的套件。常见误判点:
- 用
openssl s_client -connect example.com:443 -tls1_2看输出里的Cipher is行,确认不是AES128-SHA这类老套件 - 跑一次 SSL Labs Server Test,重点看 “Handshake Simulation” 表格里 Chrome、Firefox、Android 各版本实际协商到的 Cipher Suite
- 如果某客户端显示
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,说明你的ssl_ciphers末尾兼容项被误前置,或ssl_prefer_server_ciphers没生效
最容易被忽略的是:Nginx 的 ssl_prefer_server_ciphers 只作用于 server 块或 http 块,若你在某个 location 里覆盖了 ssl 配置,或者用了 include 引入了冲突设置,它就会静默失效。











