开启 ssl_prefer_server_ciphers on 是防止 TLS 1.2 及以下协议协商弱加密套件的关键控制点,但必须与严格限制 ssl_protocols(仅 TLSv1.2+)、精确配置前向保密+AEAD 密码套件(如 ECDHE-AES-GCM/ChaCha20)协同生效,单独启用无效。

开启 ssl_prefer_server_ciphers on 本身不能直接“防御”加密降级攻击,但它是在 TLS 1.2 及以下协议中防止协商出弱加密套件的关键控制点——前提是它必须和协议限制、密码套件精确定义协同使用。
明确禁用不安全的协议版本
降级攻击(如 POODLE、FREAK、BEAST)大多依赖客户端或中间设备诱使服务端回退到 TLS 1.0、TLS 1.1 或 SSL 3.0。这些旧协议本身存在设计缺陷,无法靠单个指令修复。
- 必须显式关闭不安全协议:
ssl_protocols TLSv1.2 TLSv1.3; - 禁止写
TLSv1(等价于 TLSv1.0)、TLSv1.1或模糊的SSLv3等表述 - TLS 1.3 自动忽略
ssl_ciphers和该指令,所以它的安全性不依赖于此;但 TLS 1.2 协商仍需你严格把关
配置强且有序的 cipher list
ssl_prefer_server_ciphers on 的作用是让 Nginx 按你写的顺序选套件,而不是迁就客户端提出的弱选项。但如果列表里还混着 RC4、3DES、SHA1、CBC 类套件,它照样会选出来。
- 推荐只保留前向保密(PFS)+ AEAD 模式的组合,例如:
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305 - 避免使用
HIGH、!aNULL:!MD5这类宽泛表达——它们无法排除 SHA1 签名或非 PFS 套件 - 确保 3DES、DES、RC4、MD5、EXPORT、NULL、CBC-SHA 等已知风险套件完全不在列表中
确认服务器主导权真正生效
该指令只有在 server 块中与 ssl_ciphers、ssl_protocols 同时存在才起作用。常见失效场景包括:
- 在 http 块全局启用
ssl_prefer_server_ciphers on,却在某个 server 块漏配ssl_ciphers→ 该站点会回退到 OpenSSL 默认弱套件 - 多个域名共用一台 Nginx,但未为每个 server 块独立配置 cipher 策略 → 安全策略被最宽松的站点拖累
- 未验证实际协商结果:reload 后仅凭语法检查不够,要用工具确认真实握手行为
验证是否真正阻断降级路径
改完配置后,务必通过实测确认攻击面已被切断:
- 用 OpenSSL 测试 TLS 1.2 握手:
openssl s_client -connect example.com:443 -tls1_2 | grep "Cipher is"
输出应是你ssl_ciphers列表中最靠前的强套件(如ECDHE-RSA-AES128-GCM-SHA256) - 用 SSL Labs 的 SSL Server Test 全面扫描,重点关注 “Handshake Simulation” 中老旧客户端(如 Win7 IE11、Android 4.4.2)是否仍能协商出 TLS 1.0/CBC 套件
- 若扫描显示 “Weak key exchange” 或 “Weak cipher” 警告,说明某处配置未闭环,需回溯检查











