TL;DR

WebRTC 通过 STUN 直接拿真实 IP,能绕过系统代理。检测:访问 ipleak.net + browserleaks.com/webrtc。修复(推荐顺序):(1)Sing-Box / Karing 开 TUN 模式(最稳);(2)Brave 浏览器或 Firefox about:config 关闭;(3)Chrome 装 WebRTC Network Limiter 扩展。做跨境业务 / 防关联场景必须修复。

WebRTC 是浏览器内置的实时通信能力(Google Meet / Discord / Whereby 都用它)。但它有一个安全副作用——能绕过系统代理直接通过 UDP 拿到本机真实 IP。这对匿名 / 防关联 / 跨境业务场景是致命的。本篇按”原理 / 检测 / 修复”三块给出完整落地方案。

WebRTC 是怎么泄露 IP 的

正常工作流程

浏览器 → STUN 服务器(如 stun.l.google.com:19302)
    ↓ 通过 UDP 请求
STUN 返回:"你的公网 IP 是 1.2.3.4,端口 54321"

浏览器把这个信息共享给对端,建立 P2P 连接

设计目的:让 NAT 后的两台机器能直连通信,不必走中转。

泄露发生的场景

你的电脑 → VPN 客户端(建立隧道)
    ↓ HTTP / HTTPS 走 VPN
浏览器 → 正常网页 → 显示 VPN 出口 IP
    ↓ 但 WebRTC 走 UDP
浏览器 → STUN(UDP)→ 真实公网 IP 被回传

如果操作系统没把 UDP 路由到 VPN 网卡(典型 OpenVPN / WireGuard 在某些配置下),WebRTC 的 UDP 直接走物理网卡,真实 IP 暴露。

内网 IP 泄露

更隐蔽的是内网 IP 暴露。WebRTC 会列举本机所有网卡,把内网 IP(192.168.x.x / 10.x.x.x)放进 ICE candidate 列表。攻击者 / 网站脚本通过 JavaScript 拿到这个 IP,可以:

  • 判断你是否在企业 / 学校网络
  • 推断你的设备指纹
  • 在防关联场景识别”同一台机器换 VPN”

怎么检测

网页检测(最简单)

打开浏览器(保持你的 VPN / 代理开着),访问:

判断标准:

  • WebRTC 检测出的 Public IP 与你的代理出口 IP 一致 → 安全
  • 显示真实公网 IP(与不开代理时相同)→ 泄露
  • 显示内网 IP(192.168.x.x)→ ICE candidate 泄露内网,做指纹的脚本能拿到

命令行检测(macOS / Linux)

# 看本机所有公网 IP
curl ifconfig.me

# 用 chromium-headless 跑 WebRTC API 抓出来
google-chrome --headless --no-sandbox \
  --dump-dom https://browserleaks.com/webrtc

修复方案 1:Sing-Box / Karing 客户端 + TUN 模式(推荐)

最稳的方案。开启 TUN 模式后,操作系统的所有流量(含 UDP)都被代理客户端接管,WebRTC 也不例外。

Karing(iOS / macOS)

  1. Karing 设置 → 系统代理 → 启用 TUN 模式
  2. 系统会请求”添加 VPN 配置”,允许
  3. 此后所有应用(含浏览器 WebRTC)都走代理

Sing-Box(Windows / Linux)

{
  "inbounds": [{
    "type": "tun",
    "tag": "tun-in",
    "interface_name": "tun0",
    "inet4_address": "172.19.0.1/30",
    "auto_route": true,
    "strict_route": true,
    "sniff": true,
    "stack": "gvisor"
  }]
}

strict_route: true 强制所有流量走 TUN,连本地 STUN 也被接管。

Hiddify

  • 开启 “TUN Mode” + “Block Direct Traffic” 选项
  • 所有 WebRTC 流量被强制走代理

实测:开 TUN 模式后再访问 ipleak.net,WebRTC 显示的 IP 与代理出口完全一致。

修复方案 2:浏览器层关闭

Brave 浏览器(最简单)

Brave 内置 WebRTC IP 拦截:

  1. Brave 设置 → 隐私和安全 → WebRTC IP 处理
  2. 选 “Default Public and Private Interfaces” → “Default Public Interface Only”
  3. 或更严:选 “Disable Non-Proxied UDP”

Firefox

在地址栏输入 about:config,搜索:

  • media.peerconnection.enabled → 设为 false(彻底关闭 WebRTC)
  • media.peerconnection.ice.default_address_only → 设为 true(只暴露公网 IP)
  • media.peerconnection.ice.no_host → 设为 true(不暴露内网 IP)

关闭后 Google Meet / Discord 网页版无法使用,但隐私场景下值得。

Chrome

Chrome 没有原生关闭选项。两条路:

A. 安装 WebRTC Network Limiter 扩展(Google 官方)

chrome://extensions → Web Store → 搜 "WebRTC Network Limiter"

设置为 default_public_interface_onlydisable_non_proxied_udp

B. 命令行启动 Chrome(不暴露内网)

google-chrome \
  --enforce-webrtc-ip-permission-check \
  --force-webrtc-ip-handling-policy=disable_non_proxied_udp

Safari

macOS Safari 默认行为较保守,通常不泄露。如果系统代理生效,WebRTC 走代理。如要强制关闭:

  • macOS 终端:defaults write com.apple.Safari WebKitWebRTCEnabled -bool false
  • 重启 Safari

iOS Safari

iOS 15+ 在系统设置 → VPN 里:

  • 选你用的 VPN 配置
  • 打开 “断开时不允许其它流量”(Kill Switch)
  • 这样 VPN 断开时 WebRTC 流量也被切断

修复方案 3:防火墙级阻断(高级用户)

如果你信不过浏览器扩展,可以在系统防火墙级别阻断 STUN UDP:

Linux iptables

# 阻断常见 STUN 端口
iptables -A OUTPUT -p udp --dport 3478 -j DROP
iptables -A OUTPUT -p udp --dport 19302 -j DROP

macOS pf

echo "block out proto udp to any port 3478" >> /etc/pf.conf
echo "block out proto udp to any port 19302" >> /etc/pf.conf
pfctl -f /etc/pf.conf -e

此方案最暴力但也最稳:连 Google Meet 都连不上。

综合建议

场景推荐方案
普通用户(防关联场景)Karing / Hiddify + TUN 模式
浏览器轻度使用Brave 浏览器 + 内置 WebRTC 拦截
重度 Firefox 用户about:config 调整三个开关
Chrome 必须用WebRTC Network Limiter 扩展
跨境电商养号TUN 模式 + 浏览器内核独立指纹
极度匿名Tor Browser(默认禁用 WebRTC)

验证修复

修复后再去 ipleak.net + browserleaks.com/webrtc 检查:

  • WebRTC 区显示的 IP 与你的代理出口 IP 一致 → 修复成功
  • 内网 IP 字段为空或显示 mDNS 占位符(如 abcd1234.local)→ 内网 IP 已隐藏

定期检测(每月一次),因为浏览器更新可能改默认行为。

节点 IP 一致性的重要性

WebRTC 泄露只是 IP 一致性问题的一部分。完整防关联要求:HTTP/HTTPS / WebRTC / DNS / IPv6 都走同一出口。要做到这一点,最简单的方法是用一份 配套订阅线路 在 Sing-Box / Karing 客户端开 TUN 模式 + IPv6 全走代理 + DNS 强制 fakeip。

相关阅读

来源与最后核对

本文最后实际验证日期:2026-05-19。