IP 检测台

WebRTC 泄露是什么、怎么防

分流检测显示一切正常,网页却仍然可能知道你的宽带 IP。原因通常是浏览器里的 WebRTC:它用 UDP 直接联系外部服务器,不一定经过你给浏览器设置的代理。本文讲清它怎么发生,以及在浏览器和代理客户端两侧分别怎么处理。

更新于

WebRTC 为什么会暴露 IP

WebRTC 是浏览器内置的实时通信功能,网页视频会议、语音通话、屏幕共享、部分网页游戏都靠它。两台设备想直接连上,首先要知道对方能从哪个地址找到自己,所以浏览器会收集一组“候选地址”(ICE candidate):

常见的三类候选地址
类型内容从哪里来
host本机网卡上的地址,例如 192.168.1.23,或者 mDNS 随机名称浏览器直接读取
srflx你在公网上的地址,也就是路由器或运营商对外的出口 IPSTUN 服务器回报
relay中转服务器的地址TURN 服务器分配,需要账号

srflx 是问题的关键。STUN 的工作方式很简单:浏览器向 STUN 服务器发一个 UDP 包,服务器回复“我看到你来自某某地址”。网页只需几行脚本创建一个 RTCPeerConnection,填上任意一个公开的 STUN 服务器,不需要你点任何按钮、也不弹出权限提示,就能读到这个结果。本站的 WebRTC 检测做的正是这件事,只是把结果展示给你自己看。

为什么开了代理还会泄露

大多数代理客户端默认以“系统代理”的方式工作:客户端在本机开一个 HTTP / SOCKS 端口,再告诉系统和浏览器“网页请求请发到这个端口”。浏览器会照做,但这套机制只覆盖 HTTP 和 HTTPS 请求。STUN 走的是 UDP,浏览器不会把它交给 HTTP 代理,于是它从你的网卡直接出去。

系统代理模式下的两条路径 浏览器的网页请求经过系统代理端口,再经代理节点出去,网站看到节点 IP;WebRTC 的 STUN 请求是 UDP,不经过系统代理,直接从宽带出去,STUN 服务器看到宽带 IP。 浏览器 系统代理(HTTP / SOCKS) 网页请求 网站看到节点 IP STUN 看到宽带 IP WebRTC 的 UDP 请求,不经过系统代理
系统代理只接管网页请求。WebRTC 的 UDP 请求绕开它,从宽带直接出去。

结果就是:网站通过普通请求看到的是节点 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 之后还要注意三点:

  1. 节点要支持 UDP 转发。有的协议或节点不转发 UDP,这时 STUN 请求会失败,WebRTC 检测显示“没有拿到公网 IP”。这不算泄露,但网页视频通话可能连不上,或者只能退回较慢的方式。
  2. 规则对 UDP 同样生效。STUN 请求会像网页请求一样被规则分流。本站使用的小米 STUN 服务器是国内域名,规则模式下按规则直连,检测时那一条回报宽带 IP 是规则使然。任何网页都能用国内 STUN 服务器做同样的事,如果你不希望这样,就需要一条把 STUN 流量交给代理的规则,或者在浏览器里限制 WebRTC。
  3. 全局模式不等于不泄露。只开系统代理时,全局模式也只是把网页请求全部交给节点,WebRTC 的 UDP 照样绕开。决定 UDP 走向的是 TUN,不是规则或全局。

开了 TUN 后检测结果仍显示泄露,先确认客户端提示 TUN 已生效(部分系统需要授予管理员权限或安装服务),再确认浏览器没有用自己的代理设置覆盖系统设置。

各浏览器的设置

浏览器一侧的思路是限制 WebRTC 能用的网络路径。下表是截至本文更新时各浏览器的情况:

主流浏览器的 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 模式。

改完之后怎么确认

  1. 打开 WebRTC 检测,看“WebRTC 公网 IP”一栏:没有出现和“网站看到的 IP”不同的地址,就说明这条路已经堵上。
  2. 看“本地地址”一栏:显示 mDNS 随机名称或者为空都是正常的;出现原始的 192.168.x.x,说明 mDNS 保护被关掉了。
  3. 回到分流检测再测一次,确认 TUN 模式没有改变你原本的分流结果。

每种结论的具体含义,见检测结果怎么看里的 WebRTC 部分。

相关文章