WebRTC 泄露是什么、怎么防
分流检测显示一切正常,网页却仍然可能知道你的宽带 IP。原因通常是浏览器里的 WebRTC:它用 UDP 直接联系外部服务器,不一定经过你给浏览器设置的代理。本文讲清它怎么发生,以及在浏览器和代理客户端两侧分别怎么处理。
更新于
WebRTC 为什么会暴露 IP
WebRTC 是浏览器内置的实时通信功能,网页视频会议、语音通话、屏幕共享、部分网页游戏都靠它。两台设备想直接连上,首先要知道对方能从哪个地址找到自己,所以浏览器会收集一组“候选地址”(ICE candidate):
| 类型 | 内容 | 从哪里来 |
|---|---|---|
| host | 本机网卡上的地址,例如 192.168.1.23,或者 mDNS 随机名称 | 浏览器直接读取 |
| srflx | 你在公网上的地址,也就是路由器或运营商对外的出口 IP | STUN 服务器回报 |
| relay | 中转服务器的地址 | TURN 服务器分配,需要账号 |
srflx 是问题的关键。STUN 的工作方式很简单:浏览器向 STUN 服务器发一个 UDP 包,服务器回复“我看到你来自某某地址”。网页只需几行脚本创建一个 RTCPeerConnection,填上任意一个公开的 STUN 服务器,不需要你点任何按钮、也不弹出权限提示,就能读到这个结果。本站的 WebRTC 检测做的正是这件事,只是把结果展示给你自己看。
为什么开了代理还会泄露
大多数代理客户端默认以“系统代理”的方式工作:客户端在本机开一个 HTTP / SOCKS 端口,再告诉系统和浏览器“网页请求请发到这个端口”。浏览器会照做,但这套机制只覆盖 HTTP 和 HTTPS 请求。STUN 走的是 UDP,浏览器不会把它交给 HTTP 代理,于是它从你的网卡直接出去。
结果就是:网站通过普通请求看到的是节点 IP,通过 WebRTC 看到的却是你的宽带 IP。两者一对比,代理就形同虚设。这里要分清两件事:
- 公网 IP 泄露:srflx 地址和网站看到的 IP 不同。这是真正需要处理的问题,它暴露的是你的宽带出口和大致位置。
- 本地地址暴露:host 候选里出现 192.168.x.x、10.x.x.x 这类原始局域网地址。它不能直接定位你,但能帮网站区分同一网络里的设备,增加被追踪的可能。新版浏览器默认用 mDNS 随机名称(形如一串字符加
.local)代替,正常情况下看不到原始地址。
从代理客户端解决:TUN 模式
最彻底的办法是让代理客户端接管所有流量,而不是只接管浏览器愿意交出来的那部分。Clash Verge Rev、Mihomo Party 等客户端的 TUN 模式(有的叫“虚拟网卡模式”)会在系统里建一块虚拟网卡,把 TCP 和 UDP 都按规则处理。v2rayN 也提供 TUN 选项;手机上的 Shadowrocket、Android 上的各类客户端本来就以 VPN 方式运行,默认接管全部流量。
开启 TUN 之后还要注意三点:
- 节点要支持 UDP 转发。有的协议或节点不转发 UDP,这时 STUN 请求会失败,WebRTC 检测显示“没有拿到公网 IP”。这不算泄露,但网页视频通话可能连不上,或者只能退回较慢的方式。
- 规则对 UDP 同样生效。STUN 请求会像网页请求一样被规则分流。本站使用的小米 STUN 服务器是国内域名,规则模式下按规则直连,检测时那一条回报宽带 IP 是规则使然。任何网页都能用国内 STUN 服务器做同样的事,如果你不希望这样,就需要一条把 STUN 流量交给代理的规则,或者在浏览器里限制 WebRTC。
- 全局模式不等于不泄露。只开系统代理时,全局模式也只是把网页请求全部交给节点,WebRTC 的 UDP 照样绕开。决定 UDP 走向的是 TUN,不是规则或全局。
开了 TUN 后检测结果仍显示泄露,先确认客户端提示 TUN 已生效(部分系统需要授予管理员权限或安装服务),再确认浏览器没有用自己的代理设置覆盖系统设置。
各浏览器的设置
浏览器一侧的思路是限制 WebRTC 能用的网络路径。下表是截至本文更新时各浏览器的情况:
| 浏览器 | 默认行为 | 怎么限制 |
|---|---|---|
| Chrome | 本地地址用 mDNS 隐藏,srflx 照常收集 | 设置里没有开关,用官方扩展或企业策略 WebRtcIPHandling |
| Edge | 同 Chrome | 同 Chrome,可用策略 WebRtcLocalhostIpHandling |
| Firefox | 本地地址用 mDNS 隐藏,srflx 照常收集 | about:config 里可以细调或完全关闭 |
| Safari | 没有摄像头、麦克风权限时不提供 host 候选 | 没有关闭开关 |
| Brave | 取决于指纹保护设置 | 设置里的“WebRTC IP 处理策略” |
Chrome 和 Edge
设置界面里没有 WebRTC 开关。普通用户最简单的做法是安装 Google 官方发布的 WebRTC Network Limiter 扩展(见下一节)。管理多台电脑时,可以用企业策略统一设置:Chrome 的策略名是 WebRtcIPHandling,Edge 对应的是 WebRtcLocalhostIpHandling,取值 disable_non_proxied_udp 表示“不允许不经过代理的 UDP”。设置后可以在 chrome://policy 或 edge://policy 页面确认是否生效。
Firefox
在地址栏输入 about:config,接受风险提示后搜索下列首选项:
media.peerconnection.ice.default_address_only设为true:只使用默认路由那块网卡的地址。开着 TUN 时,默认路由就是虚拟网卡。media.peerconnection.ice.proxy_only_if_behind_proxy设为true:设置了代理时,让 WebRTC 只走代理。media.peerconnection.enabled设为false:完全关闭 WebRTC,网页再也拿不到候选地址,代价是网页通话、会议全部不能用。
Safari
Safari 默认就比较克制:没有获得摄像头或麦克风权限的网页拿不到 host 候选,自然也看不到局域网地址。srflx 地址仍然可以通过 STUN 拿到,所以在 Mac、iPhone 上同样需要代理客户端接管 UDP。“开发”菜单里的 WebRTC 选项是给网页开发者调试用的,不要为了隐私去改它。
Brave
打开 brave://settings/privacy,找到“WebRTC IP 处理策略”,选择“禁用非代理 UDP”。开启 Brave 的指纹保护后,这一项默认就是这个值。
用扩展限制 WebRTC
Chrome 网上应用店里的 WebRTC Network Limiter 由 Google 发布,安装后会改用更保守的网络选择方式:只使用默认路由的公网地址和对应的局域网地址。在扩展的选项页里勾选禁止不经代理的 UDP,WebRTC 就只能通过你设置的代理连接,代理不支持 UDP 时它会退回 TCP 或直接失败。Edge 同样可以从 Chrome 应用店安装这个扩展。
另外还有一类扩展可以一键关闭 WebRTC。选择时注意扩展需要的权限,优先用来源清楚、长期维护的扩展,用不上的扩展及时删掉。
浏览器设置和扩展只能保护这一个浏览器。电脑上的其他程序,例如桌面版会议软件、游戏客户端,仍然按代理客户端的方式联网。想全面处理,还是要靠 TUN 模式。
改完之后怎么确认
- 打开 WebRTC 检测,看“WebRTC 公网 IP”一栏:没有出现和“网站看到的 IP”不同的地址,就说明这条路已经堵上。
- 看“本地地址”一栏:显示 mDNS 随机名称或者为空都是正常的;出现原始的 192.168.x.x,说明 mDNS 保护被关掉了。
- 回到分流检测再测一次,确认 TUN 模式没有改变你原本的分流结果。
每种结论的具体含义,见检测结果怎么看里的 WebRTC 部分。