节点UDP测试怎么做?两种测法和一个最常见的假阴性

约 7 分钟读完 10 次阅读

节点UDP测试要回答的只有一个问题:你发出去的 UDP 包,有没有经过节点转发出去、再把回包带回来。最可靠的测法是通过客户端的本地 SOCKS5 端口,向公网 STUN 服务器发一个请求,看对方回报的来源 IP 是不是节点的 IP。

实际排查中,「测出来 UDP 不通」的结果里有相当一部分是假的:测试流量根本没进代理,节点本身并没有问题。所以这篇先讲清楚测试前要确认什么,再给两种能照着做的测法,最后是结果怎么读。

哪些场景离不开 UDP

大部分网页和下载走 TCP,UDP 不通时你往往察觉不到。真正受影响的是下面这些:

场景用不用 UDPUDP 不通时的表现
网页、下载主要走 TCP基本没感觉
支持 HTTP/3 的网站、YouTube优先走 QUIC(基于 UDP)浏览器自动退回 TCP,能用,首次加载可能慢一点
网络游戏大多数对战类游戏走 UDP连不上游戏服务器、匹配失败,或者干脆没走代理
语音和视频通话优先走 UDP多数会退回 TCP 中继,延迟变高;有的直接失败

如果你只刷网页、看视频,UDP 通不通影响很小。打游戏、开语音会议的人才需要认真测。

测试前先确认流量真的进了代理

Windows 的「系统代理」本质是一个 HTTP 代理设置,只有浏览器这类主动读取它的程序会用,而且走的是 TCP。游戏、语音软件发出的 UDP 包完全不经过系统代理,直接从你家的网络出去了。在这种状态下测 UDP,测到的是你自己宽带的 UDP,跟节点无关。

想让 UDP 进代理,只有两条路:

  1. 测试工具直接连客户端的 SOCKS5 端口。SOCKS5 协议有专门的 UDP 转发命令(UDP ASSOCIATE),这是下面两种测法用的方式
  2. 客户端开启 TUN 模式。TUN 会建一块虚拟网卡,所有程序的 TCP 和 UDP 都被接管,游戏和语音软件才会真正走节点

常见客户端的本地 SOCKS5 端口:

客户端默认端口说明
Clash Verge Rev7897mixed 端口,HTTP 和 SOCKS5 共用
其它 Clash / mihomo 系常见 7890同样是 mixed 端口
v2rayN10808SOCKS5 端口,10809 是 HTTP
FunMeGo PC 端2080mixed 端口,HTTP 和 SOCKS5 共用

以你客户端设置页里实际显示的为准,改过就用改过的。

方法一:NatTypeTester(Windows 图形界面)

NatTypeTester 是 GitHub 上开源的 NAT 类型检测工具,支持通过 SOCKS5 代理发 STUN 请求,正好拿来测节点 UDP。

  1. 打开 NatTypeTester,进入「设置」→「网络设置」,选「SOCKS5 代理」
  2. 「服务器」填 127.0.0.1:端口,端口按上面的表填
  3. 回到主界面,选 RFC 5780 那一页,点「测试」
  4. 看结果:「绑定测试」为 Success,并且「公网地址」显示的是节点的 IP,UDP 就是通的

「绑定测试」显示 Fail,或者等了很久没结果,说明 UDP 包发出去没有回来。

方法二:一段 Python 脚本(任何系统)

不想装软件的话,下面这段脚本只用 Python 自带的标准库,做的事情和 NatTypeTester 的绑定测试一样。保存成 udp_test.py:

import os, socket, struct, sys

PROXY = ("127.0.0.1", int(sys.argv[1]) if len(sys.argv) > 1 else 2080)
STUN = ("stun.l.google.com", 19302)

# 1. 建 TCP 控制连接,申请 UDP 转发(SOCKS5 UDP ASSOCIATE)
ctl = socket.create_connection(PROXY, timeout=5)
ctl.sendall(b"\x05\x01\x00")
if ctl.recv(2) != b"\x05\x00":
    sys.exit("代理不接受无认证的 SOCKS5 连接")
ctl.sendall(b"\x05\x03\x00\x01" + b"\x00" * 6)
rep = ctl.recv(10)
if len(rep) < 10 or rep[1] != 0:
    sys.exit("代理拒绝了 UDP 转发请求:这个代理端口不支持 UDP")
relay = (socket.inet_ntoa(rep[4:8]), struct.unpack("!H", rep[8:10])[0])
if relay[0] == "0.0.0.0":
    relay = (PROXY[0], relay[1])

# 2. 经代理给 STUN 服务器发一个 Binding 请求
tid = os.urandom(12)
stun_req = struct.pack("!HHI", 0x0001, 0, 0x2112A442) + tid
host = STUN[0].encode()
head = b"\x00\x00\x00\x03" + bytes([len(host)]) + host + struct.pack("!H", STUN[1])
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp.settimeout(5)
udp.sendto(head + stun_req, relay)
try:
    data, _ = udp.recvfrom(2048)
except socket.timeout:
    sys.exit("5 秒内没收到回包:UDP 不通")

