开启 ssl_prefer_server_ciphers on 的本质是将 TLS 握手加密套件选择权从客户端收归服务端,确保按配置的 ssl_ciphers 顺序优先协商强算法(如 ECDHE+AES-GCM),但必须配合禁用 TLSv1.0/1.1、精简 cipher list 及优化密钥交换才真正生效。

开启 ssl_prefer_server_ciphers on 的本质,是把 TLS 握手时加密套件的选择权从客户端手里收回来,交还给服务器自己——但这个“交还”不会自动带来安全,它只是让服务端配置的加密策略真正有机会被执行。
它解决的核心问题:默认协商太被动
默认情况下,Nginx 会接收客户端发来的完整 cipher suite 列表(按客户端偏好排序),然后从中挑出第一个双方都支持的套件。问题在于:很多旧设备、中间代理甚至恶意攻击者,会故意在列表里塞入 RC4、3DES、SHA1 等已被淘汰的算法。只要你的 ssl_ciphers 配置里还留着它们(哪怕排在末尾),就可能被选中。
开启该指令后,Nginx 不再看客户端的排序,而是严格从你自己写的 ssl_ciphers 列表中,从左到右匹配第一个客户端也支持的套件。这相当于设了一道“服务端优先门禁”。
必须同步落实的三项关键配置
单独打开 ssl_prefer_server_ciphers on 没有意义,它只是开关,真正起作用的是配套设置:
- 限定协议版本:只启用 TLSv1.2 TLSv1.3;TLSv1.0 和 TLSv1.1 必须禁用,它们本身存在设计缺陷,无法支撑现代加密逻辑
-
精简并明确排序 cipher list:剔除所有已知脆弱项(RC4、DES、3DES、MD5、SHA1、EXPORT、NULL),开头放前向保密(PFS)强组合,例如:
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305 - 优化密钥交换过程:添加 ssl_ecdh_curve secp384r1:prime256v1,避免因椭圆曲线不匹配而被迫回退到不支持前向保密的 RSA 密钥交换
配置位置与验证不能省略
这个参数必须写在 server 块内,和 ssl_certificate、ssl_ciphers 等其他 SSL 参数保持一致。避免在 http 块全局开启,却在某个 server 中漏配 cipher,导致该站点策略失效。
改完务必验证:
- 用 OpenSSL 强制走 TLSv1.2 测试:
openssl s_client -connect yourdomain.com:443 -tls1_2 | grep "Cipher is"
输出应为你 ssl_ciphers 列表中最靠前的那个强套件 - 用 SSL Labs 全面扫描,重点看 “Handshake Simulation” 中各主流客户端实际协商到的套件是否全部落在你设定的强范围内,目标评级为 A+
TLSv1.3 下它还管用吗?
TLSv1.3 协议本身已硬性规定只能使用 ECDHE+AES-GCM/ChaCha20 等极少数强套件,ssl_ciphers 和 ssl_prefer_server_ciphers 在该协议下自动失效。但它对 TLSv1.2 仍完全有效——而目前仍有部分老旧客户端依赖 TLSv1.2,所以这个指令必须保留,不能省略。











