http/2 在 nginx 中强制要求 tls 加密,不支持明文传输;必须在 listen 443 ssl http2; 配置下启用,并确保 tls 支持 alpn h2、tlsv1.2+ 及正确证书,否则协议协商失败。

HTTP/2 在 Nginx 中不支持明文(即非 TLS)传输,这是协议强制要求,不是配置疏漏。如果你在启用 http2 后访问 http://(非 HTTPS)地址失败,或出现连接重置、空白页、ERR_FAILED 等现象,根本原因就是试图在未加密通道上运行 HTTP/2 —— 这在标准实现中被直接拒绝,Nginx 会静默忽略 http2 指令或触发协议降级异常。
确认是否误在 HTTP 端口启用 http2
Nginx 只会在 ssl 上下文中处理 http2。若你在监听 80 端口的配置中写了:
listen 80 http2;
该 http2 参数会被完全忽略,且不会报错,但浏览器仍按 HTTP/1.1 请求,无法触发 HTTP/2 协商。更危险的是,部分客户端(如 curl 或某些测试工具)可能因协议不匹配直接断连。
✅ 正确做法是:仅在 HTTPS 的 listen 443 ssl 行后添加 http2:
listen 443 ssl http2;
同时确保该 server 块中已正确定义 ssl_certificate 和 ssl_certificate_key。
检查浏览器实际协商的协议版本
不要依赖地址栏“看起来像 HTTPS”,要验证真实协议:
- Chrome / Edge:打开开发者工具 → Network 标签页 → 刷新页面 → 查看任意请求的 Protocol 列,应显示
h2;若为http/1.1,说明未进入 HTTP/2。 - 命令行验证:
curl -I --http2 https://your-domain.com,成功返回响应头表示协商正常;若报HTTP/2 over TLS is required或连接失败,说明服务端未正确启用 HTTPS + HTTP/2 组合。 - 使用
nghttp -v https://your-domain.com(需安装 nghttp),可看到详细 ALPN 和帧交互过程,明确是否卡在 TLS 握手或协议切换阶段。
排查 TLS 配置是否满足 HTTP/2 前置条件
HTTP/2 要求 TLS 必须启用 ALPN,并通告 h2。即使开了 HTTPS,若 TLS 层不合规,HTTP/2 也无法激活:
- 运行
openssl s_client -alpn h2 -connect your-domain.com:443 -servername your-domain.com,输出中必须含ALPN protocol: h2。若显示ALPN protocol: http/1.1或无 ALPN 字样,说明 Nginx 未正确通告或 OpenSSL 版本过低(需 ≥1.0.2)。 - 检查 Nginx 配置中是否禁用了 TLSv1.2+:
ssl_protocols TLSv1.2 TLSv1.3;是最低要求,移除TLSv1.1及以下版本。 - 确认未遗漏
ssl_prefer_server_ciphers off;—— 启用该选项可能干扰 ALPN 协商,尤其在旧 OpenSSL 下。
避免常见误导性错误
有些现象看似“HTTP/2 升级失败”,实则与明文无关,需区分:
- 访问 http:// 却期望 h2 生效:不可能。HTTP/2 不允许明文,浏览器根本不会发起 h2 协商。
-
HTTPS 页面部分资源走 HTTP/1.1:可能是混合内容(如资源引用了
http://链接)、CDN 未开启 HTTP/2,或资源域名未配置 HTTPS + http2。 - ERR_HTTP2_PROTOCOL_ERROR:这不是明文问题,而是响应头非法、TLS 参数错配或帧违规,属于 HTTP/2 已启用后的运行时错误,与“是否支持明文”无因果关系。











