Discord 连接中卡住(RTC Connecting)怎么办?语音UDP端口排查
Discord 文字聊天一切正常,但进入语音频道一直提示“RTC Connecting”或“No Route”?打开呀深入拆解 WebRTC 底层协议、UDP 语音数据包拦截、ICE 候选连接协商与客户端 TUN 模式语音修复全解。
Discord 连接中卡住(RTC Connecting)?语音 UDP 端口与 ICE 协商排查
Discord 连接中卡住(RTC Connecting)怎么办?语音UDP排查
Answer Block
Discord 卡在 “RTC Connecting” 或 “No Route”,本质是 WebRTC 的 ICE 打洞流程没有完成。文字频道走的是 HTTPS/WSS(TCP 443),只要 TCP 能通就能收发消息;语音/视频走的是 WebRTC,媒体面默认用 UDP,端口动态落在 50000–65535 区间,信令面靠 STUN/TURN 完成 ICE 候选交换。绝大多数”文字正常、语音卡死”的场景,是代理链路只转发了 TCP,UDP 被丢弃或未被接管,导致 STUN Binding 请求发不出去、ICE 候选永远凑不齐,客户端就停在 RTC Connecting。解决路径有三条:一是让代理以 TUN/虚拟网卡模式接管全系统 UDP;二是把 Discord 语音相关域名与 UDP 端口段放行直连;三是换用支持 UDP 转发、且 NAT 类型为全锥型(Full Cone)的出口节点。排查时优先用 ping、tracert、nslookup 确认基础连通,再用浏览器 chrome://webrtc-internals 或 Discord 开发者控制台观察 ICE 候选类型(host/srflx/relay)与 STUN/TURN 是否超时。
一、文字频道和语音频道,根本不是同一条路
很多人以为”Discord 能发消息,就说明网络没问题”。这个判断在语音场景下是错的,因为两者走的是完全不同的传输栈。
文字频道:HTTPS + WSS,纯 TCP。
你打开频道列表、加载历史消息、发文字,走的是标准 HTTPS 请求和 WebSocket over TLS(WSS)。目标端口是 443,传输层是 TCP。TCP 的特点是面向连接、可靠、有重传,只要链路能建立三次握手,数据就能慢慢磨过去。代理软件对 TCP 的支持是最成熟的——HTTP CONNECT、SOCKS5 的 TCP 模式,本质都是帮你建一条 TCP 隧道。
语音/视频频道:WebRTC,媒体面是 UDP。
语音频道建立时,Discord 客户端会做几件事:
- 通过 WSS 信令通道拿到语音服务器的连接信息(包括 IP、端口、加密参数)。
- 启动 WebRTC 的 ICE 流程,收集本地候选(host candidate)、通过 STUN 服务器反射出的公网候选(srflx candidate)、以及 TURN 中继候选(relay candidate)。
- 把这些候选通过信令交换给对端/服务器,双方尝试点对点或经中继建立媒体通道。
- 媒体通道建立后,Opus 编码的语音包以 UDP 形式持续发送,端口动态分布在 50000–65535。
关键点在于:UDP 是无连接的,没有握手、没有重传、没有拥塞控制的”礼貌等待”。它要么通,要么丢。丢了你不会收到”连接失败”的明确错误,只会看到 ICE 一直凑不齐候选,界面就卡在 RTC Connecting。
所以”文字正常”只能证明 TCP 443 通,完全不能证明 UDP 通。这是两套独立的网络路径。
二、卡在 RTC Connecting / No Route 的底层原因
2.1 代理只转 TCP,UDP 被静默丢弃
这是最常见、也最容易被忽视的原因。
HTTP 代理和 SOCKS5 代理在默认配置下,只处理 TCP 流量。HTTP CONNECT 方法本身就是为 TCP 隧道设计的;SOCKS5 虽然协议上定义了 UDP ASSOCIATE 命令,但大量代理服务端和客户端实现并不支持,或者默认关闭。
结果就是:你的 Discord 客户端以为自己在通过代理发 STUN 请求,实际上这些 UDP 包在本地就被代理层拦下、丢弃,或者发出去后没有回程。STUN Binding Request 没有响应,客户端拿不到 srflx 候选;TURN 的 UDP 中继也建不起来,relay 候选同样缺失。ICE 候选列表里只剩 host candidate,而对端/服务器根本连不到你的内网地址,ICE 永远处于 checking 状态。
界面表现就是:RTC Connecting 转圈,或者过一会儿变成 No Route。
2.2 NAT 类型太严,打洞失败
即使 UDP 能出去,如果本地 NAT 是对称型(Symmetric NAT),STUN 反射出的公网端口和对端看到的端口不一致,打洞就会失败。企业网络、部分运营商 CGNAT、以及某些云主机默认网络,都可能是对称型 NAT。
这种情况下,唯一出路是 TURN 中继。但如果 TURN 的 UDP 也被阻断,就彻底没戏。
2.3 防火墙/安全软件拦截 UDP 高端口
Windows Defender 防火墙、第三方安全软件、路由器 ACL,都可能对 50000–65535 的 UDP 出站或入站做限制。尤其是入站方向,WebRTC 需要接收对端发来的 UDP 包,如果入站被拦,媒体通道建不起来。
2.4 DNS 污染或语音服务器域名解析异常
Discord 语音相关域名如果被解析到错误 IP,或者解析超时,客户端连信令都拿不到,自然卡在连接阶段。这类问题和 UDP 无关,但表现相似,排查时要区分。
三、彻底解决的黄金方案
方案一:开启 TUN 虚拟网卡模式,强制接管全系统 UDP
这是最彻底的做法。TUN 模式会在系统里创建一块虚拟网卡,把包括 UDP 在内的所有流量都路由到代理核心,由核心决定怎么转发。
Clash Meta / Mihomo 系:
- 打开配置文件,确认
tun段启用:tun: enable: true stack: system # 或 gvisor / mixed dns-hijack: - any:53 auto-route: true auto-detect-interface: true stack选system性能最好,gvisor兼容性更好。如果语音仍不通,切换 stack 试。- 以管理员/root 权限启动核心,否则创建虚拟网卡会失败。
- 启动后确认系统路由表里出现了 TUN 接口,且默认路由指向它。
sing-box:
{
"inbounds": [
{
"type": "tun",
"interface_name": "singtun0",
"auto_route": true,
"strict_route": true,
"stack": "system"
}
]
}
strict_route 能防止流量绕过 TUN,但可能影响局域网访问,按需开启。
验证 TUN 是否接管了 UDP:
- Windows:
Get-NetAdapter看是否有 TUN 虚拟网卡;route print看默认路由。 - macOS/Linux:
ifconfig或ip addr看 tun 接口;netstat -rn看路由。
TUN 模式的关键价值在于:Discord 发出的 UDP 包不再依赖应用层代理设置,而是被系统路由强制送进代理核心,核心再用支持 UDP 的协议(如 VLESS+XTLS、Hysteria2、TUIC、WireGuard)转发出去。
方案二:Discord 语音域名与端口直连
如果你有可用的直连线路,或者只想让语音走直连、其他走代理,可以把 Discord 语音相关目标加入直连规则。
需要关注的域名群(用于分流规则):
discord.com、discordapp.com、discordapp.netdiscord.gg(邀请链接)discord.media、discordstatus.com- 语音媒体服务器通常解析到
*.discord.gg或 Discord 自有的 IP 段,实际以客户端日志为准
Clash 规则示例:
rules:
- DOMAIN-SUFFIX,discord.com,DIRECT
- DOMAIN-SUFFIX,discordapp.com,DIRECT
- DOMAIN-SUFFIX,discordapp.net,DIRECT
- DOMAIN-SUFFIX,discord.gg,DIRECT
- IP-CIDR,66.22.0.0/16,DIRECT,no-resolve
- IP-CIDR,162.159.128.0/18,DIRECT,no-resolve
注意:Discord 的 IP 段会变动,且部分 IP 属于 Cloudflare 共享段,直接按 IP 直连可能误伤。更稳妥的做法是按域名分流,并让 DNS 解析走可信通道。
端口层面: 如果路由器支持,放行 50000–65535 的 UDP 出站和入站,至少放行出站。
方案三:选择支持 UDP 且 NAT 类型友好的出口节点
不是所有节点都能跑 UDP。判断标准:
- 协议支持:VLESS、VMess、Trojan 的 TCP 模式不转 UDP;需要服务端开启 UDP 支持,或用 Hysteria2、TUIC、WireGuard 这类原生 UDP 协议。
- NAT 类型:出口节点的 NAT 最好是全锥型(Full Cone)。对称型 NAT 下,即使 UDP 能出去,打洞也容易失败。
- 测试方法:用
nat类型测试工具(如基于 STUN 的检测脚本)确认出口 NAT 类型。全锥型最佳,受限锥型次之,对称型最差。
如果节点是对称型 NAT,优先依赖 TURN 中继,或换节点。
四、跨平台排查命令与操作步骤
Windows
# 基础连通
ping discord.com
nslookup discord.com
tracert discord.com
# 查看 UDP 连接与端口占用
netstat -ano -p udp | findstr "50000-65535"
# 查看路由表,确认 TUN 是否接管默认路由
route print
# 查看网卡
Get-NetAdapter
# 防火墙规则检查
Get-NetFirewallRule | Where-Object {$_.Direction -eq "Outbound" -and $_.Enabled -eq "True"} | Select-Object DisplayName,Action
Discord 客户端日志: 按 Ctrl+Shift+I 打开开发者工具,切到 Console 和 Network 标签,观察 ICE 相关日志和 WebSocket 连接状态。语音连接时能看到 RTC Connecting 对应的 ICE 状态变化。
macOS
# 基础连通
ping discord.com
dig discord.com
traceroute discord.com
# 查看 TUN 接口与路由
ifconfig | grep -A 5 utun
netstat -rn | head -20
# 查看 UDP 连接
lsof -i UDP -n -P | grep -i discord
Linux
# 基础连通
ping -c 4 discord.com
dig discord.com
traceroute discord.com
# 查看 TUN 与路由
ip addr show
ip route show
# 查看 UDP 套接字
ss -u -a -p | grep -i discord
# 抓包看 STUN 是否发出/收到
sudo tcpdump -i any -n udp port 3478 or udp port 19302
STUN 常用端口是 3478 和 19302(Google STUN)。如果抓包只看到发出的 STUN 请求、没有响应,基本可以确认 UDP 回程被阻断。
浏览器侧验证 WebRTC
打开 chrome://webrtc-internals,发起一次 Discord 语音(网页版),观察:
- ICE candidate 列表里有没有 srflx 和 relay 类型。
- 只有 host candidate,说明 STUN/TURN 都没通。
- ICE connection state 是否长期停在
checking。
五、高价值长尾 FAQ
H3:为什么我开了代理,Discord 文字能发,语音却一直 RTC Connecting?
因为文字和语音走的是两条完全不同的传输路径。文字频道用 HTTPS 和 WSS,底层是 TCP,端口 443,代理的 TCP 隧道能直接覆盖。语音频道用 WebRTC,媒体面是 UDP,端口动态分布在 50000–65535,信令面依赖 STUN/TURN 完成 ICE 候选交换。绝大多数 HTTP 代理和默认配置的 SOCKS5 代理只转发 TCP,不处理 UDP。你的 Discord 客户端发出的 STUN Binding 请求在代理层就被丢弃了,拿不到 srflx 候选,TURN 中继也建不起来,ICE 候选列表里只剩内网 host candidate,对端根本连不上,于是界面永远停在 RTC Connecting。解决办法是让代理以 TUN 模式接管全系统 UDP,或者换用原生支持 UDP 转发的协议和节点。判断方法很简单:在能复现问题时抓包看 STUN 端口 3478/19302 有没有回包,没有回包就是 UDP 路径断了。
H3:TUN 模式和系统代理模式到底差在哪,为什么 TUN 能救语音?
系统代理模式(也叫应用层代理)依赖应用主动把流量交给代理。浏览器、部分客户端会读系统代理设置,但很多应用——包括 Discord 的语音模块——并不读,或者只对 TCP 走代理。系统代理本质上是在应用层做转发,UDP 很难被完整接管。TUN 模式则是在网络层动手:它在系统里创建一块虚拟网卡,修改路由表,把默认路由指向这块网卡。这样一来,无论哪个应用、无论 TCP 还是 UDP,流量都会被强制送进代理核心,再由核心按规则转发。对 Discord 语音来说,UDP 包不再依赖应用是否”愿意”走代理,而是被系统路由强制接管。这就是 TUN 能救语音的根本原因。代价是 TUN 需要更高权限(管理员/root),且配置不当可能影响局域网访问或导致路由环路,所以 auto-route、strict_route、DNS 劫持这些参数要按需调。
H3:怎么判断我的代理节点能不能跑 Discord 语音?NAT 类型为什么重要?
判断分两层。第一层是协议层:节点用的协议是否支持 UDP 转发。VLESS、VMess、Trojan 的纯 TCP 模式不转 UDP;需要服务端显式开启 UDP,或者改用 Hysteria2、TUIC、WireGuard 这类原生基于 UDP 的协议。第二层是 NAT 层:出口节点的 NAT 类型决定了 UDP 打洞的成功率。全锥型(Full Cone)最好,任何外部主机都能通过映射端口访问到你;受限锥型次之;对称型(Symmetric)最差,每个目标地址会分配不同映射端口,STUN 反射结果和对端看到的不一致,打洞基本失败。测试方法是连上节点后,用基于 STUN 的 NAT 类型检测工具跑一遍,看返回的映射行为。如果是对称型,要么换节点,要么依赖 TURN 中继,但 TURN 中继会增加延迟且消耗服务器带宽。
H3:Discord 语音服务器域名和端口到底有哪些,分流规则该怎么写才不误伤?
Discord 的核心域名包括 discord.com、discordapp.com、discordapp.net、discord.gg、discord.media、discordstatus.com。语音媒体服务器通常解析到 Discord 自有 IP 段或 Cloudflare 段,实际 IP 会变动,所以按域名分流比按 IP 分流更稳。分流规则建议:把上述域名后缀设为直连(如果你有可用直连线路),其余流量走代理;或者反过来,只让 Discord 走代理,其余直连。端口层面,WebRTC 媒体面用 50000–65535 的 UDP,STUN 用 3478 和 19302,TURN 常用 3478、5349 以及 49152–65535。如果按 IP 分流,注意 Discord 部分 IP 与 Cloudflare 共享,直接 IP-CIDR 直连可能误伤其他 Cloudflare 站点,建议加 no-resolve 并配合域名规则使用。最稳妥的做法是先用域名分流跑通,再根据抓包结果微调。
H3:企业网络或校园网下 Discord 语音完全连不上,还有救吗?
企业网络和校园网通常有更严格的出站策略:UDP 高端口可能被完全封禁,STUN/TURN 可能被识别并阻断,深度包检测(DPI)可能直接干扰 WebRTC 流量。这种情况下,本地怎么调都很难绕过去,因为问题在出口策略。可行的思路有几个:一是走 TUN 模式 + 支持 UDP 的代理协议,把 UDP 封装进 TCP 或 TLS 隧道里出去,让防火墙只看到普通 HTTPS 流量;二是如果 TURN 的 TCP/TLS 模式(端口 443 或 5349)可用,强制 Discord 走 TURN over TCP,牺牲一点延迟换连通性;三是换网络,比如用手机热点验证是不是网络策略问题。如果手机热点下语音正常,基本可以确认是原网络的出站策略在拦 UDP。注意,任何绕过网络管理策略的操作都要遵守所在组织的使用规定。