结论先给:判断一个防关联浏览器环境的隔离效果,看参数数量 没有意义,要看的是自洽性------一组互相矛盾的指纹(美国时区配中文字体列表、Windows UA 配 macOS 渲染特征),比参数少更危险。
本文给出一套可复现的测试方法:先用 CDP 采集环境的关键指纹项,再比对不同环境之间的差异与内部一致性,最后封装成一个可重复执行的自检脚本。全程使用 Playwright + CDP,不依赖任何厂商私有接口。
一、防关联浏览器需要覆盖的六类指纹参数
平台的设备指纹采集通常覆盖以下六类,这也是环境自检必须覆盖的最小集合:
|--------------|--------------------|--------------|
| 类别 | 采集内容 | 常被忽略的原因 |
| Canvas | 2D 绘图的像素级渲染差异 | 随机噪声会破坏稳定性 |
| WebGL | GPU 厂商、渲染器字符串、管线特征 | 与宣称的硬件型号容易冲突 |
| 字体列表 | 系统已安装字体的枚举结果 | 跨系统字形很难对齐 |
| AudioContext | 音频处理链路的数值特征 | 极少有人测,但稳定性好 |
| WebRTC | 内网 IP 与候选地址 | 泄露即环境失效 |
| 屏幕与时区 | 分辨率、色深、时区、语言 | 必须与 IP 归属地一致 |
前五项是"采集型"参数,第六项是"配置型"参数。前者考验环境的伪造能力,后者考验操作的严谨程度------多数环境问题出在第六项上。
二、测试环境与前置准备
测试使用 Python + Playwright,通过 CDP 调试端口连接已启动的目标环境。相比在浏览器内跑 JS,走 CDP 的好处是采集过程本身不污染被测环境的 DOM。
被测环境需要先开启调试端口。以常见的多账号隔离环境为例,多数指纹浏览器在环境配置中提供"开放调试端口"选项,启动后本地会监听一个端口;启动后读取该端口即可连接;部分产品还提供 API 方式获取端口,可省去手工步骤。
三、采集脚本:获取六类指纹
以下脚本连接指定调试端口,采集关键指纹项并输出 JSON。
四、判定:差异之外,更重要的是自洽
拿到两份 JSON 之后,建议按两级检查来做,而不是只比对差异。
第一级:环境间差异。 两份结果的 canvas、webglRenderer、audio、fonts 四项应当有明显差异。如果两环境这四项完全相同,说明这款防关联浏览器的隔离没有生效。
第二级:环境内自洽。 这一级更能发现真问题,检查三组关系:
- UA ↔ platform ↔ 渲染特征 ------ UA 声明 macOS,WebGL 渲染器却出现 Windows 常见的 SwiftShader,即为冲突
- timezone ↔ language ↔ IP 归属地 ------ 三者应指向同一区域。可以用 ipinfo.io 核对 IP 归属
- fonts ↔ 系统宣称 ------ 声称 macOS 却出现 SimSun、MS Gothic 这类 Windows 字形,是典型的自相矛盾
第二级检查不需要比对其它环境,单个环境就能做,也是日常巡检成本最低的方式。
补充一点经验:过于随机的 Canvas 噪声反而是特征。每帧都产生不同哈希的环境,与完全静态的环境一样显眼。真实设备的渲染结果在短期内应该是稳定的------这一点在很多追求"随机化"的实现里被忽略。
五、封装成可重复执行的自检脚本
把上面的检查固化,每次新建环境后跑一遍:
输出里只要出现自洽性问题或内网地址泄露,这个环境就不应该投入正式使用------无论这款指纹浏览器的参数表看起来有多完整。
六、这套方法的边界
要说明三个局限,避免过度依赖:
其一,测的是 Google 能看到的,不是平台看到的。 平台侧的采集维度与权重不公开,且会动态调整。这套脚本覆盖的是公开已知的六类,不能等同于平台的完整判定集合。
其二,通过检测不等于不会被判定关联。 设备指纹只是信号之一,账号资料、收款链路、操作行为同样是判定维度------环境干净但多个账号在同一秒执行同一动作,依然会出问题。
其三,不要高频跑。 频繁启动 RTCPeerConnection 与 Canvas 采集会产生异常行为记录,建议新环境上线前跑一次、之后按周或按变更抽查,不要做成常驻任务。
把这三点记住,这套脚本的定位就清楚了:它是一个排除明显错误的工具,不是一个给出安全保证的工具。
文中代码基于 Playwright 1.48 与 Chromium 内核验证,不同指纹浏览器的实现细节存在差异,请以各自官方文档为准。