PAYATHON 2026

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 本身不提供网络隔离。

备注:内容仅供参考。