通过代理传输 UDP 与 QUIC
代理可能通过 Web 检查,却仍无法承载程序需要的流量。例如,游戏可能通过代理完成登录,却无法交换游戏状态更新;网站可能正常打开,但浏览器使用的是 HTTP/2 而非 HTTP/3。这些操作需要不同的网络能力。
更全面的协议选择,见SOCKS 与 HTTP 代理。本文说明 UDP 如何通过代理到达目标、QUIC 对这条路径有何要求,以及如何确认应用正在使用预期传输方式和出口 IP。
UDP、QUIC 和 HTTP/3 分别做什么
TCP 提供有序字节流。数据丢失时,它会安排重传,并在缺口补齐前暂不向应用交付后续字节。UDP 发送彼此独立的消息,称为数据报。UDP 本身不保证交付、顺序,也不防止重复;如何处理这些情况,由使用它的软件决定。
这样,应用就可以选择不同的行为。语音应用可能丢弃到达太晚、已无法播放的音频包;游戏可能更重视最新位置更新,而不是旧更新;DNS 交互可能只包含简短的一问一答。实际传输方式取决于程序:这些例子不意味着每次通话、每款游戏或每个 DNS 请求都使用 UDP。
QUIC 是构建在 UDP 之上的传输协议。它增加了连接建立、丢失数据恢复、拥塞控制和可靠流。通过可靠 QUIC 流传输的文件,可以完整、有序地到达。数据包在 UDP 数据报内传输,并不会消除 QUIC 所提供的可靠性。
QUIC 还允许多个流共用一条连接。当一个流的数据丢失时,数据已到达的其他流可以继续。与让所有流共用一条有序 TCP 连接相比,这可以减少等待。结果仍取决于路由、丢包、服务器和客户端;仅选择 QUIC,并不保证应用更快。
HTTP/3 在 QUIC 上承载 HTTP。HTTP/1.1 和 HTTP/2 通常使用 TCP。三者都能服务 HTTPS 网站,因此地址中的 https:// 既不能标识 HTTP 版本,也不能确认使用了 UDP。
加密是独立属性。UDP 不会加密数据。QUIC 使用 TLS 1.3 为应用流量建立保护。普通 UDP 应用可能使用其他安全机制,也可能不加密载荷;通过代理转发并不会自动增加这种保护。
SOCKS5 如何承载 UDP
SOCKS5 定义了 UDP 中继:接受客户端数据报、将载荷发给目标,再返回响应的服务。客户端先通过 TCP 安排转发,随后控制连接与数据报路径并行存在。
- 客户端通过 TCP 连接 SOCKS5 服务器,并完成约定的身份验证流程。
- 客户端请求
UDP ASSOCIATE。如果代理接受,响应会提供中继地址和 UDP 端口。 - 客户端向中继发送带 SOCKS 头的数据报,其中标识目标。中继转发载荷之前移除该头部。返回响应时,中继先加上 SOCKS 头,再把数据报发回客户端。
- 使用中继期间,客户端保持 TCP 控制连接打开。关闭它,就会结束由该连接安排的 UDP 转发。控制连接与 UDP 转发之间的这种关系,称为 UDP 关联。
中继使用的地址或端口,可能不同于代理设置中填写的 TCP 端点。直接向那个熟悉的端点发送原始 UDP,并不会完成 SOCKS5 交互。仅实现 CONNECT 的客户端,可以使用 SOCKS5 传输 TCP,却缺少这里所需的流程。SOCKS4 没有定义这种 UDP 中继功能。
这解释了一种常见的部分成功情况:防火墙允许 TCP 连接和身份验证,却阻止发送到协商中继的数据报。密码有效,但应用仍收不到 UDP 响应。路径的两个部分都必须可用。
HTTP 代理能转发 UDP 吗?
普通 HTTP CONNECT 请求要求代理建立到目标的 TCP 连接,并承载字节流。它不会建立 UDP 转发。使用 TLS 连接 HTTPS 代理,可以保护该连接,但不会改变所请求隧道的类型。
HTTP 另有一种 UDP 隧道机制,通常称为 CONNECT-UDP,是 MASQUE 的组成部分。客户端和服务器兼容时,客户端请求通往 UDP 目标的隧道。代理向目标转发数据报,并将响应传回。这要求两端明确支持。
在客户端到代理的连接上,如果支持 HTTP/3 和所需扩展,HTTP 数据报可以由 QUIC DATAGRAM 帧承载。它们也可以封装为 capsule,即可靠 HTTP 流中的带帧消息,包括基于 TCP 的 HTTP/2。此时,即使路径的第一段使用 TCP,代理仍然向目标发送 UDP。
这种选择会影响时序。如果 TCP 连接丢失数据,后续字节可能等待恢复,导致其中承载的数据报延迟。隧道可能正常工作,却不适合某种实时负载。仅在程序中填写一个 http:// 代理地址,并不会启用这些额外 UDP 机制。
哪条连接使用 QUIC?
“QUIC 代理”这个说法需要结合上下文。它可能描述连接代理使用的传输方式,也可能描述应用与目标之间的连接。这是交互中的不同部分。
| QUIC 的使用位置 | 代理做什么 | 能够确认什么 |
|---|---|---|
| 客户端与代理之间 | 通过 QUIC 接受连接。例如,通过 HTTP/3 发送普通 CONNECT,仍是要求代理建立到目标的 TCP 连接。 | 到代理的连接使用 QUIC。网站连接需要单独检查。 |
| 应用与目标之间,通过 UDP 中继 | 使用 SOCKS5 UDP 转发或合适的 HTTP UDP 隧道,转发承载应用 QUIC 数据包的数据报。 | 如果整条路径正常,应用就能与目标建立 QUIC。HTTP/3 还必须由两端支持并实际选用。 |
普通 UDP 中继中,代理无需终止应用的 QUIC 连接。它只转发数据包,应用和目标仍是这次加密交互的端点。代理仍然知道流量转发到哪里,也能观察流量大小和时间。
应用支持为什么重要
程序需要实现服务提供的转发方法。一个 SOCKS5 复选框,不能说明是否支持 UDP ASSOCIATE。同样,程序可能在直接连接时支持 HTTP/3,但代理连接只支持 TCP。
Chrome 是一个具体例子:它内置的 SOCKS5 支持会代理基于 TCP 的 URL 请求,但不会通过 SOCKS5 中继 UDP。使用这个设置加载页面,无法测试服务的 UDP 中继。这项限制针对的是该特定客户端模式;其他客户端或外部路由软件可能具备不同能力。
还应检查设置的覆盖范围。同一应用中的登录、文件下载、语音和游戏交互,可能使用不同网络组件。为 Web 请求配置的代理,可能只覆盖其中一部分。系统代理设置也取决于各程序是否遵循。
重定向其他应用流量的程序,如果支持 UDP 和服务所用的转发方法,就可以把 UDP 发往代理。仅重定向 TCP 还不够。如果程序使用虚拟网络接口,路由规则会决定哪些流量进入该接口。应测试完整组合:应用、路由程序和代理端点。
回退、失败与直接连接
所需路径不可用时,结果取决于应用能力和策略。如果只问“是否打开”,下面三种结果可能看起来很相似:
| 观测结果 | 如何理解 |
|---|---|
| 操作失败 | 所需交互未完成。应在客户端、隧道建立、网络路径或目标处定位故障。 |
| 网站通过 HTTP/2 或 HTTP/1.1 打开 | 网站交互使用基于 TCP 的 HTTP 版本。Web 访问正常,但不能确认到该网站的 HTTP/3 正常。独立的到代理连接可能使用另一种传输方式。 |
| UDP 交互直接成功 | 流量没有经过预期代理路径。必须单独检查它的出口地址。 |
切换到基于 TCP 的 HTTP 版本称为回退。QUIC 不可用时,这可以保持正常浏览。客户端会打开另一条连接,QUIC 本身并不会变成 TCP。因此,禁用 QUIC 可能帮助 Web 应用使用可用的 TCP 路径,却不能为必须使用 UDP 的功能提供 UDP。
直接连接目标是一项路由决定。不支持的 UDP 并不都会直接发送:软件可能停止、尝试其他传输方式,或遵循配置的绕过规则。如果任务的全部流量都必须经过代理,应使用在该路径失败时停止的模式,并在代理不可用时检查其行为。
为什么 UDP 在建立后仍可能停止工作
端口规则与返回路径
TCP 端口 443 和 UDP 端口 443 属于不同传输协议。允许其中一个,不会开放另一个。对于 SOCKS5,客户端必须能够访问返回的 UDP 中继端点;中继也必须获准访问目标 UDP 端口。HTTP/3 可以使用 443 以外的端口,因此应检查应用实际使用的端点。
响应必须通过中继、防火墙以及可能存在的 NAT 返回。NAT 在网络之间转换地址,通常也转换端口。仅发送了一个数据报,不能证明返回路径正常。网络变化可能改变客户端公网 IP 或端口映射。SOCKS5 中继必须拒绝源 IP 与该 UDP 关联记录不符的数据报,因此地址改变后,可能需要重新建立关联。
暂停与状态过期
中继和 NAT 设备为 UDP 交互保存临时记录。暂停期间,这些记录可能过期。通话或会话最初可以正常工作,之后却失去 UDP 路径,直到客户端重新建立。保持同一出口 IP 不能防止这种情况:转发 UDP 所需状态与服务的 IP 分配,是两回事。
数据报大小与 MTU
MTU 是网络链路无需分片即可承载的最大 IP 数据包大小。一条路径可用的大小,受沿途最小限制约束,称为路径 MTU。IP、UDP 和额外隧道头部都占用包内空间。小测试消息可能通过,较大数据报却被丢弃,因此应用必须考虑完整路径及新增头部。
QUIC 路径必须能够承载至少 1,200 字节的 UDP 载荷,不计 IP 和 UDP 头部。客户端会把承载 QUIC Initial 数据包的 UDP 数据报填充到至少这个载荷大小。客户端到代理这一段的代理头部还需要额外空间。这不是建议把接口 MTU 设置为 1,200,而是在解释:为什么小型 DNS 请求和响应可能正常,较大的 QUIC 握手却无法通过。
延迟、丢包与负载
对于通话或游戏,交付时间可能与能否交付同样重要。延迟波动、丢包和包速率限制,都可能影响原本正常工作的 UDP 中继。单靠带宽不能描述这些条件。代理为路径增加一个环节;根据网络和负载不同,它既可能改善,也可能降低性能。
如何验证通过代理的 UDP 和 HTTP/3
测试实际准备使用的应用,或实现相同转发方法的客户端。有效测试应针对同一次交互,检查响应、传输方式和出口地址。
- 选择会响应所需流量的目标。使用实际应用服务器,或可控的 UDP 响应服务。对于 HTTP/3,应选择已知支持它的目标。任意 UDP 端口没有响应,并不能说明哪一部分失败。
- 确认中继或隧道已被接受。使用 SOCKS5 时,查看
UDP ASSOCIATE结果,以及返回的中继地址和端口。使用 HTTP UDP 隧道时,确认该隧道已被接受。身份验证本身不涵盖这一步。 - 完成一次请求与响应。可控的响应服务可以返回请求标识符,并记录它看到的源 IP。这样可以检查该次 UDP 交互使用的出口。单独的 Web IP 检查,只能覆盖它自己的请求。
- 对于 HTTP/3,应在与目标的交互中确认协议。在客户端或服务器连接日志中,查找 HTTP/3 或
h3,同时保留流量经过代理的证据。如果测试客户端有仅使用 HTTP/3 的模式,它可以暴露被自动回退掩盖的故障。 - 在相关条件下重复测试:实际数据报大小、持续流量,以及暂停后恢复活动。如果任务禁止直接流量,还应测试代理不可用时会发生什么。把客户端版本和连接设置与结果一起保存。
抓包可以帮助识别路由。标准 SOCKS5 UDP 转发会向协商好的中继发送数据报。HTTP UDP 隧道则可能使用外层 TCP 连接,因此第一段路径上没有 UDP,并不足以证明失败。
远程 DNS 和 ping 测试的是不同事情。代理可以为 TCP 连接查询主机名,却不转发应用的 UDP 流量。普通 ping 使用 ICMP。两种测试都不能替代在预期代理路径上观测到的 UDP 请求和响应。
何时值得选择 UDP 支持
先确定任务需要什么流量。基于 HTTP/1.1 或 HTTP/2 的网站与 API 工作,可能完全由仅支持 TCP 的代理满足。HTTP/3 测试、UDP 媒体和其他依赖 UDP 的功能,则需要合适的中继或隧道,以及能够使用它的客户端。
向服务商询问支持哪种 UDP 转发方式和客户端配置。然后检查允许的目标和端口、数据报大小限制、空闲行为,以及与负载相关的流量或包速率限制。如果 TCP 和 UDP 必须使用相同出口 IP 或位置,应在实际应用中验证。共用账户或成功通过 Web 检查,并不能证明出口行为相同。
