WebRTC泄露是浏览器中的一种漏洞:网站可以通过WebRTC的STUN/TURN机制直接查询网络接口,绕过代理服务器或VPN,从而发现用户的真实IP地址。之所以会造成这种暴露,是因为为实时通信而设计的WebRTC常常使用UDP连接访问STUN(Session Traversal Utilities for NAT)和TURN(Traversal Using Relays around NAT)服务器来建立直接的点对点连接,而这些请求可能并不会经过浏览器配置的代理。
理解WebRTC及其架构
WebRTC(Web Real-Time Communication)是一个开源项目,可在浏览器与其他客户端应用之间直接实现实时的语音、视频和数据通信。它无需中间服务器即可完成点对点数据传输,从而显著降低视频会议、文件共享和直播等应用的延迟与服务器负载。
WebRTC建立连接的关键组件包括:
- 信令服务器(Signaling Server):在建立直接连接之前,用于在对端之间交换元数据(如会话控制消息、网络配置、媒体能力)。信令过程本身并未被WebRTC标准化,可以使用多种协议(如WebSocket)。
- ICE(Interactive Connectivity Establishment):一套让对端发现并建立直接连接的框架。ICE利用STUN和TURN服务器寻找最优的通信路径。
- STUN服务器:帮助对端发现自己的公网IP地址以及所处的NAT类型。当位于NAT后的客户端向STUN服务器发送请求时,服务器会返回从互联网侧看到的该客户端的公网IP地址和端口。
- TURN服务器:在无法建立直接点对点连接时使用(例如受限NAT或防火墙)。TURN服务器充当中继,转发对端之间的全部流量。
导致IP泄露的关键,在于ICE如何收集"候选者"(candidates)——即可用于通信的潜在网络地址和端口。这些候选者包括:
- 主机候选者(Host Candidates):用户机器的本地IP地址(如
192.168.1.100、10.0.0.5)。 - 服务器自反候选者(Server Reflexive Candidates):由NAT路由器分配、通过STUN服务器发现的公网IP地址与端口映射。
- 中继候选者(Relayed Candidates):TURN服务器上的IP地址和端口,在无法直连时使用。
WebRTC泄露的机制
当浏览器发起WebRTC连接时,它会通过JavaScript API向操作系统查询本地网络接口,然后发出STUN请求以发现自己的公网IP地址。这些STUN请求通常基于UDP,往往由浏览器或底层WebRTC库直接发出,绕过了为常规网页流量配置的HTTP/SOCKS代理设置。
浏览器的RTCPeerConnection对象会直接枚举本地IP地址并发送STUN binding请求。STUN服务器的响应中包含客户端的公网IP地址。随后,这些信息(包括本地和公网IP候选者)会通过ICE候选者交换过程提供给远端对端——更关键的是,也提供给托管该WebRTC应用的网站。
即便正在使用代理或VPN,浏览器的WebRTC引擎仍可能直接、不经代理地连接STUN服务器,或直接查询本地网络接口,从而暴露用户的真实IP地址。
示例:通过JavaScript泄露IP
恶意网站或诊断网站只需几行JavaScript即可发起WebRTC连接并提取这些ICE候选者。
// 这是一个简化示例,仅用于说明。
// 真实世界中的利用涉及更复杂的候选者收集。
function getWebRTCIPs() {
return new Promise((resolve, reject) => {
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
const candidates = [];
pc.onicecandidate = (event) => {
if (event.candidate) {
const candidate = event.candidate.candidate;
// 候选者字符串示例:
// "candidate:4234997380 1 udp 2043278322 192.168.1.100 50000 typ host" (本地 IP)
// "candidate:4234997380 1 udp 2043278322 203.0.113.45 50000 typ srflx" (通过 STUN 获取的公网 IP)
const ipMatch = /(?:[0-9]{1,3}\.){3}[0-9]{1,3}/.exec(candidate);
if (ipMatch && ipMatch[0] && candidates.indexOf(ipMatch[0]) === -1) {
candidates.push(ipMatch[0]);
}
} else {
// 所有 ICE 候选者均已收集完毕
if (candidates.length > 0) {
resolve(candidates);
} else {
reject(new Error('No WebRTC IP candidates found.'));
}
}
};
pc.createDataChannel(''); // 需要一个 data channel 来触发候选者收集
pc.createOffer()
.then(offer => pc.setLocalDescription(offer))
.catch(reject);
});
}
// 用法:
// getWebRTCIPs().then(ips => console.log('Discovered IPs:', ips)).catch(error => console.error(error));
这段JavaScript代码会创建一个RTCPeerConnection并监听onicecandidate事件。每个事件都包含一个候选者字符串,其中含有IP地址(本地IP、经STUN获得的公网IP,或经TURN中继的IP)。网站可以解析这些候选者,从中提取真实IP地址。
如何识别WebRTC泄露
要判断某个代理配置是否存在WebRTC泄露风险,可以使用在线工具:
- 访问IP检测服务:在通过代理连接的状态下,打开
ipleak.net或browserleaks.com/webrtc等站点。 - 对比显示的IP:
- 代理IP:代理服务应当向互联网呈现的IP地址。
- WebRTC IP:该栏目会列出通过WebRTC发现的IP地址。
- 您的真实IP:您实际的公网IP地址,理想情况下应当被隐藏。
如果"WebRTC IP"一栏显示的是您真实的公网IP地址,说明存在WebRTC泄露。如果显示的是本地网络IP(如192.168.x.x或10.x.x.x),说明浏览器正在枚举本地接口;这未必会直接暴露您的公网IP,但仍然泄露了内部网络配置。
缓解策略
缓解WebRTC泄露需要采取专门措施,因为标准的代理配置往往并不足够。
浏览器配置与扩展
不同浏览器对WebRTC的可控程度不同:
-
Mozilla Firefox:
- 在地址栏输入
about:config。 - 搜索
media.peerconnection.enabled并将其值设为false。这会完全禁用WebRTC,可能导致部分正常网页应用无法使用。 - 或者,搜索
media.peerconnection.ice.no_host_candidates并设为true。这可以阻止浏览器暴露本地IP地址。 - 搜索
media.peerconnection.ice.default_obfuscate_host_addresses并设为true。这会混淆WebRTC上报的本地IP地址。
- 在地址栏输入
-
Google Chrome / 基于Chromium的浏览器:
- Chrome并未在
chrome://flags中提供可在不影响其他浏览器功能的前提下完全禁用WebRTC的配置开关。 - 扩展:安装专门用于阻止WebRTC泄露的浏览器扩展,例如"WebRTC Network Limiter",或配合特定过滤规则的"uBlock Origin"。这类扩展通常会修改浏览器WebRTC API的行为,以防止IP被直接暴露。
- "WebRTC Network Limiter"扩展的原理是将Chrome配置为只使用"mDNS host candidates"或"proxy-only ICE candidates",从而有效限制所收集和共享的候选者类型。
- Chrome并未在
-
Opera:
- Opera内置的VPN功能有时包含WebRTC泄露防护。启用后,它会将WebRTC流量经由VPN转发。请在
Settings > Privacy & security > VPN中检查相关设置。
- Opera内置的VPN功能有时包含WebRTC泄露防护。启用后,它会将WebRTC流量经由VPN转发。请在
操作系统层面的控制
虽然精度较低,但操作系统层面的控制同样可以限制WebRTC流量:
- 防火墙规则:封禁常用STUN/TURN端口(如3478、19302-19309)上的出站UDP流量。这可以阻止STUN请求到达外部服务器,但也可能破坏正常的WebRTC功能。
- 网络接口管理:在某些场景下,禁用特定网络适配器可以避免其IP地址被枚举,但这在日常使用中通常并不现实。
代理与VPN在WebRTC泄露防护上的差异
代理与VPN在工作方式上的根本差异,决定了它们防止WebRTC泄露的能力。
| 特性 | 浏览器代理(HTTP/SOCKS) | VPN(Virtual Private Network) |
|---|---|---|
| 工作层级 | 应用层(浏览器) | 网络层(操作系统层级) |
| 流量转发 | 转发指定的浏览器流量;可能无法转发所有协议。 | 加密并转发设备上的全部网络流量。 |
| WebRTC泄露 | 存在风险:WebRTC的STUN请求常常绕过浏览器代理设置。 | 受保护:包括WebRTC STUN请求在内的全部流量都被强制走加密隧道。 |
| IP地址暴露 | 若未专门缓解,真实IP可经WebRTC被看到。 | 真实IP通常被VPN服务器的IP所隐藏。 |
| 配置复杂度 | 相对简单(浏览器设置)。 | 需要安装客户端软件;转发系统全部流量。 |
VPN会把设备上的全部网络流量通过安全隧道加密转发,其中也包括WebRTC STUN请求产生的UDP流量。这样,暴露给外部STUN服务器的IP地址就只有VPN服务器的IP,从而有效防止WebRTC泄露。相比之下,浏览器层面的代理工作在更高层级,可能只转发TCP流量,导致UDP的WebRTC连接直接建立。
若要获得针对WebRTC泄露的稳固防护和全面隐私,全系统级的VPN方案通常比仅限浏览器的代理更有效。使用代理时,必须配合特定的浏览器配置或扩展,才能防止WebRTC暴露真实IP地址。