# 3. 跳过 SOCKS5 UDP 头,解析 XOR-MAPPED-ADDRESS
atyp = data[3]
off = 10 if atyp == 1 else 22 if atyp == 4 else 7 + data[4]
msg = data[off:]
if msg[8:20] != tid:
    sys.exit("收到的不是这次请求的回包")
i = 20
while i + 4 <= len(msg):
    t, ln = struct.unpack("!HH", msg[i:i + 4])
    v = msg[i + 4:i + 4 + ln]
    if t == 0x0020 and v[1] == 1:
        port = struct.unpack("!H", v[2:4])[0] ^ 0x2112
        ip = socket.inet_ntoa(bytes(a ^ b for a, b in zip(v[4:8], b"\x21\x12\xa4\x42")))
        print(f"UDP 通了,STUN 服务器看到的来源:{ip}:{port}")
        break
    i += 4 + ln + (-ln % 4)

连上节点后,把端口号作为参数运行:

python udp_test.py 7897

输出 UDP 通了,STUN 服务器看到的来源:x.x.x.x:端口,再把这个 IP 和节点 IP 对一下。脚本假设代理不需要用户名密码,本地客户端的端口默认都是这样。

结果怎么读

看到的结果意味着什么下一步
通了,来源 IP 是节点 IP节点 UDP 正常游戏还是不走代理的话,去开客户端的 TUN 模式
通了,来源 IP 是你自家宽带的 IP测试流量没进代理检查端口是否填对、客户端是否已连接
代理拒绝了 UDP 转发请求本地这个端口不支持 UDP换成 SOCKS5 或 mixed 端口;Clash 系检查节点配置里 udp: true 有没有打开
超时,没收到回包UDP 在节点或沿途被丢弃同一节点多测两三次;稳定超时就换节点,或切到基于 UDP 设计的协议

用 mihomo 直接读 vless:// 这类链接订阅时,它会自动给节点加上 udp: true,手写的 YAML 配置就要自己检查。

三个常见误区

「网页能开、视频能看,UDP 肯定是通的」

浏览器在 QUIC 失败时会悄悄退回 TCP,所以网页和视频几乎永远能用。它们恰恰是最不能用来判断 UDP 的东西。

「NAT 类型测出来是对称型,说明节点不好」

经过代理测到的映射行为,反映的是代理服务器那一侧的 NAT 策略,很多代理服务器表现得像对称型 NAT。判断 UDP 通不通只看绑定测试;NAT 类型对游戏联机有什么影响,NAT原理与四种类型那篇单独讲过。

「测速网站跑得快,UDP 也就没问题」

多数测速网站测的是 TCP 的吞吐,跟 UDP 能不能转发没有关系。速度快和 UDP 通是两件独立的事,要分开测。

FunMeGo 客户端的情况

我们的 PC 端连上之后默认是系统代理模式,本地开一个 127.0.0.1:2080 的 mixed 端口。说一句对我们不利的实话:在这个默认模式下,游戏和语音软件的 UDP 流量不走我们的线路,原因就是上面讲的,系统代理管不到 UDP。要让它们走代理,需要在客户端里勾选「代理所有应用」,客户端会创建名为 FunMeGoTun 的虚拟网卡接管全部程序。这一步需要管理员权限,被安全软件拦住的话,客户端的环境自检会提示「未检测到 FunMeGoTun 网卡」。

另外,我们的线路内置 Hysteria2 备用协议,它本身就跑在 QUIC/UDP 上,跟主协议走完全独立的传输层,客户端里可以一键切换。两种协议下各测一次 UDP,比只测一种更能说明问题。两者的区别和切换时机见 Hysteria2是什么。

常见问题

机场 UDP 测试用什么工具?

Windows 上用 NatTypeTester,在设置里把代理设成客户端的 SOCKS5 端口;其它系统可以用本文的 Python 脚本。两者原理相同,都是经代理向 STUN 服务器发请求,看能不能收到回包。

怎么判断节点是否支持 UDP?

先看协议:Shadowsocks、Trojan、VLESS、Hysteria2 这些协议本身都支持转发 UDP,纯 HTTP 代理不支持。但协议支持不等于这个节点开了,服务端配置和沿途网络都可能把 UDP 丢掉,最终以实测为准。

代理 UDP 是什么意思?

指代理除了转发 TCP 连接,还能转发 UDP 数据包。游戏、语音通话、QUIC 都依赖它;只支持 TCP 的代理,这些应用要么不走代理,要么用不了。

UDP 不通会影响看视频吗?

一般不会。YouTube 这类网站优先用 QUIC,失败后浏览器会自动退回 TCP,你最多感觉首次加载稍慢。受影响大的是游戏和实时通话。

节点 UDP 检测通过了,游戏还是没走代理怎么办?

说明游戏的流量没有进入客户端。系统代理模式管不到游戏,需要开启客户端的 TUN 模式(在我们的 PC 端叫「代理所有应用」),再用客户端的路由日志确认游戏的域名或 IP 确实走了代理。

在线客服
正在加载...