HTTP/3 到底值不值得折腾
每次聊到「给网站加速」,绕不开的话题就是 HTTP/3。它基于 QUIC(跑在 UDP 上的传输协议),主打两个卖点:0-RTT 建连和彻底消除队头阻塞。对个人站长而言,最实际的好处是——在弱网、移动网络、跨境访问场景下,首屏加载的感知速度能有可测量的提升。
但 HTTP/3 也是那种「配置细节多、坑不少、效果看场景」的技术。今天这篇不讲玄学,只讲怎么在 Nginx 上真把它跑起来:编译参数、配置块、防火墙、CDN 取舍、以及如何验证握手的的确确走的是 QUIC 而不是 TCP。
前提:Nginx 版本与 QUIC 支持
Nginx 从 1.25.0 开始提供 HTTP/3 的正式实现(早期 1.25.0 之前的那些第三方 patch 就不必用了)。但要提醒几个现实:
- Debian/Ubuntu 官方仓库里的 Nginx(通常是 1.22/1.24)不带 HTTP/3 模块。
- 要自己编译,或者用官方 nginx.org 的
nginx-quic分支/仓库。 - 编译需要 BoringSSL 或打过补丁的 OpenSSL,这不是一条 apt 命令能搞定的。
所以第一个决策点是:要不要自编译?如果你只是想用上 HTTP/3,而且已经在用 Cloudflare,那答案很明确——让 CDN 扛 HTTP/3,源站继续跑 HTTP/2。Cloudflare 免费套餐就支持 HTTP/3,客户端到 Cloudflare 走 QUIC,Cloudflare 到源站走 HTTP/2,你一行 Nginx 配置都不用改。本文后半部分也会讲这个方案。
如果你确实想自建(比如不用 CDN、或者想彻底掌控),继续往下看。
编译带 QUIC 的 Nginx
准备编译依赖:
apt-get update
apt-get install -y build-essential libpcre3-dev zlib1g-dev libssl-dev git curl
HTTP/3 的 TLS 部分需要 BoringSSL。克隆并构建(步骤较多,官方 nginx-quic 页面有完整脚本,这里给关键步骤):
# 拉取 BoringSSL
git clone --depth 1 https://github.com/google/boringssl.git
cd boringssl
mkdir build && cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=Release ..
ninja
cd ../..
# 拉取 Nginx 源码
git clone --depth 1 -b nginx-quic https://github.com/nginx/nginx.git
配置时把 --with-http_v3_module 打开,并指向 BoringSSL 源码目录:
cd nginx
./auto/configure \
--with-http_v3_module \
--with-http_v2_module \
--with-http_ssl_module \
--with-cc-opt="-I../boringssl/include" \
--with-ld-opt="-L../boringssl/build -lstdc++" \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf
make -j$(nproc)
make install
装完 nginx -V 应该能在编译参数里看到 --with-http_v3_module。看不到就说明没编进去,别急着改配置。
Nginx 配置:quic 监听块
HTTP/3 的监听语法比较特殊,需要同时开 TCP(HTTP/1.1 + HTTP/2)和 UDP(HTTP/3)两个监听,并加上 quic 标志。以下是我实测可用的最小配置:
server {
listen 443 quic reuseport;
listen 443 ssl;
http2 on;
server_name example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
# HTTP/3 必须启用 TLS 1.3
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
# 通告客户端本服务支持 HTTP/3
add_header Alt-Svc 'h3=":443"; ma=86400' always;
# QUIC 专用参数
quic_retry on;
ssl_early_data on;
location / {
root /var/www/html;
index index.html;
}
}
逐条解释几个关键点:
listen 443 quic reuseport;:UDP 监听。HTTP/3 走 UDP,这一行不能少。reuseport让多 worker 都能接收,提升并发。http2 on;:显式开启 HTTP/2(新语法,旧写法是listen 443 ssl http2;,两者混用会告警)。add_header Alt-Svc ...:这是 HTTP/3 能不能被发现的关键。浏览器第一次访问走 HTTP/2,看到这个响应头后,才知道「下次可以用 h3 连我」,后续才升级到 QUIC。没有 Alt-Svc,客户端永远不会尝试 HTTP/3。ssl_early_data on;:配合 0-RTT,让回头客首次请求就带数据,省一个往返。但要注意它和后面提到的proxy_set_header安全取舍。
防火墙:最容易忘的一步
HTTP/3 跑在 UDP 443 上。你平时开的防火墙规则十有八九只有 TCP 443。没开 UDP 443,浏览器探测 HTTP/3 会超时,然后永远回退到 HTTP/2,你还以为是配置没生效。
# ufw
ufw allow 443/udp
ufw allow 443/tcp
# 或者 iptables
iptables -A INPUT -p udp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
云服务商的安全组(阿里云/腾讯云/AWS)也要单独放行 UDP 443,安全组和系统防火墙是两套,都要配。
验证 HTTP/3 是否真的生效
这一步不做,前面全白搭。三种验证方法:
方法一:curl(需要 curl 支持 HTTP/3 编译)。普通发行版 curl 不支持 --http3,会报 option --http3: is unknown。得用支持 QUIC 的 curl:
curl --http3 -I https://example.com
# 看响应里是否有 alt-svc 头,以及连接是否走 h3
方法二:看 Alt-Svc 响应头。这是最快的一步:
curl -sI https://example.com | grep -i alt-svc
# 期望输出: alt-svc: h3=":443"; ma=86400
方法三:浏览器开发者工具。Chrome/Edge 打开 F12 → Network → 右键表头勾选「Protocol」列。刷新几次页面后,看 Protocol 列是不是显示 h3。第一次访问通常还是 h2(因为要先读到 Alt-Svc),第二次刷新才变 h3。
踩坑提醒:如果你挂了 Cloudflare 且开了代理(橙云),那 Alt-Svc 头是 Cloudflare 加的,你源站 Nginx 的配置对最终用户体验毫无影响——用户连的是 CF 的 HTTP/3。别在源站白折腾。
CDN 方案:更省心的选择
对 90% 的个人站长,我推荐这个方案:
- 源站 Nginx 保持 HTTP/2 就好,专心做业务。
- Cloudflare 面板 → Network → 打开 HTTP/3 (with QUIC) 开关。
- 客户端自动走 QUIC 到 CF 边缘,CF 用 HTTP/2 回源。
好处是零编译、零维护、全球边缘节点就近接入、还白送任播路由优化。唯一的代价是你的 HTTP/3 链路只覆盖「客户端到 CF 边缘」这一段,回源段还是 TCP——但对终端用户的感知速度提升,主要就来自前段。
如果你不想用 Cloudflare,Caddy 也是一个选项:Caddy 原生内置 HTTP/3,配置文件里一行 protocols h1 h2 h3 就搞定,不需要自编译。追求「少折腾」的站长,直接换 Caddy 反而比死磕 Nginx 编译更划算。
几个容易被忽略的细节
- 0-RTT 重放攻击:
ssl_early_data on让客户端在握手完成前就发数据,对幂等的 GET 没问题,但如果你用它保护POST接口,存在被重放的风险。Nginx 会在$ssl_early_data变量里标记,建议在后端对非幂等请求做去重校验。 - UDP 缓冲与丢包:QUIC 对 UDP 丢包敏感。内核 UDP 缓冲区小会导致高并发下丢包。可以调
net.core.rmem_max/wmem_max,并确认quic_retry on已开(它能缓解部分放大攻击与连接伪建)。 - 日志里看不到 h3:Nginx 的
$server_protocol变量对 HTTP/3 请求会记录为HTTP/3.0(或HTTP/3,取决于版本),可以用它确认流量里 h3 的占比。
小结
HTTP/3 不是银弹,但在移动端和跨境访问上是实打实的体验优化。决策路径很简单:能用 CDN 就用 CDN(Cloudflare 一个开关的事),想完全自控再上自编译(BoringSSL + nginx-quic)。无论哪条路,最后都要记住三件事:UDP 443 防火墙要开、Alt-Svc 响应头要发、浏览器 Protocol 列要验证成 h3。
技术选型的本质是性价比。对个人站,把「省下来的运维时间」投入到内容本身,往往比死磕一个协议版本带来的收益更大。HTTP/3 该用,但没必要为它把服务器玩崩。