我自己平时折腾浏览器折腾得比较多,最近手上在维护的一个小项目是 camofox-browser,简单说就是给 Firefox 做一套“迷彩服”:通过配置性裁剪、指纹伪装、网络请求拦截、容器隔离,让浏览器在默认状态下就把隐私和安全性拉高,而不是每次装完还要手动点开十几个设置项去调。
这个项目我定位得很明确——不追求大而全的隐私系统,也不搞所谓“百分百匿名”的玄学,而是要在“能不能正常用”和“少泄露多少信息”之间找到一个真正可落地的平衡点。做这个项目的原因也挺实际:我日常要在多台电脑上用 Firefox,每次重装系统都要重新配一遍隐私设置、扩展和界面样式,干脆就把整套配置固化成一个可复用的方案,取名叫 camofox-browser。
这篇文章就围绕这个项目来写,从设计思路、核心配置模块,到完整的搭建流程和我在实际使用中踩过的坑,一次性说清楚。如果你平时也比较在乎浏览器隐私,又不想把自己弄得太“原始人”,那这套东西大概率能直接抄作业。
1. 项目定位与整体设计思路
1.1 camofox-browser 到底是什么
camofox-browser 不是一个独立编译的浏览器内核,也不是某个现成开源项目的 fork,它本质上是一套针对 Firefox 的深度配置方案,包含了 user.js 配置脚本、扩展推荐清单、userChrome.css 界面样式,以及一套可重复执行的部署流程。
“camo”是迷彩,“fox”指 Firefox,组合在一起就是“给 Firefox 披上迷彩”的意思。迷彩的核心逻辑不是彻底隐形,而是融入环境、减少辨识度。对应到浏览器上就是:不搞那些一打开页面就直接报错的激进拦截,而是让浏览器在行为特征、网络请求、存储隔离这些维度上尽量和普通用户混在一起,同时把真正敏感的追踪路径切断。
整个项目的设计目标是三个:
- 降低指纹辨识度:WebGL、Canvas、字体、时区、语言、UA 等信息尽量统一或伪装。
- 减少数据外泄:第三方 Cookie、重定向追踪参数、跨站请求、隐藏跟踪器,能拦就拦。
- 保持可用性:不影响网银、邮箱、社交媒体的正常登录和使用,兼容性可以被控制在一个合理的范围内。
它适合的人群也很明确:用过 Firefox 但没深入调过的普通用户,想抄一份现成隐私配置的开发者,以及像我一样在多台设备上同步浏览器环境的重度用户。
1.2 为什么选 Firefox 而不是 Chrome
选 Firefox 不是情怀问题,而是这个方案在 Firefox 上更成立。Chrome 本身对扩展的能力限制越来越严格,MV3 之后网络请求拦截类扩展的能力被削了一大截,而且 Chrome 想在浏览器里塞广告追踪技术这件事本身就是明牌,用户作为个体很难在浏览器层面和它对抗。
Firefox 的情况则完全不一样。它在 about:config 里保留了大量核心开关,privacy.resistFingerprinting 这种整体性的反指纹开关,到现在为止 Chrome 系浏览器都没有一个对等的原生实现。再加上 userChrome.css 这种可以直接改浏览器 UI 样式的机制,让 Firefox 成了“配置型隐私方案”最理想的底座。
Mozilla 本身是拿来主义,Firefox 也依赖 Google 搜索合作收入,这确实不假。但单从技术架构和可定制性角度说,Firefox 依然是主流浏览器里最适合被用户改造成“自己想要的形状”的那一个。用偏好设置、脚本、扩展组合,就能完成一个类似企业级安全浏览器才具备的隐私基线,这一点是 camofox-browser 项目成立的前提。
1.3 设计原则与边界
做这套配置之前,我给自己定了三条原则,到现在也没有改过。
第一,所有改动必须可回滚。user.js 被替换后可以用 about:config 手动恢复,扩展随时可以停用,userChrome.css 删掉文件就还原默认界面。不做任何需要重新编译或用脚本注入 dll 之类的不可逆操作。
第二,默认配置保持克制。真正激进的设置项不会默认开启,而是放在配置文件的注释里,按需手动打开。比如 Canvas 指纹的“白名单”模式、WebRTC 的完全禁用等,这些会直接影响部分网页功能的开关,我不会替用户做激进决定。
第三,不依赖任何“商用隐私服务”。所有配置都是本地生效的,不需要注册账号,不需要加一个永远在线的中间服务器。因为一旦依赖外部服务,这个服务的运营方就掌握了用户所有流量的元数据,相当于把隐私从一个坑挪到另一个坑。
至于边界,camofox-browser 从一开始就不承诺“完全匿名”。浏览器层面能做的只是降低信息的暴露程度,真要对抗有国家级能力的追踪体系,那已经不是浏览器配置能解决的问题了。明确这个边界很重要,否则用户容易对隐私保护产生不切实际的预期。
2. 核心配置模块拆解
2.1 指纹伪装层:统一数字身份的第一步
指纹伪装是 camofox-browser 的重头戏,也是 Firefox 区别于其他浏览器最大的优势所在。先说结论:指纹伪装的目标不是让每个用户都不同,而是让所有打开这个配置的用户看起来尽量相同,这样指纹数据库里的分类就会变得没有区分度。
Firefox 的 about:config 里,privacy.resistFingerprinting 这一个开关就能覆盖大部分常见指纹维度。把它设成 true 之后,浏览器会默认做这几件事:
- 时区统一为 UTC,和真实时区解耦。
- 操作系统平台和 UA 信息做整体偏移,减少真实环境信息。
- 字体列表被裁剪和伪造,网页无法枚举完整字体列表。
- Canvas、WebGL、AudioContext 等接口的输出会被加入可识别的噪声。
- 部分 API 的精度被降低,比如 performance.now() 的时间精度,避免高精度计时被用来做侧信道追踪。
实测下来,把 resistFingerprinting 打开之后,大部分在线指纹测试网站都会给出“你的指纹不唯一”或“大量用户具有相同指纹”的结论。这就是我想要的效果——不是变成另一个人,而是变成一群人。
但这里有一个坑需要说清楚:resistFingerprinting 会强制第一方隔离(First Party Isolation),也就是说每个网站默认都会被隔离开,无法通过浏览器直接获取其他网站的 Cookie 和登录状态。这在绝大多数场景下是好事,但如果你有“在一个网站里通过第三方登录另一个网站”的需求,就会受到限制。这种情况我在后面“常见问题”章节里再展开讲。
2.2 网络请求控制层:减少数据外泄
指纹伪装做的是“往外看”的信息伪装,网络请求控制层做的是“往上走”的数据拦截。这两个是互补关系,缺一个都不完整。
我在这套配置里固定用四个扩展,分别负责不同的拦截维度:
- uBlock Origin:网络请求过滤器,拦截广告域名、追踪域名、恶意域名。这是整个拦截体系的中枢。
- LocalCDN:把网页中引用的公共 CDN 资源改为从本地缓存读取。很多网页在加载时会去请求 googleapis、cdnjs 这些外部域名,即使你不是 Google 用户,这个请求本身就暴露了你的 IP 和访问的站点。LocalCDN 直接掐掉了这类外联请求。
- ClearURLs:自动清理 URL 中的追踪参数,比如 Facebook 的 fbclid、Google 的 gclid、各类短链跳转里加上的 campaign 参数等。这些参数的价值就在于把“你是从哪跳过来的”这件事告诉网站主。
- Privacy Badger:作为兜底,检测前三个扩展可能漏掉的“学习型”追踪器。它会在发现某个域名在所有站点上都在请求数据时,自动学会拦截它。
这里说说我的实际体验:uBlock Origin 和 ClearURLs 的过滤规则是静态的、基于列表的,而 Privacy Badger 的行为模型是动态的,所以两者的拦截结果会出现差异。比如某个新出现的追踪脚本,在 filter list 被更新之前,只有 Privacy Badger 能拦住。反过来,如果某个合法网站的资源域名恰好被广告列表误伤,靠 filter list 的扩展会直接拦截,而 Privacy Badger 可能因为该域名只在当前站点出现而选择放行。正是这种互补性,让我一直没有把这几个扩展精简掉。
2.3 容器隔离层:多身份同时在线
Firefox 的多账户容器(Multi-Account Containers)是我认为它被低估得最严重的一个功能。简单理解,容器就是给浏览器里的页面做了几个互相隔离的“隔间”,每个隔间有自己独立的 Cookie、LocalStorage 和缓存,而且这些数据无法跨容器访问。
容器隔离和 resistFingerprinting 的 First Party Isolation 有什么区别?First Party Isolation 是按“站点”隔离,访问同一个站点时,不管你在哪个标签页打开,都会共享同一份站点数据。而容器是按“颜色”隔离,同一网站在不同容器里会被当成完全独立的第三方来处理。
我习惯这样做:个人日常用一个“个人”容器,工作相关的用“工作”容器,购物相关的用“购物”容器。这几个容器之间的登录状态完全独立,即使同一个网站需要多个账号,比如不同租期的云服务器控制台,也可以直接打开三个容器同时操作,互不干扰。
camofox-browser 里对容器扩展的处理比较克制——只推荐安装,不做额外配置。因为容器的划分方式高度依赖个人使用习惯,把它写死反而会让这个方案不适合大多数人。
2.4 界面轻量化定制:把浏览器做成工具
浏览器界面和隐私似乎没什么关系,但这个模块在我的配置里占据了重要位置。原因很简单:如果浏览器界面本身在追求“内容推荐”和“营销位”,那浏览器厂商的商业模式就会持续倾向于在你的界面上安插追踪和推荐逻辑。
Firefox 默认的工具栏里有 Pocket 推荐位、书签工具栏自动填充、地址栏搜索建议广告等内容。这些功能单看无害,但它们会持续引入额外的网络请求和服务数据。在 camofox-browser 里,我会通过 userChrome.css 把这类元素从界面上移除,并且关闭 Firefox 自带的遥测数据上报。
这里贴一小段我用的 userChrome.css 核心配置:
/* 隐藏 Pocket 推荐入口 */ #pocket-button, #pocket-panel-button { display: none !important; } /* 隐藏地址栏右侧的搜索建议和 zen 图标区域 */ #urlbar-zoom-button, #identity-box { display: none; } /* 让标签栏更加紧凑 */ .tabbrowser-tab { min-height: 30px !important; padding: 0 !important; } /* 去掉首页的品牌信息和 Pocket 推荐位 */ .topsites, .pocket_posts { display: none !important; }除此之外,需要在 about:config 里手动关闭遥测上报:
- toolkit.telemetry.enabled = false
- toolkit.telemetry.unified = false
- datareporting.policy.dataSubmissionEnabled = false
- browser.ping-centre.telemetry = false
做完这些之后,浏览器界面会变成纯粹的工具形态——只有地址栏、标签栏和书签栏,没有任何推荐和信息流。用起来的感觉就像是从“浏览器产品”回到了“浏览器工具”。
3. 从零搭建 camofox-browser 全流程
3.1 环境准备与配置文件位置
搭建之前,先要找到 Firefox 的 Profile 目录。这一步很多人卡住,实际上非常简单。
打开 Firefox,在地址栏输入 about:support,回车以后,页面下方有一个“Profile Folder”(配置文件文件夹)区域,右边有个“Open Folder”(打开文件夹)按钮,点击后就会弹出资源管理器,里面就是 Profile 目录。
camofox-browser 的配置全部放在这个目录下:
- user.js:主配置文件,Firefox 启动时会读取它并覆盖默认偏好设置。
- chrome/userChrome.css:界面样式文件,用于隐藏和调整浏览器 UI 元素。
- extension-settings.json 等目录:扩展安装后会自动生成,不需要手动处理。
注意,Profile 目录下有 prefs.js 文件,这个文件会记录运行时被修改的所有偏好项。user.js 的优先级比 prefs.js 高,但 prefs.js 里的“用户主动修改”会导致 user.js 的某些配置项表现得不稳定,这点在第 4 章再展开。
3.2 手写 user.js 的核心配置
我的 user.js 分成几个区块,每个区块都有注释,方便日后维护。这里截取最关键的一部分:
// 1. 指纹伪装 user_pref("privacy.resistFingerprinting", true); user_pref("privacy.resistFingerprinting.letterboxing", true); user_pref("privacy.resistFingerprinting.randomization", true); user_pref("privacy.window.name.update", true); // 2. 网络与 Cookie 隔离 user_pref("privacy.firstparty.isolate", true); user_pref("network.cookie.cookieBehavior", 1); user_pref("network.cookie.lifetimePolicy", 2); user_pref("network.http.referer.XOriginPolicy", 2); user_pref("network.http.referer.trimmingPolicy", 2); // 3. 关闭遥测 user_pref("toolkit.telemetry.enabled", false); user_pref("toolkit.telemetry.unified", false); user_pref("datareporting.policy.dataSubmissionEnabled", false); user_pref("browser.ping-centre.telemetry", false); // 4. 关闭 WebRTC 的私网暴露 user_pref("media.peerconnection.enabled", false); user_pref("media.peerconnection.ice.default_address_only", true); // 5. 自动清理 user_pref("privacy.clearOnShutdown.cache", true); user_pref("privacy.clearOnShutdown.cookies", true); user_pref("privacy.clearOnShutdown.offlineApps", true); user_pref("privacy.sanitize.sanitizeOnShutdown", true);其中 network.cookie.lifetimePolicy = 2 的意思是“会话结束即清除所有 Cookie”,用户手动添加的“例外”可以保留白名单。这个设置配合容器扩展,在不使用“记住我”的网站时几乎不会留下持久追踪物。
还有一点要特意提一下:media.peerconnection.enabled 一旦设为 false,所有依赖 WebRTC 的网页电话、网页视频会议都会变得不可用,包括但不限于网页版在线会议系统。如果你日常离不开这类服务,建议把这一项保留为默认值 true,只开 ice 的默认地址限制就够了。我自己的做法是把它做成注释,放到配置文件的“进阶选项”区域,按需开启。
3.3 开启 userChrome.css 样式定制
userChrome.css 的原理不复杂,它就是通过 CSS 规则来覆盖 Firefox 内置界面的默认样式。但它不是默认生效的,需要在 about:config 里打开一个开关:
user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);在配置里打开这个开关之后,把样式文件放到Profile 目录/chrome/userChrome.css,重启浏览器就能生效。我用这个机制做的事情主要有这么几件:
- 隐藏 Pocket 按钮和推荐位。
- 压缩地址栏高度和标签栏间距,让浏览器看起来更密实。
- 去掉“Firefox View”入口和集锦(Collections)功能。
- 让书签栏只在需要时显示,平时隐藏。
这两段 userChrome.css 是我自己用的核心样式,放这里给个参考:
/* Firefox View 移除 */ #firefox-view-button { display: none !important; } /* 书签工具栏只在焦点在地址栏时显示 */ #PersonalToolbar { visibility: collapse !important; } #navigator-toolbox:is(:hover, :focus-within) #PersonalToolbar { visibility: visible !important; }第一段很简单,隐藏一个按钮。第二段有点意思:默认隐藏书签栏,但当鼠标悬停在浏览器顶部工具栏区域,或者地址栏获得焦点时,书签栏会自动展开。对于经常用快捷键的人来说,能省出大约 80 像素的纵向空间,写代码/看文档的时候会舒服很多。
3.4 扩展安装与分组管理
扩展的安装没什么好说的,直接去 Firefox 官方附加组件商店搜索安装即可。我想多说一句的是“分组管理”。Firefox 的扩展工具栏默认会把所有扩展图标都显示在地址栏右端,一旦装到四五个以上,看着就乱。
我的做法是装上 uBlock Origin、LocalCDN、ClearURLs、Privacy Badger、Multi-Account Containers 这几个扩展之后,进入“工具栏 > 固定扩展”管理界面,只保留 uBlock Origin 和 Multi-Account Containers 的图标固定在地址栏,其他全部收纳进扩展面板。
这样做的好处有两个。第一是界面干净,不会被一长串小图标占据视野;第二是减少误点。ClearURLs 这类扩展平时根本不需要手动操作,它在后台静默工作就够了,没必要占一个固定入口。
每个扩展装好之后都有一个简单的初始化动作:
- uBlock Origin:设置里勾选“自动更新过滤规则”,更新频率设为每 4 小时一次。
- ClearURLs:设置里勾选“在页面加载时自动清理 URL”,保留“显示清理数量角标”为关闭,不要给自己增加使用焦虑。
- Privacy Badger:保持默认即可,它不需要用户干预。
- LocalCDN:默认配置已经完全够用,唯一需要做的是勾选“仅缓存已确认安全的资源”。
3.5 验证指纹伪装是否生效
配置完成后,建议做两轮验证。第一轮是技术层面的验证,第二轮是可用性层面的验证。
技术层面的验证很简单,打开指纹检测网站(比如 browserleaks.com 的 Screen、Font、WebRTC 这几个页面),观察以下指标:
- Canvas 指纹:应该每次刷新都会产生不同的值,因为被加入了随机噪声。
- 字体指纹:列表应该被裁剪为固定的一小撮,不同刷新之间保持一致。
- 时区:显示为 UTC,而不是你本地的时区。
- WebRTC:私网 IP 那一栏应该是空的,或者显示为默认地址。
- User-Agent:应该被伪装成一个通用版本,而不是当前浏览器确切版本号。
可用性层面的验证更重要。我会打开几个日常必用的网站,逐个确认登录、搜索、下单、支付这些核心功能是否正常。最常出问题的是用了第三方验证码服务的网站(比如用 Google reCAPTCHA 的站点),以及那些强制要求启用 WebRTC 的在线会议服务。这两类网站在指纹伪装开启时大概率会拦人,需要手动添加例外。
4. 实测中的常见问题与排查技巧
4.1 常见问题速查表
我在实际搭建和使用 camofox-browser 的过程中,遇到了不少问题,整理成一个速查表,按“症状 → 原因 → 排查方向”的格式列出来,方便大家直接对照:
| 症状 | 原因 | 排查方向 |
|---|---|---|
| 某网站反复提示“浏览器环境异常” | resistFingerprinting 的 Canvas/WebGL 噪声被风控识别为特殊环境 | 临时关闭 resistFingerprinting,单站点添加例外 |
| 某些站点的验证码图片一直加载不出来 | ClearURLs 把验证码链接中的参数误删了 | 在 ClearURLs 里添加该站点的白名单 |
| 网银或政务站点提示“浏览器不受支持” | 字体列表被裁剪或 UA 被伪装 | 为该站点添加 resistFingerprinting 的例外 |
| 安装完配置后部分扩展的图标变灰 | 扩展未兼容 resistFingerprinting,或者被 firstparty.isolate 隔离了 | 逐个停用扩展定位冲突对象 |
| 浏览器无限循环重定向 | cookie.lifetimePolicy=2 导致某站点的登录态反复失效 | 给该站点加入 Cookie 白名单 |
| 重启后配置项被“重置”了 | prefs.js 中对应键值被覆盖 | 保证修改配置前先完全退出浏览器,或者删除 prefs.js 后导入 user.js |
| 页面字体发虚 | 新字体被裁剪,页面使用了系统不存在的后备字体 | 在系统安装一组 Arial/Helvetica 属性和 Noto Sans 系列字体 |
| 视频网站播放不了视频 | WebRTC 或 DRM 模块被拦截 | 检查 media.peerconnection.enabled 和 DRM 相关内容 |
排查这类问题的时候,我强烈建议一个一个因素地关。很多人在遇到网站异常时,一顿操作把所有隐私配置全关了,结果没定位到具体原因,还白白丢了隐私防护。实际上,只要逐项恢复,找到影响该网站的配置项并加例外,就可以兼顾二维码正常使用和隐私保护。
4.2 典型案例解析:为什么某些网站会把你拦截
网上最常被问到的就是“为什么开了 resistFingerprinting,淘宝能进,但某个政企网站就打不开”。其实原因很简单,目前主流的风控系统大多会用浏览器指纹作为风险评分的一部分。resistFingerprinting 产生的效果是“指纹值的随机化和统一化”,这在风控眼里本身就是一个异常信号——因为正常用户不会有那么统一的指纹分布。
Firefox 官方其实对这个问题有解,就是 fingerprinting protection 的“无噪音模式”或者对特定站点关闭保护。具体到配置上,做法是:
在 about:config 里搜索privacy.resistFingerprinting.exemptedDomains,添加需要豁免的域名列表。格式是逗号分隔的域名主域,比如:
user_pref("privacy.resistFingerprinting.exemptedDomains", "gov.cn,example.com");这个设置项值得多说一句。很多人不知道它的存在,导致做什么都一刀切,完全不考虑站点兼容性。实际使用中,我建议把“网银”“政务”“日常购物”“可能需要高可信环境登录的管理后台”这四类站点加进来。因为这些站点本身就是需要登录才能访问的,你能登录到账号里时,网站本来就知道你是谁,这时候强行伪装指纹没有意义,反而会因为指纹突变触发安全警报。
4.3 配置被静默覆盖的坑:prefs.js 与 user.js 的优先级问题
这个坑我自己踩过好几次,也帮不少网友排查过,值得单独拿出来说。
Firefox 的偏好存储机制是:启动时读取 user.js,将里面的配置写入 prefs.js。prefs.js 里保存的是运行时状态和用户手动修改的配置。问题出在:如果用户某次在 about:config 里手动修改了某个 user.js 中已经存在的键,那个值会被写入 prefs.js。以后每次启动,prefs.js 里被“记住”的新值会覆盖 user.js 里的值,即使你删掉 user.js 也不会恢复。
有几次我更新了自己的 user.js,用新版配置替换旧版,重启 Firefox 后却发现部分设置没有生效,一查 prefs.js 才发现是以前手动调过对应键所致。
解决方法有三个,任选其一:
- 在 about:config 里把要改的键右键点选“重置(Reset)”,然后重启浏览器。
- 退出 Firefox,打开 Profile 目录,删除 prefs.js,下次启动会自动重新生成并读取 user.js。
- 直接在 prefs.js 里编辑,删除对应键,但操作时必须保证 Firefox 已经完全退出。
关于这个问题,建议无论什么时候修改配置,都先退掉浏览器,再改 user.js。改完再启动,这样最稳。edge case 是如果你在 amd64 的 Windows 上开着 Firefox 的时候去改 user.js,即使文件保存成功,重启后也会被浏览器运行时里的当前状态覆盖回去。
4.4 性能与可用性的平衡建议
隐私配置做到最后,最大的敌人往往是“可用性下降”——网站打不开、登录态不稳定、页面布局错乱。我自己的经验是:隐私设置不是越多越好,冗余配置反而可能带来新的指纹特征。
比如开 resistFingerprinting 之后,用户如果再额外装一个专门的 Canvas Blocker 扩展,两者作用在同一接口上,会造成两个问题:一是接口噪声被叠加,反而让指纹更容易被识别;二是网页在检测 canvas API 时会收到“调用失败”或“返回空白”,很多站点会因此认为浏览器版本太老或环境异常。
所以 camofox-browser 的设计原则是一项功能只交给一个模块。指纹统一这件事只由 user.js 干,网络拦截只交给 uBlock Origin 和 ClearURLs,Canvas 噪声则交给 resistFingerprinting 的随机化机制,不重复装同类工具。冗余配置不但浪费资源,还会引入新的边缘问题。
另外,关于培养习惯比装扩展更重要这一点,我说一句真心话。浏览器隔离和配置只是“最后一道闸”,真正让隐私风险降低的,是你是否养成了“不清除数据就退出浏览器前,先关闭敏感页面”的习惯。camofox-browser 能帮你承载大部分自动化的拦截和隔离,但它管不了你在一个地址栏里输入的每一个域名是否合适。
结尾
写了这么多,其实就是想把 camofox-browser 这个项目完整地记录下来,也算给以后自己重装系统时留一份详细的手册。这个方案我现在多台电脑上都在用,日常办公、购物、逛论坛、刷视频都没出过什么大问题。唯一一次比较麻烦的是某个政务类网站登录时要求“高环境可信度”,当时我直接把这个站点加进了豁免名单——理性取舍,而不是死磕隐私设置,这才是把浏览器真正当成工具的姿态。
如果你也想折腾,我的建议是从最小配置开始:只加 user.js 里的 resistFingerprinting 和 cookie 隔离这两项,配合 uBlock Origin 一个扩展,先体验一周,看有没有遇到不方便的地方,再逐步补齐其他模块。千万不要第一天就全部铺开,那样出现问题的时候你根本不知道是哪个开关引起的。
最后再分享一个小习惯:每次改配置之前,先给 Profile 目录打个压缩包备份。折腾浏览器配置这种事,回滚能力比配置本身更重要。camofox-browser 这个项目后续我还会继续维护,比如研究一下如何在保持当前功能的前提下进一步精简配置项,以及怎么把多设备同步做得更优雅。这些问题,等我实际操作完再回来写。