Chrome Release 中 --force-webrtc-ip-handling-policy 为何失效?
结论
这些现象还不足以认定“Chrome Release build 会忽略 WebRTC IP 策略”。需要先区分两个参数:
--force-webrtc-ip-handling-policy:问题引用的 content 层测试使用这个参数,读取逻辑位于content_shell。--webrtc-ip-handling-policy:Chrome 的命令行偏好映射使用这个参数,将参数值写入webrtc.ip_handling_policy。
可以通过 content_shell 实现、Chrome 参数定义和命令行偏好映射核对两者的区别。实际使用时,应查看与已安装 Chrome 版本对应的源码,开发主分支的实现不能保证适用于所有历史版本。
如果只需要配置指定 user-data-dir 内的 Profile,可以使用 Chrome 对应的参数,也可以在启动前修改目标 Profile 的 Preferences。但如果当前 Profile 的有效偏好已经是 disable_non_proxied_udp,把同一个值写入文件通常不会增加约束,仍需查明泄漏来源。
为什么参数和 Preferences 都不能单独证明执行成功
chrome://version 的 Command Line 只展示启动命令。参数出现在这里,不代表 Chrome 实现了对它的读取和处理。
如果 chrome://prefs-internals 中出现:
{
"webrtc": {
"ip_handling_policy": "disable_non_proxied_udp"
}
}
只能说明该偏好的值是 disable_non_proxied_udp。单凭这段输出,无法确认配置来源,也无法证明测试页面创建的 RTCPeerConnection 最终使用了这个值。
在所引用的 Chromium 实现中,Chrome 会读取 Profile 的 webrtc.ip_handling_policy,并将其传入渲染进程,WebRTC 随后据此配置 ICE 端口分配器。disable_non_proxied_udp 会关闭非代理 UDP,底层设置包括禁止 UDP、STUN 和 UDP relay。这条执行路径没有“仅 Debug build 生效”的条件,见偏好传递代码、WebRTC 策略处理代码和端口分配器代码。
要确定具体故障,还需要核对 Chrome 版本、实际使用的 Profile、是否存在策略覆盖,以及检测结果对应的 ICE candidate。
方法一:使用 Chrome 对应的命令行参数
先彻底退出使用 $HOME/Isolated_Chrome 的实例,再启动:
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--user-data-dir="$HOME/Isolated_Chrome" \
--profile-directory="Default" \
--proxy-server="http://127.0.0.1:10808" \
--webrtc-ip-handling-policy=disable_non_proxied_udp
这里使用不带 force- 的参数。上述 Chrome 源码会将它直接映射到目标偏好,无需扩展程序。
启动后,在 chrome://version 检查:
- Command Line 是否包含本次启动的参数。
- Profile Path 是否为
$HOME/Isolated_Chrome/Default对应的绝对路径。
user-data-dir 是用户数据根目录,其中可以包含多个 Profile。Default 是其中一个,实际使用的路径应以 Profile Path 为准,见 Chromium 用户数据目录说明。
如果已有 Chrome 进程使用该目录,再执行命令可能会复用现有实例,新参数未必会重新配置它。
方法二:启动前修改 Profile 的 Preferences
默认 Profile 的文件路径通常是:
$HOME/Isolated_Chrome/Default/Preferences
配置应写入这个文件。不要写入根目录的 Local State,也不要把企业策略名称 WebRtcIPHandling 当作 Preferences 的键名。配置片段如下:
{
"webrtc": {
"ip_handling_policy": "disable_non_proxied_udp"
}
}
如果文件已经存在,应合并修改并保留其余配置。下面的脚本需要 Python 3,执行前必须关闭所有使用该用户数据目录的 Chrome 进程。
python3 - <<'PY'
import json
import os
import shutil
import tempfile
from pathlib import Path
profile_dir = Path.home() / "Isolated_Chrome" / "Default"
prefs_path = profile_dir / "Preferences"
profile_dir.mkdir(parents=True, exist_ok=True)
data = {}
if prefs_path.exists():
data = json.loads(prefs_path.read_text(encoding="utf-8"))
shutil.copy2(prefs_path, profile_dir / "Preferences.webrtc.bak")
data.setdefault("webrtc", {})["ip_handling_policy"] = (
"disable_non_proxied_udp"
)
fd, temp_path = tempfile.mkstemp(
prefix="Preferences.",
dir=profile_dir,
)
try:
with os.fdopen(fd, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, separators=(",", ":"))
os.replace(temp_path, prefs_path)
finally:
if os.path.exists(temp_path):
os.unlink(temp_path)
print(prefs_path)
PY
然后使用相同的 --user-data-dir 和 --profile-directory 启动 Chrome。验证文件配置时,可以去掉 WebRTC 命令行参数,以免混淆配置来源。
这项修改只作用于该 Profile,属于用户偏好设置,不等同于受管理的企业策略,也不能作为不可覆盖的网络访问限制。如果在 Chrome 运行期间修改文件,改动还可能被 Chrome 退出时保存的配置覆盖。
偏好正确时,如何继续定位泄漏
检查是否存在按 URL 覆盖的策略
在 chrome://policy 中检查 WebRtcIPHandling 和 WebRtcIPHandlingUrl。
支持 WebRtcIPHandlingUrl 的版本可以按站点选择处理方式,匹配项的优先级高于通用的 WebRtcIPHandling。即使全局偏好为 disable_non_proxied_udp,也需要检查测试站点是否有覆盖规则,见 Chromium 策略变更说明。
查看具体 ICE candidate
先打开 chrome://webrtc-internals,再重新运行检测,查看新建连接的候选信息:
host:本机接口候选。srflx:服务器反射候选,常用于识别 NAT 映射后的公网地址。relay:TURN 中继候选。
记录候选的地址和协议,以及检测页显示真实公网 IP 的具体位置。如果原始候选或 SDP 中出现真实地址,也应检查 raddr 等相关字段。
“页面显示了一个地址”“浏览器收集到了一个候选”和“连接实际选用了这个候选”是不同的情况。候选暴露给页面就已经涉及隐私泄漏,但仅凭页面的汇总字段,还无法判断实际媒体路由。
核对代理出口和连接记录
127.0.0.1:10808 是本机代理入口。需要确认代理的上游出口确实不同于 ISP 公网地址,并检查代理规则是否让相关目标直连。
结合代理日志、chrome://webrtc-internals 和抓包记录,检查 Chrome 是否绕过本机代理,向外部 STUN/TURN 地址发起连接。提交 Chromium 问题报告时,应附上完整版本、最小启动命令、有效配置和候选记录,以便判断是否存在版本缺陷。
这项设置能保证什么
disable_non_proxied_udp 用于限制 WebRTC 的连接方式。HTTP 代理不承载普通 UDP;在符合相应处理模式的实现中,WebRTC 需要通过代理使用 TCP。如果网站和代理之间没有可用路径,连接可能失败,检测页也可能没有可用候选,因此未必会显示代理出口 IP,见 RFC 8828 第 5.2 节。
使用时需要注意:
- 单个 Profile 的配置需求,可以通过正确的参数或
Preferences实现。 - 如果已经有相同的有效偏好,再写一次文件不能保证修复泄漏。
- 如果要求浏览器配置失效时也绝不能直连,需要进程级网络隔离,或独立运行环境配合出口限制。
user-data-dir本身不提供网络隔离。
备注:内容仅供参考。
