当某个 WebRTC 测试页打印出 172.20.4.15 时,它只是得知该网络中确实存在一个本地接口。这是真实的披露,但与「媒体从 VPN 出口离开」并不是同一个结论。候选发现与数据包路由是两套彼此独立的机制,而多数泄漏报告把它们合并成一个判断。你面对的是哪一种,决定了修复方式。

收集在任何数据发出之前就已完成

浏览器枚举本地接口,向 STUN 服务器发送绑定请求,并向 TURN 服务器申请分配,然后把结果作为候选行写入会话描述。这一切都在没有通话、没有媒体、也没有对端的情况下完成。因此候选列表记录的是发现过程,而不是传输过程。

现代浏览器可能把主机候选的字面地址替换成 mDNS 名称 .local,页面因此读不到私有 IP。本地网络仍然看得到解析该名称的多播查询,也就是说地址只是对应用隐藏,并没有从链路上消失。

顺序同样重要:重新加载页面会收集到新的一组候选,TURN 分配不同,反射映射也可能不同。两次结果不一致,未必意味着两套不同的配置。

三种候选,三类证据

每一行都来自不同的观测。每种类型回答不同的问题,表格按它们能证明什么、不能证明什么来区分。

CandidateDerived fromWhat it establishesWhat it cannot establish
HostAn interface on the deviceA local address exists in that networkThat the peer can reach it
Server-reflexiveA STUN binding responseHow a NAT mapped this sourceWhich exit the media will use
Peer-reflexiveA connectivity check that arrivedAn address seen by the far sideThat it was ever advertised
RelayA TURN allocationThe relay server accepted the sessionThat the relay carries the call

中继候选常被误当成用户的公网地址。它属于 TURN 服务器,它的存在只说明有中继可用,并不说明浏览器选择了它。主机候选上也有同样的误解,只是方向相反:mDNS 名称向页面隐藏了地址,而网络仍在传递那些查询。先读类型,再读取值。

被选中的那对才回答路由问题

ICE 会把每个本地候选与每个远端候选配对,对每一对执行连通性检查,然后提名胜出者。真正承载媒体的是被提名的那一对,它可以在浏览器自身的诊断信息中看到。列表里其余的一切都是落败的可能性。

胜出者告诉你路径的形状。中继到中继走 TURN 服务器,主机对留在本地网络,服务器反射对则直接穿过 NAT。这正是 VPN 检查所需的事实,而它与地址列表是两回事。两次候选列表完全相同的通话,也可能走不同的配对。

未被选中的候选同样被收集过,而收集本身就是离开本机的网络流量。最终使用了中继,并不代表在构建列表的过程中什么都没暴露。

控制项对应的是目标,而不是泄漏评分

WebRTC 的 IP 处理规范描述了几种策略:只使用承载默认路由的接口、使用所有接口,以及禁用未经代理的 UDP 以强制流量经过中继或代理。每一种都在连通性与延迟之间,换取不同形式的暴露。浏览器究竟实现哪一种、叫什么名字,随平台与版本而异。

按目标来选策略。向页面隐藏本地地址是一个目标,阻止直接的点对点流量是另一个,把每个数据包都留在隧道内是第三个。第一个主要关乎应用能知道什么,第二个关乎允许走哪条路,第三个还必须在平台或 VPN 的边界上强制实施。

无论选择哪种控制,都要验证两个部分:运行收集测试并记录候选类型,然后在真实会话中查看被选中的配对。一份干净的地址列表配上直连的媒体路径,依旧是你并不想要的路径。

相关文章