同一套 WebRTC 代码,在家里两秒直连,换到公司却只能中继;手机从 Wi-Fi 切到 5G 后短暂恢复,又马上断开。这不是 NAT 穿透“随机”,而是每个网络对出站端口、返回来源和协议有不同规则。ICE 的任务就是在这些规则之上收集可能的路线、逐一验证,再保留当前真正可用的一对。
理解这条链路后,连接失败就不再只有“多加几个 STUN”一种处理。你可以判断是候选没收齐、信令丢了、检查包被拦、路径选错,还是网络变化后没有重新协商。
NAT 实际做了什么
局域网设备使用私有地址向外发包时,路由器把来源改成公网地址和一个临时端口,并记录怎样把回复送回来。较宽松的映射可能接受不同远端的回包;严格映射只接受刚才联系过的特定地址和端口。双方都很严格时,彼此从 STUN 得到的映射不一定能互访。
传统的“全锥形、受限锥形、端口受限、对称型”分类有助于理解,但现实设备会混合行为,企业防火墙还会叠加规则。工程上更可靠的做法是实际跑 ICE 检查,而不是先猜 NAT 名称再决定路线。
浏览器会收集哪些候选
- 主机候选:来自本机网络接口。现代浏览器可能用 mDNS 名称隐藏私有 IP,降低网页指纹风险。
- 服务器反射候选:通过 STUN 看到的公网映射,常用于跨家庭网络直连。
- 中继候选:由 TURN 分配,直接路径失败时保证可达。
- IPv6 候选:在双方和路径都支持时可绕开部分 IPv4 NAT,但仍受防火墙策略约束。
候选通过信令发给对方。Trickle ICE 会边收集边发送,通常比等全部收齐更快。应用要给每条候选标记当前会话,刷新或重新协商后拒绝旧会话的迟到候选,否则会出现偶发的状态污染。
候选对如何通过检查
两端把本地与远端候选组合成候选对,发送带认证的连通性检查。成功只表示这对地址能双向通信,随后还要选出提名对并完成 DTLS 等安全握手。优先级倾向低成本路径,但“优先”永远排在“可用”之后。
ICE 角色也要明确。一方为 controlling,另一方为 controlled;角色冲突可按协议中的随机 tie-breaker 解决。应用如果同时建立两条 PeerConnection 再互相覆盖,会把浏览器已经解决的角色问题重新制造一遍。
哪些网络更容易需要 TURN
对称或严格端口映射、运营商级 NAT 叠加家庭 NAT、公司只允许 443 出站、UDP 被封、访客 Wi-Fi 客户端隔离,都可能让直连失败。VPN 还会加入虚拟接口、改变默认路由,有时允许 WebRTC 绕过隧道,有时完全阻断。
TURN 应同时准备 UDP 与适合受限网络的 TCP/TLS 入口,常见兜底端口是 443。TCP 中继能提高可达性,却会受到队头阻塞,性能未必等同 UDP。部署多个大陆节点时,凭据下发应选择靠近用户且健康的节点,而不是让客户端依次等待很长超时。
同一局域网为什么也会失败
访客网络和 AP 隔离会禁止无线客户端互访;系统防火墙可能拦截浏览器的入站 UDP;一台设备连主路由,另一台连下级路由,地址看起来相近却跨了两个 NAT。企业终端策略也可能过滤 mDNS 或 WebRTC UDP。
这种情况下,服务端“发现到同出口设备”仍然可以成功,因为两边都能访问互联网,但主机候选之间无法通信。发现、信令和数据路径是三层独立事实,界面应分别反馈,不能把“看到设备”直接写成“局域网直连”。
网络切换后怎样恢复
浏览器上线事件只能说明系统认为有网络,不证明旧候选仍可用。应用观察 PeerConnection 状态、选中候选对和持续心跳;路径失败后先尝试 ICE restart,生成新的用户名片段与密码并重新交换描述。若对象已进入不可恢复状态,再建立新的会话。
恢复需要去重。双方同时检测失败会同时发 offer,协议应通过确定规则或协商队列合并。重试使用带抖动退避,但网络类型确实变化时可立即尝试。用户主动点过停止,就不再因 online 或 visibilitychange 自动唤醒。
收集哪些证据才有用
记录候选类型与协议、最终路径、连接阶段耗时、失败状态、ICE restart 次数和粗略网络类型即可。IP、完整 candidate 字符串、用户名片段和 TURN 凭据不进入普通分析。需要安全排查时也要脱敏并限制保留期。
复现时用两台真实浏览器,分别覆盖同 LAN、家庭宽带对移动网络、两条移动网络、VPN、公司网络和 UDP 受限环境。只在同一台电脑开两个标签页,几乎测不到穿透的真实边界。
产品应该追求什么
不是百分之百直连,而是能直连时快速直连,不能时及时走受控中继;网络切换后积极恢复,用户停止后彻底安静;状态显示当前事实,而非上一次成功路径。
在 uCopy 的连接流程中,ICE 会并行尝试候选并在必要时使用 TURN。用户不需要研究 NAT 类型,但应该得到清楚答案:正在连接、已直连、经中继,或在哪一阶段失败。