resistFingerprinting 伪装时区、屏幕尺寸与字体,是 Firefox 与 Tor 的一致性反指纹防御。
大多数反指纹工具试图通过让设备"每次看起来都不一样"来隐藏你——一个全新的 Canvas 哈希值、被打乱的字体列表、随机的屏幕尺寸。Firefox 的 privacy.resistFingerprinting 偏好设置(在 Tor Browser 中始终开启)走的却是相反的路线:它让你的浏览器上报与所有其他开启同一设置的用户完全相同的一小组数值。本文将解释这种"一致性"哲学在实践中意味着什么、RFP 具体伪装了哪些内容、为什么 Tor Browser 和 Firefox 共用同一套防御引擎,以及它换来的代价是什么。
关键要点
privacy.resistFingerprinting(RFP)是 Firefox 的一项偏好设置,在普通 Firefox 中默认关闭,但在 Tor Browser 中始终开启,用于统一可被指纹识别的浏览器特征。- 它的设计目标是一致性,而非随机化:让每一个开启 RFP 的浏览器上报相同的数值,使单个实例无法从人群中被区分出来。
- 它会将时区伪装为 UTC、将窗口/屏幕尺寸取整为固定档位("letterboxing" 加边框)、在读取 Canvas 前弹出提示、限制字体枚举,并冻结上报的操作系统/User-Agent 信息。
- Tor Browser 与 Firefox 通过"Tor Uplift"项目共用同一套 RFP 代码——Tor 的反指纹研究成果最终作为通用的 Firefox 偏好设置发布。
- 代价是真实存在的:RFP 会破坏依赖精确地理位置、原生窗口尺寸或 Canvas 组件的网站。它是一件粗暴但有效的工具,并不能无缝替代日常浏览体验。
一致性哲学:融入人群,而非脱颖而出
Canvas 噪声工具及类似扩展试图通过让每次读取都"独一无二"来对抗指纹识别——每次都是全新的随机值,这样就无法计算出稳定的哈希值。我们关于 Canvas 噪声的文章 解释了这种方法为何是个陷阱:任何脚本能够检测到的随机性(比如两次读取同一 Canvas 却得到不同字节)本身就会成为一种信号——"这个浏览器正在运行隐私工具"这件事本身就具有辨识度,有时甚至比原始指纹更具辨识度。
Mozilla 的反指纹设计文档直接给出了另一种思路:与其试图隐藏一个独一无二的值,不如让浏览器彼此无法区分。如果一千万 Tor Browser 用户都上报相同的时区、相同的取整窗口尺寸、相同的字体列表,那么单条上报数据就不携带任何能把某个用户从其他人中区分出来的信息。匿名性来自人群的规模,而非来自隐藏本身。关于该项目自身对这一目标的阐述,可参见 Mozilla 的 Security/Fingerprinting 维基页面;关于指纹识别作为一种追踪技术本身的定义,可参见 MDN 的 Fingerprinting 术语条目。
这种方法只有在共享同一数值的人群足够庞大时才有效。如果只有少数用户拥有相同的一致性数值,那反而更接近一种指纹,而不是防御——这正是 RFP 以严格、狭窄的伪装方式发布,而不是做成可自定义选项的原因:用户能调整的任何选项都会把整个人群重新拆分成可区分的小群体。
RFP 具体伪装了什么
RFP 涉及一长串 API,其中影响最大的包括:
时区 → UTC。 Intl.DateTimeFormat().resolvedOptions().timeZone 和 Date.prototype.getTimezoneOffset() 无论系统时钟设置如何,都统一上报 UTC。直接从浏览器读取时区的追踪脚本将完全得不到位置信号——关于这一信号通常如何被用来识别 VPN 用户,以及为什么 RFP 选择从源头消除泄露、而不是让伪造的时区与 VPN 出口国"看起来一致",可参见《时区与语言泄露》。
窗口与屏幕尺寸取整("letterboxing")。 RFP 不会上报你的精确视口尺寸,而是将 innerWidth/innerHeight 向下取整到最近的档位(默认是 200×100 像素的倍数),并用纯色边框填充多余空间。屏幕分辨率(screen.width、screen.height)同样会被限制为取整后的窗口尺寸,而非显示器的真实分辨率。这是最容易被察觉的 RFP 效果——当浏览器窗口没有恰好落在某个档位上时,你会在内容区域周围看到灰色边框。
Canvas 读取权限提示。 RFP 不会完全屏蔽 Canvas,也不会注入噪声,而是在网站首次尝试读取 Canvas 像素时,用权限提示拦截 toDataURL() / getImageData() 调用。大多数用户默认会拒绝该提示,这会返回一个空白 Canvas——在每个开启 RFP 的浏览器上都视觉一致,既满足了一致性目标,又避免了噪声注入那种可被检测的副作用。
受限的字体枚举。 RFP 不会暴露操作系统实际安装的字体列表——这是普通指纹中信息熵最高的信号之一——而是将 document.fonts 和 CSS 字体匹配限制在浏览器内置的一份固定白名单内,与系统实际安装了什么字体无关。
冻结的 User-Agent 与 navigator 属性。 navigator.platform、navigator.oscpu、navigator.hardwareConcurrency 等字段会被伪装成一小组通用值(例如固定的 CPU 核心数),而不是你的真实硬件规格;User-Agent 字符串也会被统一为少数几种常见变体,而非反映你确切的操作系统版本。
降低的计时精度。 高精度计时器 performance.now()(以及 Date.now() 的分辨率)会被取整到更粗的时间间隔,从而关闭了本可被用来对硬件性能进行指纹识别或探测缓存行为的计时侧信道。
Tor Uplift:Firefox 与 Tor Browser 为何共用一套引擎
RFP 之所以存在于普通 Firefox 中,源于 Tor Uplift 项目——该项目致力于将 Tor Browser 的反指纹防御从一个专属于 Tor 的分支中剥离出来,作为标准的、有人持续维护的 Firefox 偏好设置发布。Tor Browser 基于 Firefox ESR 构建,并默认开启 privacy.resistFingerprinting;普通 Firefox 内置了同一套代码,但默认将其关闭,因为下文所述的代价对日常浏览而言被认为过于扰人。
共用同一套引擎带来的实际好处是:反指纹防御相关的 bug 只需在一处代码库中修复一次,两款浏览器都能受益。这也意味着,任何对 Tor Browser 的反指纹行为感到好奇的人,都可以在普通 Firefox 中通过 about:config 开启同一个偏好设置来体验完全相同的机制——这有助于在全面切换到 Tor Browser 进行日常浏览之前,先了解其中的取舍。
代价:会破坏哪些体验
一致性是一件粗暴的工具,RFP 确实会破坏一些体验:
- 依赖地理位置的网站(天气、本地搜索结果、与时区相关的日程安排)看到的是 UTC 而非你的真实时区,其行为就像你身处某个任意地点一样。
- 基于 Canvas 的界面——部分验证码、绘图工具和数据可视化组件——要么每次加载都弹出权限提示,要么在你拒绝后渲染为空白。
- 窗口尺寸显得不够精确。 Letterboxing 意味着内容区域不会精确填满窗口,部分用户会觉得这在视觉上有干扰感,尤其是在窗口尺寸比较特殊的情况下。
- 少数网站会出现异常,当它们收到一个通用的 User-Agent 或一个被取整过的硬件并发数值、而这与其预期不符时,尤其是那些进行激进浏览器嗅探的老旧网站。
这些都不是 bug——而是一致性策略本身直接带来的代价。按照 RFP 自身的逻辑,一种只有在"不可见"时才有效的防御,本身也算不上多可靠的防御。
如何验证 RFP 是否生效
如果你在 Firefox 中开启 privacy.resistFingerprinting(about:config → 搜索该偏好设置 → 设为 true),或者切换到 Tor Browser,你可以直接检验其效果,而不必仅凭字面描述来相信它。在开启前后分别运行一次 BrowserInsight 指纹检测:开启 RFP 后,你应该会看到上报的时区变为 UTC、Canvas 哈希值变为空白或触发权限提示、字体列表缩减为内置白名单,并且窗口/屏幕尺寸落在某个取整档位上,而非你显示器的原生分辨率。对比这两次结果,是直观感受一致性效果最快的方式,而不只是抽象地阅读文字描述。
常见问题
resistFingerprinting 能让我实现匿名吗?
没有任何单一设置能让你实现匿名。RFP 减少了你的浏览器自身信号在其他 RFP 用户中的区分度,但你的 IP 地址、账号登录状态和浏览行为是另外独立的追踪途径,RFP 并不涉及这些方面。Tor Browser 之所以将 RFP 与 Tor 网络配合使用,正是为了同时匿名化你的 IP 地址;仅在普通 Firefox 中单独使用 RFP,你的网络层身份依然可见。
我应该在普通 Firefox 中开启 privacy.resistFingerprinting 吗?
这取决于你的威胁模型。RFP 确实能显著降低指纹的独特性,但 letterboxing、时区伪装和字体限制在日常使用中会比较明显,并且会破坏部分网站的功能。大多数只想获得部分收益、又不想承受太多干扰的用户,会选择 Firefox 默认自带的、更轻量的增强型跟踪保护,把完整的 RFP 或 Tor Browser 留给敏感度更高的浏览场景。
为什么 Tor Browser 的内容周围会出现一圈灰色边框?
这就是 letterboxing 效果。RFP 会将你窗口上报的尺寸取整到一个固定档位,并用纯色边框填充剩余空间,这样你实际的窗口尺寸就不会作为一个独一无二的值被泄露出去。这是预期行为,不是渲染方面的 bug。
RFP 能完全阻止 Canvas 指纹识别吗?
就 Canvas 而言,实际效果上可以:默认的"先提示后拒绝"行为会返回一个空白 Canvas,在每个开启 RFP 的浏览器上都完全一致,满足了一致性目标。这与 Brave 的 farbling 等基于噪声的防御机制走的是不同路线——两种方式的比较可参见我们关于 Canvas 噪声的深度解析。


