发布时间:2026-09-19 05:01 更新时间:2026-09-19 05:01 阅读量:0
证书部署完,浏览器地址栏已经是小锁,但打开开发者工具看协议那一栏,写的是 http/1.1 而不是 h2。这个问题比想象中常见,而且原因往往不在证书本身。HTTP/2 是否生效,取决于三件事:服务端有没有打开对应协议开关、TLS 握手阶段 ALPN 有没有协商成功、以及当前 Nginx 版本是否真的编译支持。下面按排查顺序讲清楚。
排查第一步不是改配置,而是确认事实。浏览器 F12 的 Network 面板里,右键表头勾选 Protocol 列,直接看每条请求是 h2 还是 http/1.1。命令行则用 curl 更干净,带 --http2 参数发起请求并打印协议版本:
curl -I --http2 https://www.example.com/
关注输出第一行,正常应显示 HTTP/2 200
想看 TLS 握手协商出的协议,用 openssl 直接问服务端
openssl s_client -connect www.example.com:443 -alpn h2,http/1.1 < /dev/null 2>/dev/null | grep -i alpn
返回 ALPN protocol: h2 才算协商成功
如果 curl 返回 HTTP/1.1,而 openssl 那行显示的是 http/1.1 或者没有 ALPN 输出,说明服务端根本没把 h2 放进 ALPN 候选列表,问题出在 Nginx 配置或编译选项上,和证书、CDN、防火墙都没关系。反过来,如果 openssl 显示 h2 但你本地 curl 仍是 1.1,那多半是 curl 自身没编译 HTTP/2 支持,或者中间有代理,以实际环境为准。
还有一种情况要排除:域名前面挂了 CDN。此时浏览器连的是 CDN 节点,节点回源才连你的服务器。CDN 侧是否开启 HTTP/2 要在 CDN 控制台设置,源站开了也没用,排查前先确认请求真正落在哪一层。
宝塔面板给网站配置 SSL 时,页面上通常有一个「HTTP/2」或多协议开关。打开它,面板会往该站点的 Nginx 配置里写入 listen 443 ssl http2; 这类指令。可以到「网站 → 设置 → 配置文件」里直接核对:
server {
listen 443 ssl http2;
server_name www.example.com;
ssl_certificate /www/server/panel/vhost/cert/www.example.com/fullchain.pem;
ssl_certificate_key /www/server/panel/vhost/cert/www.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
}
保存后记得重载,只改文件不重载是不会生效的:
nginx -t && nginx -s reload
宝塔环境下也可以直接用面板的重载按钮
这里有个版本坑必须提醒。在较老的 Nginx 版本里,HTTP/2 是通过 listen ... http2 参数在 server 块开启的;而从 Nginx 1.25.x 开始,官方引入了独立的 http2 on; 指令,老写法在新版本里会给出弃用告警,未来版本可能不再支持。所以如果你的宝塔用的是较新的 Nginx,面板又还在写老参数,就可能出现「配置里有 http2 但没生效」或者「启动时报 unknown directive」的情况。具体某个版本从哪一版开始切换,请以 Nginx 官方文档和你面板里 nginx -v 的实际版本为准,不要照抄网上的版本号。
另外要确认编译支持。Nginx 需要带 --with-http_v2_module 才能处理 HTTP/2,宝塔官方源里的 Nginx 一般默认带上,但如果是自行编译或换过第三方源,就未必。用下面命令看编译参数:
nginx -V 2>&1 | tr ' ' '\n' | grep -E 'http_v2|http_v3|openssl'
看不到 http_v2 说明当前二进制不支持 HTTP/2
如果确实没编译进去,在宝塔「软件商店 → Nginx → 设置」里切换版本或重装,比手动编译省事。重装前记得先备份现有配置,避免自定义规则丢失。
HTTP/2 在 HTTPS 场景下依靠 ALPN 扩展协商,如果服务端配置的 TLS 版本过低,协商会直接失败。现在没有理由再开 TLS 1.0/1.1,建议只保留 TLSv1.2 和 TLSv1.3。同时注意别把加密套件限得过窄,某些只支持旧套件的客户端可能在握手阶段就掉队,表现就是「有的浏览器是 h2,有的还是 1.1」。用前面那条 openssl s_client 命令多测几次,比在浏览器里反复刷新靠谱。
至于 HTTP/3,它基于 QUIC,跑在 UDP 上,和 HTTP/2 完全不是一回事。要启用至少要满足几个前提:Nginx 版本需支持 QUIC 相关指令(较新的主线版本才具备),编译时要包含 HTTP/3 模块,服务端要额外监听 UDP 443,并且证书配置需要用支持该模式的写法,同时防火墙和安全组要放行 UDP 443。缺少任何一项,配置写了也起不来。以官方文档和实际编译结果为准,别看到别人博客里的配置就直接套。
还有一点容易被忽略:HTTP/3 的首选机制依赖浏览器缓存和 Alt-Svc 响应头,第一次访问通常还是走 HTTP/2,第二次才可能切过去。测试时别只刷新一次就下结论。
小结一下排查顺序:先用 curl 和 openssl 确认协议协商结果,再核对站点配置里的 listen 指令写法是否匹配当前 Nginx 版本,最后检查编译参数和 TLS 版本设置。绝大多数「证书正常但 HTTP/2 不生效」的情况,都出在这三步里,而不是证书本身有问题。HTTP/3 属于进阶选项,建议先把 HTTP/2 跑稳再考虑。
| 📑 | 📅 |
|---|---|
| WordPress改域名后打不开:siteurl与home改错的救援步骤 | 2026-09-19 |
| Cloudflare 后真实访客 IP 丢失:CF-Connecting-IP 与 Nginx real_ip 配置 | 2026-09-19 |
| Nginx日志按天切割实操:logrotate配置与不生效排查 | 2026-09-19 |
| 宝塔面板网站目录权限怎么给:www用户与755/644取舍 | 2026-09-19 |
| Nginx上传目录禁止执行PHP:location匹配与fastcgi拦截写法 | 2026-09-18 |
| WordPress邮件发不出去:wp_mail走SMTP还是sendmail与SPF/DKIM检查 | 2026-09-20 |
| 宝塔面板FTP连不上:Pure-FTPd被动端口与权限排查 | 2026-09-20 |
| robots.txt写错导致整站被屏蔽:误写排查与sitemap配合 | 2026-09-20 |
| WordPress后台上传图片报错:权限、临时目录与尺寸限制逐项定位 | 2026-09-20 |
| Nginx缓存与浏览器缓存协同:expires、Cache-Control与强刷不生效的原因 | 2026-09-20 |