nginx 可通过分层配置同时支持 http/2 与旧 tls 客户端:前端保持现代 tls 协商,后端自动降级至 http/1.1;需满足版本要求、正确 listen 指令、弹性 ssl_protocols(如 tlsv1.1+)、兼容性加密套件,并依赖 alpn 自动回落。

要让 Nginx 同时支持 HTTP/2 并兼容旧版客户端(比如仍依赖 TLS 1.0/1.1 的嵌入式设备、老系统或特定企业内网环境),关键不是“牺牲安全换兼容”,而是分层配置:前端协议协商保持现代标准,后端连接与响应行为兼顾弹性。HTTP/2 本身不强制禁用旧 TLS,但浏览器和主流客户端会主动拒绝 TLS 1.0/1.1 上的 HTTP/2 协商——所以兼容性主要体现在 能否建立 HTTPS 连接,而非是否走 h2。
以下是实际可行、经验证的配置策略:
确保基础支持条件到位
Nginx ≥ 1.9.5(推荐 1.20+),编译含 --with-http_v2_module;OpenSSL ≥ 1.0.2(建议 1.1.1 或 3.x);证书有效且域名匹配。这些是硬门槛,缺一不可。
listen 指令必须写成一条且带 ssl + http2
listen 443 ssl http2; listen [::]:443 ssl http2;
不能拆成两行(如 listen 443 ssl; + listen 443 http2;),也不能省略 ssl —— HTTP/2 在浏览器中只允许通过 TLS 协商启用。
TLS 协议层做弹性适配
若需兼容明确依赖 TLS 1.1 的旧客户端(如某些工控系统、定制终端),可保留 TLSv1.1,但不推荐开启 TLSv1.0(已被标记为不安全):
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
注意:启用 TLSv1.1 后,HTTP/2 仍仅对支持 ALPN 且 TLS ≥ 1.2 的客户端生效;TLSv1.1 客户端会自动降级到 HTTP/1.1,不影响服务可用性。
加密套件兼顾安全与握手成功率
避免完全剔除 RSA 密钥交换(部分旧设备不支持 ECDSA),同时排除已禁用算法:
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off;
其中 DHE-RSA-* 套件为 TLS 1.1 客户端提供 fallback 能力,而所有套件均为 AEAD 类型,满足 HTTP/2 强制要求。
不干扰 ALPN 协商,但允许降级透明
ALPN 是 HTTP/2 协商核心机制,无需额外配置(Nginx 1.13+ 默认启用)。只要 OpenSSL ≥ 1.0.2,h2 就会作为 ALPN 列表首项发送。旧客户端忽略 h2 标识,自然回退到 http/1.1,整个过程对用户无感。
验证要点不止看 h2,更要看连接是否稳定回落
- 浏览器 DevTools → Network → Protocol 列:新客户端显示
h2,旧客户端应显示http/1.1且页面正常加载 - 终端测试兼容路径:
# 模拟 TLS 1.1 客户端(不协商 h2) openssl s_client -tls1_1 -connect your-domain.com:443 -servername your-domain.com 2>/dev/null | head -10 # 应返回成功握手,而非 handshake failure
- 确保
curl -I --http2 https://your-domain.com成功返回HTTP/2 200,证明 h2 主路径畅通
真正影响兼容性的往往不是 Nginx 配置,而是证书链完整性、SNI 支持、或中间网络设备(如老旧防火墙)拦截 ALPN 扩展。遇到“部分客户端打不开”,优先检查证书是否含完整 intermediate chain,以及是否被中间设备静默降级。











