Nginx 多实例环境下 TLS 协议统一需逐 server 块显式配置 ssl_protocols TLSv1.2 TLSv1.3;,不支持 http 块继承;须同步强化 ssl_ciphers、ssl_prefer_server_ciphers 及 TLSv1.3 的 ssl_conf_command,并逐域名用 openssl 验证。

在多实例 Nginx 环境下(如多个独立安装版本、多个虚拟主机、多个 conf 文件),统一 TLS 协议规范不能靠“一次配置、全局生效”,必须逐层落实、逐实例校验。核心原则是:协议控制只在 每个 HTTPS server 块 内有效,不存在继承或覆盖机制。
每个 HTTPS server 块必须单独配置 ssl_protocols
Nginx 不支持在 http 块中设置 ssl_protocols 来统管所有虚拟主机。哪怕你写在 /etc/nginx/nginx.conf 最顶部,该指令也完全不生效。
- 所有监听 443 并启用 SSL 的 server 块,都需显式写入:
ssl_protocols TLSv1.2 TLSv1.3; - 包括 sites-enabled/ 下的每个域名配置、Nginx Proxy Manager 自动生成的 conf、甚至 Docker 容器内挂载的自定义配置
- 漏掉任意一个,该站点就仍可协商 TLSv1.0 或 TLSv1.1,等保或 PCI DSS 扫描会直接报高危漏洞
避免常见写法错误
看似只差一个字符,实则导致策略失效:
- ❌ ssl_protocols TLSv1 TLSv1.2 TLSv1.3; —— TLSv1 是 TLSv1.0 别名,等于主动放行旧协议
- ❌ ssl_protocols TLSv1.2+; —— Nginx 不支持通配符语法,配置无效
- ❌ ssl_protocols TLSv1.2 TLSv1.3 —— 漏掉分号,nginx -s reload 会失败
- ✅ 正确写法只有这一种:ssl_protocols TLSv1.2 TLSv1.3;
配套加密套件与协商控制必须同步强化
仅限制协议版本远远不够。TLSv1.2 允许大量弱 cipher(如含 RC4、3DES、SHA1),攻击者仍可建立“合规但不安全”的连接。
- 强制使用强密钥交换与认证组合:
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384'; - 禁用所有含 MD5、SHA1、DES、3DES、RC4 的套件
- 开启服务端优先:ssl_prefer_server_ciphers on; 防止客户端绕过你的 cipher 顺序
- TLSv1.3 需额外指定:ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256;(必须放在 ssl_certificate 之后)
验证是否真正统一生效
nginx -t 只检查语法,无法验证行为。必须对每个实例、每个域名做真实连接测试:
- 检测 TLSv1.1 是否被拒绝:
openssl s_client -connect example.com:443 -tls1_1 -servername example.com
应返回 handshake failure 或连接重置 - 确认 TLSv1.2/TLSv1.3 可用:
openssl s_client -connect example.com:443 -tls1_2 -servername example.com
openssl s_client -connect example.com:443 -tls1_3 -servername example.com - 批量验证建议用脚本或工具(如 ssllabs.com 或 testssl.sh)覆盖全部域名和 IP











