同一个海外站点,在电脑上秒开,切到手机流量却要转三秒圈;换了节点之后,工具站一切正常,视频站首屏却总是先白一下。这类「看起来像节点慢、但换节点没用」的现象,有相当一部分来自一条你从来没有配置过的通道:浏览器在 UDP 443 上自己跑去试 QUIC 了。
QUIC 不是新东西,但它对国内链路的特殊性很少被讲清楚——它既不是「比 TCP 更快的协议」这种粗糙结论,也不是「运营商封了 UDP」这么简单。下面从三个可复现的探测方法开始,先确认你关心的站点到底支不支持 HTTP/3,再拆开 UDP 443 在国内链路上最尴尬的三处机制,最后给出代理环境下的四种处置方式和一套四步排查流程。文中所有命令都在一台普通 Linux 机器上真实跑过,输出原样贴出,你可以逐条重跑;涉及订阅的环节以一条常见的 IEPL 专线链路为例(比如自由猫),因为每一步操作都要落在具体的链路上。
一、先分开三个名字:QUIC、HTTP/3,以及 Hysteria2 这类「QUIC 代理」
混在一起讲是后面所有误判的源头。三个概念分别站在不同的层:
- QUIC:一套跑在 UDP 上的通用传输协议,2021 年成为标准(RFC 9000)。可靠传输、拥塞控制、加密、流多路复用这些活,过去由 TCP 加 TLS 干,现在被它一个人包了。
- HTTP/3:把 HTTP 的语义映射到 QUIC 上的结果(RFC 9114)。浏览器地址栏后面认的就是这一层,也就是你看到的「h3」。
- Hysteria2 / TUIC:另一套东西。它们是代理协议,只是借 QUIC 当运输工具,把整条代理流量塞进 UDP,应用层是自己写的,跟 HTTP 无关。
所以「我的节点是 Hysteria2,所以我就在用 HTTP/3」是错的:你访问的站点跑自己的 h3 会话,你本地到节点跑代理协议,这是两段独立的路。排查时这个区分很关键——一段出问题,不影响另一段的判断。
为什么非管不可?因为 Chromium 系和 Firefox 现在都会默认尝试 HTTP/3。浏览器拿到过一次站点宣告,就会记住「这台主机可以从 UDP 443 走」,之后每次访问都先试一次。也就是说:你不配置,它也在用;你的代理规则如果没考虑 UDP,它就走在规则外面。
二、QUIC 到底改了什么:从两次往返到一次
2.1 建立连接的成本
在 TCP 上跑 TLS 1.3,新建一条加密连接要花两段往返:先 1 个 RTT 完成 TCP 三次握手,再 1 个 RTT 完成 TLS 握手(换成 TLS 1.2 还要多一段)。QUIC 把传输握手和加密握手合并进同一个往返,首次连接 1 个 RTT,会话恢复时甚至可以 0 RTT,直接把数据带出去。
往返本身的价格由物理距离决定,跟协议无关。上海到洛杉矶的大圆距离约 10,440 公里,光在石英光纤里按每秒 20 万公里算,单程理论下限约 52 毫秒,一个往返约 104 毫秒(这是地板,不是实测值——真实海缆走线比大圆距离长)。少一次往返,就等于在首字节到达之前少等一个这个量级的时间。这条时间线怎么构成的,一条数据包的科学上网之旅里有更细的拆解。
2.2 队头阻塞被拆掉了,但只拆了一半
HTTP/2 在一条 TCP 连接上并发跑多个请求,可 TCP 并不知道这些请求是彼此独立的:一个包丢了,后面所有流都得在缓冲区里排队,这就是传输层的队头阻塞。QUIC 的每条流独立重传,一个流丢包不拖累其他流。
但注意,这只解决传输层的排队。你的代理链路如果本身走 TCP(SS、Trojan、VLESS 都是),本地看到的「h3 更快」只是站点到节点这最后一段,而跨境那一段该排队还是排队。反过来说,如果你的跨境那一段本身就架在线路形态单一的专线上(比如以纯 IEPL 专线为定位的SS-ID这类订阅),本地这段换 h2 还是 h3 带来的差别会明显变小——瓶颈已经不在这一层了。把 QUIC 当成万能的提速药,是最常见的误判之一。
2.3 连接迁移,和「切网络就断一下」
QUIC 的连接由一个独立的 Connection ID 标识,不绑在 IP 和端口上。手机从 WiFi 切到蜂窝,源地址变了,连接理论上可以迁移过去继续用。听起来很美好,实际能不能迁移成功,取决于中间那台 NAT 有没有把这条 UDP 会话留住——国内链路上的麻烦基本都出在这里,第四节展开。
2.4 加密范围:中间设备还能看到什么
QUIC 把连接层的元信息也纳入了加密保护,中间设备能直接读到的只剩外层:IP、UDP、端口。但有一处例外——TLS 的 ClientHello 里带着 SNI(你要访问的域名),在 QUIC 里同样以可解的形式出现在首个包中,除非站点启用了 ECH。也就是说,审查设备不需要解开整条 QUIC 连接,也能在首个包里拿到域名。这部分机制与 GFW 的工作原理是同一条线索。
三、动手之前:先确认站点到底支不支持 h3
改配置之前,先花两分钟做一次确认。以下三个方法互不依赖,建议至少做前两个。做探测的前提是手上有一条能正常出海的链路——只是想给探测随便找条路的话,最小成本的入门档订阅就够用了,探测本身几乎不消耗流量,没必要为它上大带宽。
3.1 方法一:读响应头里的 Alt-Svc
站点如果支持 h3,通常会在 HTTP 响应里带一条 Alt-Svc 头,一条命令就能看到:
curl -sI -m 8 https://www.cloudflare.com | grep -i '^alt-svc:'
# alt-svc: h3=":443"; ma=86400
下面是 14 个常见站点在同一台机器上跑出来的结果,输出为原文,未做整理:
| 站点 | 首个响应状态 | Alt-Svc 宣告 |
|---|---|---|
| cloudflare.com | HTTP/2 301 | h3=":443"; ma=86400 |
| www.google.com | HTTP/2 200 | h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 |
| www.youtube.com | HTTP/2 200 | h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 |
| www.zhihu.com | HTTP/2 405 | h3 与 h3-29 各带 2592000,另有 h3-Q050、quic=":443"; v="46,43" |
| www.instagram.com | HTTP/2 200 | h3=":443"; ma=86400 |
| www.amazon.com | HTTP/2 503 | h3=":443"; ma=86400 |
| github.com | HTTP/2 200 | 未宣告 |
| x.com | HTTP/2 200 | 未宣告 |
| www.netflix.com | HTTP/2 405 | 未宣告 |
| chatgpt.com | HTTP/2 403 | 未宣告 |
| www.bing.com | HTTP/2 302 | 未宣告 |
| www.baidu.com | HTTP/1.1 200 | 未宣告 |
| www.taobao.com | HTTP/2 200 | 未宣告 |
| weibo.com | HTTP/2 302 | 未宣告 |
读这张表有三个要点:
- ma 是客户端缓存秒数。ma=86400 表示这条宣告被记 24 小时,ma=2592000 是 30 天。这就是为什么你换了节点、甚至换了出口国家之后,浏览器还顽固地往旧入口试 h3:它记着上次的宣告,跟你的规则无关。
- h3-29、quic=":443" 这些是历史标签。h3-29 指第 29 版草案,quic=":443" 是更早的写法,v="46,43" 是老草案的版本号列表。它们出现只说明这套边缘节点铺得早、铺得广,不代表你还要做额外配置。
- 「未宣告」不等于「不支持」。看状态码就明白了:同一次探测里 chatgpt.com 返回 403、netflix 405、amazon 503、cloudflare 301,这些都不是正常页面。Alt-Svc 是跟着响应一起出来的,请求被拦在第一层时你根本看不到它。要下结论,换一条链路或换一个出口 IP 复测——这里顺带说一句,出口 IP 的身份本身就是另一个独立变量:机房 IP、住宅 IP、原生 IP 在站点眼里是三件不同的事,以住宅 IP、原生 IP 为定位的仙路湾这类方案处理的正是这一层,跟 h3 无关,但经常被混进同一批「打不开」的现象里。
3.2 方法二:读 DNS 里的 HTTPS/SVCB 记录
站点还可以把「我支持 h3」提前写进 DNS,就是 HTTPS 记录(类型 65,SVCB 的一种)。客户端解析域名时就能拿到 ALPN 列表,不必等第一次 HTTP 响应:
dig +short HTTPS cloudflare.com
# 1 . alpn="h3,h2" ipv4hint=104.16.132.229,104.16.133.229 ipv6hint=2606:4700::6810:84e5,2606:4700::6810:85e5
这一条有个必须知道的坑:读 ALPN 之前,先确认解析结果本身可信。在同一台机器上把解析器换成国内公共 DNS,再读一次被墙域名:
dig +short HTTPS www.google.com @223.5.5.5
# 1 . alpn="h2" ipv4hint=174.132.167.252
返回的地址跟 Google 没有任何关系,ALPN 也只剩 h2——这是一条被污染的答案。域名都答错了,附在上面的 ALPN 自然不能当判断依据。要么走可信解析(DoH/DoT),要么在已经通了出口的链路上做这件事,机制见DNS 解析与污染对抗。
3.3 方法三:看你的客户端支不支持 h3
curl -V | grep -i features
# Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd
Features 里只有 HTTP2、没有 HTTP3——这意味着这台机器上的 curl 8.5.0 根本不能用 h3 直连,上面那些 Alt-Svc 全是它用 h2 取回来的。这不是坏消息,只是提醒:发行版自带的 curl 大多没编进 HTTP/3 支持(需要 ngtcp2 或 quiche 这类库),所以「curl 测不出 h3」不等于站点不支持。要端到端确认,用浏览器最省事——DevTools 的 Network 面板里有一列 Protocol,h3 和 h2 一目了然。
四、UDP 443 为什么是最尴尬的一条路
到这里,目标站点在宣告 h3 这件事应该已经确认了。接下来的问题是:为什么它在你这条链路上总是走不通。三处机制,按出现概率排序。
4.1 运营商对 UDP 的手段比对 TCP 少,所以更粗暴
TCP 有状态、有握手、有可观测的序列号;UDP 什么都没有。这让运营商在一个方向上判断更省事——看不清内容,就按「UDP + 大流量 + 固定目标」这个粗特征做限速和丢包。它多数时候不是掐断连接,而是让你这条路径的质量悄悄掉一档:丢包率上升、突发被削平。这也是所有 QUIC 系代理协议共同的取舍,Hysteria2 之所以在丢包链路上反而更强,根子就在它不怕丢包(Hysteria2 协议指南里展开过这套逻辑)。
4.2 NAT 留不住 UDP 会话
NAT 设备靠计时器判断会话是否结束。TCP 连接有明确的开合状态,映射可以维持很久;UDP 没有连接状态,NAT 只能在空闲一段时间后把映射回收。回收之后,同一个 QUIC 连接再发包,从 NAT 出去的源端口已经变了,服务端认不出来,只能重建。这就是「切一下 WiFi 就断几秒」「手机放着不动、回来要重连」这类现象的常见来源,也是 QUIC 连接迁移在真实链路上经常打折的原因。
4.3 代理链路上多出来的一跳
这是最容易被忽略、也最容易解决的一条。绝大多数代理节点以 TCP 为主,UDP 要么没开、要么由另一套出口承担。于是浏览器打开站点之后会发生三件事:
- 浏览器按记住的 Alt-Svc 直接往 UDP 443 发包;
- 这条 UDP 如果没进代理规则,就会以你的本地 IP 直连出去——要么当场失败,要么在你完全不知情的情况下绕过代理;
- 失败之后浏览器不会立刻放弃,它会等一段时间再回落 TCP,这段时间就是你看到的「首屏空白」。
UDP 直连漏出这条风险,在AI 浏览器网络配置里也被单独列出来过,成因完全相同:UDP 没被规则覆盖。
| 你看到的现象 | 最可能的机制 | 先查什么 |
|---|---|---|
| 首屏空白一两秒后正常 | 先试 h3、被丢弃或超时,再回落 TCP | 规则里 udp 443 命中哪一条 |
| 工具站秒开、视频站一直转圈 | 视频站 h3 会话多,回落慢且反复重试 | 该站点 Alt-Svc 与节点 UDP 承载 |
| 切换 WiFi/4G 后偶发断几秒 | NAT 映射被回收,连接迁移失败 | 是否只在移动网络出现 |
| 手机流量明显比宽带差 | 运营商 UDP 处置更激进、NAT 老化更快 | 同站同节点换网络对照 |
| 个别站点完全打不开,其余正常 | UDP 443 被拒且回退路径被误拦 | REJECT 规则的范围是否过大 |
五、代理环境下的四种处置方式
目的不同,做法完全不同。先明确一件事:判断清楚你的节点到底能不能承载 UDP,再决定要不要折腾。
5.1 放行:让 h3 跟着规则走
节点侧 UDP 承载没问题时,最省事的做法是什么都别拒,把 UDP 和 TCP 放进同一套规则里。收益是省掉一次回落等待,代价是接受 UDP 路径本身的质量波动。怎么判断节点行不行?最直接的信号是看订阅里有没有 Hysteria2、TUIC 这类天然跑在 UDP 上的节点——有,说明这条链路对 UDP 是认真的。如果手上还没有这样的节点,不妨先用一份入门档订阅把「UDP 到底通不通」这件事验一遍,比如瑶瑶领先的小流量档(¥9.9/月 384GB),成本很低,验证清楚再决定要不要为 UDP 单独换一条链路。
5.2 主动屏蔽 QUIC,强制回落 TCP
如果节点 UDP 承载一般,或者你正在排查某个怪现象,更稳的做法是主动把 QUIC 关在门外,让浏览器老老实实走 TCP。这样虽然放弃了 h3 那一点连接建立优势,但换来一条可预测的路径。mihomo 里一条规则就够:
rules:
- AND,((NETWORK,udp),(DST-PORT,443)),REJECT
- MATCH,PROXY
这条规则的语法用 mihomo 自己的校验器验证过(Mihomo Meta v1.19.5):
mihomo -t -f quic-test.yaml -d ./mh_test
# level=info msg="Initial configuration complete, total time: 4ms"
# configuration file ./quic-test.yaml test is successful
规则里两个条件缺一不可:只写 NETWORK,udp 会把游戏、语音、WebRTC 一起拒掉;只写 DST-PORT,443 会把所有走 443 的 TLS 流量一起拒掉。用 AND 把两者绑在一起,命中的才只有「UDP + 443」这一种组合。
sing-box 侧写成逻辑规则,字段名取自官方 route/rule 文档:
{
"type": "logical",
"mode": "and",
"rules": [ { "network": ["udp"] }, { "port": [443] } ],
"action": "reject"
}
它的 route-options 里还有几个专门给 UDP 用的开关:udp_timeout、udp_connect、udp_disable_domain_unmapping,分别管会话超时、是否使用本地 UDP 关联、以及域名匹配失败时是否解除映射。碰到「UDP 通了但很快就断」的情况,这几个参数值得翻一遍。
5.3 浏览器侧直接关掉 QUIC
不想动代理规则、只想让某一台机器彻底别试 h3,就从浏览器下手。Chromium 系(Chrome、Edge、各种套壳浏览器)用启动参数 --disable-quic 最稳——chrome://flags 里那个 Experimental QUIC protocol 项在新版本里时有时无,找不到不是你的问题,是它已经并进核心网络栈了。Firefox 在 about:config 里把 network.http.http3.enabled 改成 false 即可。这个做法不影响规则,但只对这台机器、这个浏览器生效。
5.4 反向操作:让代理本身走 QUIC
前三招都是在「站点到节点」这一段让步。第四种思路反过来——既然 UDP 质量差是双向的,那就把代理协议本身换成 QUIC 系(Hysteria2、TUIC),用它们的抗丢包能力顶住劣质链路。代价是要接受 UDP 特征更明显这件事,取舍逻辑和第四节讲的是同一套:用抗丢包能力换掉特征上的低调。
5.5 还有一层与协议无关的变量:出口 IP 的身份
同样一条 QUIC 连接,站点对你的态度还取决于这条出路是什么身份。机房 IP、住宅 IP、原生 IP,在站点的风控系统眼里是三件不同的事:前者被标记是常态,后两者才像真实用户。这一层跟 h3、h2 完全无关——如果你遇到的症状是「能连上但站点一直要求验证」,那问题多半在这里,别再往 QUIC 上找。
| 你的场景 | 建议做法 | 原因 |
|---|---|---|
| 订阅里有 Hysteria2/TUIC 节点 | 放行 UDP,让它随规则走 | 链路对 UDP 认真,强行回落实属浪费 |
| 节点以 TCP 为主、UDP 承载不明 | REJECT udp 443,强制回落 TCP | 避免 UDP 直连漏出与长时间等待 |
| 正在排查某站点的怪现象 | 先不拒,观察日志里 udp 443 的落点 | 先定位再改,否则不知道是哪一步起的作用 |
| 同时玩联机游戏、开语音会议 | 只拒 443,绝不整段拒 UDP | 这类业务走其他端口,误伤代价大 |
| 链路 UDP 质量确实很差 | 换 QUIC 系代理协议,或改走线路形态单一的订阅 | 协议与线路两条路通向同一个目标 |
六、四步排查:到底是不是 QUIC 的问题
这套流程只做一件事——把「QUIC 相关」和「其他原因」分开。它不做测速,结论也不涉及任何速度数字。
- 固定变量。同一个站点、同一个节点、同一个时段,先把参照结果拿到手。不同时段、不同节点之间横向对比,等于什么都没测。
- 读 Alt-Svc。用第三节的方法确认这个站点确实在宣告 h3。没有宣告,那就和 QUIC 无关,直接去查别的原因。
- 看规则落点。临时把规则日志打开,访问一次目标站点,看 udp 443 到底命中了哪一条。很多「诡异现象」在这一步就结案了——你会发现它命中的是一条你以为早就删掉的规则。
- 做一次对照。临时加上 REJECT udp 443 再访问同一个站点:现象消失,说明问题确实在这条路径上;现象照旧,说明 QUIC 是无辜的,回到节点、线路、DNS 那几条线索上继续查。
还有一个成本很低的对照手段:换一条线路形态完全不同的链路复测一次。线路形态单一(比如只有专线、没有中转)的订阅,排查时变量少;如果你的订阅里同时有中转和专线两类节点,把两类各测一遍,答案通常立刻就出来了。
七、八个常见误解
- 「QUIC 一定更快」。QUIC 省的是连接建立成本,不是传输速度。首屏、多请求场景收益明显;大文件下载这类长连接场景,差别没有想象中大。
- 「HTTP/3 就是更快的 HTTP」。HTTP/3 只是换了运输工具。服务端配置差、边缘节点远,h3 一样慢。
- 「开了代理,QUIC 就用不上了」。恰恰相反——多数情况下它还在用,只是你没看见。这才是要给 UDP 写规则的原因。
- 「UDP 被限速,说明运营商封了 UDP」。限速和掐断是两回事:前者让质量掉档,后者才彻底不通。绝大多数情况是前者。
- 「关掉 QUIC 会更不安全」。h3 和 h2 走的是同一套 TLS 1.3,加密强度没有区别,SNI 在两种情况下都以可解形式出现。
- 「0-RTT 能开就开,一定更好」。0-RTT 允许重放,对幂等的 GET 请求没问题,对提交类操作有风险。
- 「quic= 和 h3= 是两回事」。上面那条知乎的宣告里两者同时出现,一个是老式写法,一个是标准标签,别把它们当成两个不同的协议。
- 「解锁流媒体靠的是协议新」。流媒体站点看的是出口 IP 的属性,跟走 h3 还是 h2 关系不大;协议在这里帮不上忙,能帮上忙的是 IP 身份那一层。
八、FAQ
Q1:用 QUIC 会不会暴露我访问了什么?
会暴露到和 HTTPS 相同的程度。SNI 在首个包里以可解形式出现(未启用 ECH 时),审查设备不需要解开整条连接就能看到域名。QUIC 解决的不是「隐藏访问目标」,而是「更快建立连接」。
Q2:为什么同一个站点,手机流量比宽带差?
两条路径对 UDP 的处置不一样:移动网络侧 NAT 老化更快、UDP 处置更激进。加上手机在 WiFi 与蜂窝之间切换时会触发地址变化,连接迁移经常失败,表现就是「断一下再重连」。
Q3:我的 Hysteria2 节点,算不算在用 HTTP/3?
不算。它用的是 QUIC 这套运输工具,承载的是代理协议,跟 HTTP/3 是两个应用层的兄弟关系。反过来看,网管侧封掉 UDP 443 会把它一起打掉,这正是这类协议必须准备 TCP 备用线路的原因。
Q4:关掉 QUIC,会不会影响 ChatGPT、YouTube 这些站?
不会。浏览器会回落到 HTTP/2,功能完全一样,只是首屏多等一个回落判断。真正影响体验的是链路质量,不是 h2 还是 h3。
Q5:怎么知道我的节点支不支持 UDP?
三个信号:订阅里有没有 Hysteria2/TUIC 节点、节点配置里 UDP 是开还是关、访问一个纯 UDP 业务(联机游戏、语音)能不能通。三者答案通常一致,不一致的那一个就是问题所在。
Q6:UDP 443 和其他 UDP 端口有什么区别?
对运营商来说都是 UDP,处置手段一样。区别在流量来源:443 上的 UDP 基本就是 QUIC/HTTP3,其他端口上跑的多是游戏、语音和视频通话。这也是屏蔽 QUIC 要精确到 443、而不能整段拒 UDP 的原因。
Q7:软路由上怎么统一处理?
在分流规则最前面加一条命中「UDP + 443」的规则即可,写法跟客户端侧一致。注意把这条规则放在业务分流规则之前,否则会被后面的兜底规则先吃掉。改完记得用内核自带的配置校验器跑一遍,再重启服务。
Q8:为什么在公司网络没问题,回家就出问题?
两个网络的 UDP 策略不同。企业网络往往直接拦掉非常规 UDP 出站,反而让浏览器迅速回落到 TCP,路径单一且稳定;家庭宽带会放行 UDP 但质量不稳,于是出现「假通」——能连上,但一会好一会坏。这类场景下主动屏蔽 QUIC 往往比放行更稳。
九、总结
把这篇收成三句话:
- QUIC 和 HTTP/3 是浏览器在用的一条独立通道,你不配置它也在跑。既然它在跑,规则里就必须有它的位置。
- UDP 443 的尴尬来自三处:UDP 被粗暴处置、NAT 留不住会话、代理链路多出一跳。前两处你改不了,第三处一条规则就能改。
- 处理顺序永远是:先确认站点支不支持 h3,再确认规则把 udp 443 送去了哪里,最后才是改配置。跳过前两步直接改,只会把问题挪个位置。