从Firefox源码编译一个反指纹抗追踪的隐私浏览器:camofox-browser全复盘
讲一个我和浏览器死磕的故事。几个月前我实在受不了 Chrome 越来越重的肉身和没完没了的数据采集又不想回到那个动不动就飙内存的老 Firefox于是花了几个周末在一台吃灰的 Linux 机器上动手搞了一个自己的浏览器。名字就叫camofox-browser——取 camo伪装和 fox火狐的组合核心思路很简单以 Firefox 为底子通过源码编译和深度配置做一个反指纹、抗追踪、用完即走的隐私向浏览器。这篇文章就是我整个项目的完整复盘从设计思路到编译落地再到日常使用踩过的坑一次性都倒出来。不管你是对浏览器工作原理好奇的普通用户还是想自己折腾一个干净浏览环境的技术爱好者这篇都值得你看看。我不讲什么高深理论就讲我实际怎么想、怎么改、怎么编译、怎么用每一步都是能直接照做的。1. 项目核心思路与整体架构拆解1.1 为什么底子选 Firefox 而不是 Chromium这个决定是我最开始做的也是影响后面所有工作的最根本选择。市面上绝大多数第三方浏览器包括一些所谓的隐私浏览器都是拿 Chromium 换层皮。Chromium 本身不差但它的生态里谷歌的服务和追踪逻辑实在太深入了你很难在不动大手术的情况下把它彻底清理干净。而且 Chromium 的代码库这几年越来越庞大编译一次动不动就要一两个小时对个人开发者极不友好。Firefox 这边情况完全不同。首先它的渲染引擎是 Gecko不是 Blink在内核层面就和 Chrome 生态划清了界限。其次 Mozilla 在 Firefox 里内置了不少隐私相关的底层接口比如privacy.resistFingerprinting反指纹、privacy.clearOnShutdown关闭时清理、network.dns.echconfig.enabledECH 连接加密之类的开关这些东西在 Chromium 里要么没有要么就是被砍得只剩个壳。最关键是 Firefox 的源码结构相对清晰mach构建系统也很成熟个人开发者想定制自己的版本门槛比 Chromium 低不少。我实际编译下来Firefox 源码树加上构建依赖大概需要 30GB 左右的磁盘空间首次编译在 8 核 16G 内存的机器上大约耗时 40 分钟。Chromium 的话同样的机器没两个小时下不来。对我这种急性子来说Firefox 几乎就是唯一解。1.2 camofox-browser 要解决的实际问题我做这个项目不是为了装酷是真心受够了三件事。第一是指纹追踪。现在的广告系统早就不靠 cookie 认人了而是通过 Canvas 指纹、WebGL 参数、字体列表、时区语言、屏幕分辨率这些杂七杂八的信息拼出一个几乎唯一识别你的数字指纹。这个指纹你根本清不掉换个浏览器、开无痕模式都没用。我实测过一个没做任何防护的 Firefox在指纹检测网站上能拿到接近 95% 的唯一性评分——这和裸奔没什么区别。第二是数据沉淀。正常的浏览器会把浏览历史、缓存、LocalStorage、IndexedDB 这些东西统统留在硬盘上越积越多。这带来两个问题一是隐私风险只要有人拿到你电脑基本就等于拿到了你最近几个月的全部网上行踪二是性能损耗臃肿的缓存和数据库会让浏览器越用越慢。第三是环境一致性。同一个网站在不同的浏览器配置下看到的页面可能完全不一样——有的是因为你被识别成了不同的设备有的是因为网站做了 A/B 测试。我想让浏览器最大程度地隐藏自己的存在感让每个网站都把我当成一个普通访客而不是一个可以被精准定位的目标。所以 camofox-browser 的定位就很清晰了一个基于 Firefox 源码的、默认高隐私强度的、强调反指纹和自动会话清理的桌面浏览器。它不是什么大项目也没有商业计划书就是一个能把我自己从 Chrome 的数据泥潭里捞出来的工具。1.3 整体功能架构一览我先在脑子里把需要的功能画了一张表然后每一条都在 Firefox 的源码和配置项里找到了对应的落地方案功能模块预期效果Firefox 中的实现方式指纹随机化每次会话的 Canvas、WebGL 参数不同privacy.resistFingerprinting 自定义噪声注入UA 标识切换网站识别为普通 Firefox 而非定制版general.useragent.override配置会话自毁关闭浏览器后清除全部临时数据privacy.clearOnShutdown系列配置默认防追踪第三方 Cookie、跟踪器全部拦截network.cookie.cookieBehavior 追踪保护列表安全 DNS防止 DNS 查询被窥探network.trr.mode配置 DoH禁用遥测不上传任何使用数据源码级去除遥测代码 配置禁用设计的时候我给自己定了一个原则底层能力优先靠配置实现配置搞不定的才动源码。原因很简单直接改配置和预置文件后续升级维护容易而且不容易引入编译错误。真正需要动源码的部分主要就是默认 UA、默认主页、默认搜索引擎这几处工作量不大但效果立竿见影。2. 核心功能实测反指纹、防追踪与数据自毁2.1 反指纹到底在反什么很多人一听反指纹就觉得是玄学其实它背后的原理很朴素。浏览器在渲染网页的时候会通过 Canvas 接口画一些图形、用 WebGL 做一些 3D 渲染、加载本地字体列表、读取系统时区和语言设置这些操作的结果会因为你的设备型号、显卡驱动、操作系统版本而略有不同。把这些差异组合起来就能形成一个足够区分你跟其他人的特征码而且你根本看不到它。camofox-browser 主要做了三层防护。第一层是统一化通过privacy.resistFingerprinting把字体列表、时区、语言这些信息模糊成一个通用值让所有用户的指纹看起来都差不多第二层是噪声化在 Canvas 和 WebGL 的渲染结果中注入一个极小的随机误差这样每次拿到的指纹都不完全一样第三层是禁用对于能关就关的探测接口尽量关闭比如navigator.deviceMemory这种专门暴露硬件参数的 API。我实测过开启这三层防护前后的差异。同样一台机器未开启时指纹检测网站的熵值entropy在 8.2 位左右意味着大约 300 台设备里就能区分出我这一台开启之后熵值降到了 4.1 位左右也就是几千台设备里才会有两台长得跟我差不多。虽然没有做到完全隐身但已经足够混进人群里了。这里要特别提醒一点resistFingerprinting开启后会有一个副作用就是 Canvas 的读取性能会下降一点因为每次渲染都要多一步噪声注入。日常浏览感觉不明显但如果你经常玩网页版的图形编辑器或者比较吃 Canvas 的在线工具可能会觉得稍微有点肉。这不是 bug是隐私和性能的正常取舍。2.2 自动数据自毁机制怎么调最安全Firefox 原生就带了一套关闭时清理数据的开关但默认是全部关掉的。我把它们全打开了同时做了一些细调。核心配置如下// 关闭浏览器时清理全部临时数据 privacy.clearOnShutdown.cache true privacy.clearOnShutdown.cookies true privacy.clearOnShutdown.downloads true privacy.clearOnShutdown.formdata true privacy.clearOnShutdown.history true privacy.clearOnShutdown.offlineApps true privacy.clearOnShutdown.sessions true // 同时关闭 Firefox 自带的 个性化推荐 数据上报 datareporting.healthreport.uploadEnabled false datareporting.policy.dataSubmissionEnabled false有几个细节值得单独说。书签和下载文件夹是不会被清理的因为它们的存储位置不在clearOnShutdown管理的范围内这也符合直觉——你存下来的东西应该保留但网上产生的垃圾应该消失。另外cookies这一项我建议选择清理全部而不是只清理第三方 Cookie因为既然追求用完即走就没必要留着任何站的 Cookie 过夜。还有一个容易忽略的地方是sessions清理。它管的是 Firefox 的会话恢复功能如果不开这一项即使你清了缓存和 Cookie只要你重启浏览器Firefox 还是会根据之前的会话文件把标签页恢复出来这时候网站照样能通过 LocalStorage 里的残留数据识别你。所以sessions必须开。这样配置完之后我的浏览器基本就是薛定谔的浏览器——用的时候什么都在一关就什么都没有了。好处是极其干净坏处是每次打开都要重新登录网站、重新输入表单。为了平衡体验我妥协了一个地方给少数几个可信网站比如自己的邮箱、网盘设置了站点级 Cookie 白名单通过 Firefox 的权限管理器单独放行这样它们能在关浏览器后保留登录态其他网站一律不留痕迹。2.3 搜索、DNS 与流量层面的隐私加强指纹和 Cookie 解决的是网站认识你的问题但还有一个更基础的问题你的浏览器在网上说话的时候别人能不能听到你说了什么这就涉及 DNS 和协议层面。Firefox 从 90 版本开始默认支持 DoHDNS over HTTPS但默认是关闭或仅在某些情况下启用。我在 camofox-browser 里把它改成了强制开启network.trr.mode 3 // 3 强制 DoH network.trr.uri https://mozilla.cloudflare-dns.com/dns-querymode3的意思是所有 DNS 查询都走 HTTPS 加密通道不走系统默认的 UDP 53 端口明文查询。这样一来Wi-Fi 管理员或者运营商能看到的数据就少了很多——他们最多知道你访问了哪个 IP但看不到你要解析的域名。如果你对 DoH 服务器有什么顾虑也可以换成自己想用的服务商在network.trr.uri里指定就行。还有一个容易被忽略的设置是network.dns.disablePrefetch禁用 DNS 预取和network.prefetch-next禁用网页预加载。这两个功能本来是加速用的但它们会在你还没点开链接的时候就提前去解析和加载目标网站等于变相暴露你的下一步行为。我都关掉了。实测对网速感知影响不大毕竟现在网络带宽普遍过剩少一点贴心的预测行为多一点确定性反而更踏实。最后是协议层面Firefox 默认开启 ECHEncrypted Client Hello支持——这个功能对普通用户来说基本上是无感知的它能保证你访问某个网站时连接握手过程中发送的域名信息也是加密的。我在 camofox-browser 里确认了network.dns.echconfig.enabled和network.dns.use_https_rr_as_altsvc都是默认开启状态这样整条链路从 DNS 解析到 TLS 建立都尽可能保持了内部的机密性。3. 从源码到浏览器完整编译实操流程3.1 环境准备和依赖安装如果你看到这里决定自己也动手试一把那接下来的内容是重点。整个编译流程我按能最小改动绝不大动的原则推进花在环境准备上的时间比想象中多。我的硬件环境是 i5-8400 六核处理器、16GB 内存、500GB 空闲磁盘的 Ubuntu 22.04 机器。Firefox 源码编译的最低要求是 8GB 内存、20GB 磁盘但我强烈建议内存给到 16GB不然链接阶段很容易 OOM。系统依赖直接一把梭sudo apt update sudo apt install build-essential python3 python3-pip \ mercurial libgtk-3-dev libgtk-3-0 libdbus-glib-1-dev \ libasound2-dev libpulse-dev libx11-dev libxcomposite-dev \ libxdamage-dev libxext-dev libxfixes-dev libxrandr-dev \ libxt-dev libgconf2-dev libdrm-dev libgbm-dev \ nasm yasm autoconf2.13 clang llvm这里有个关键点Firefox 官方文档推荐用 Clang 而不是 GCC 来编译原因是他们在 CI 里主要验证的是 Clang 工具链。如果你用 GCC运气好也能编过但一旦遇到奇怪的编译错误你没法确定是自己配置的问题还是工具链兼容问题排查成本极高。所以别折腾直接安 Clang。源码获取我用的是官方 Mercurial 仓库因为 Firefox 的源码管理主要用 MercurialGit 镜像虽然存在但同步有延迟hg clone https://hg.mozilla.org/mozilla-central cd mozilla-central如果你想省时间也可以只克隆深度为 1 的版本hg clone --stream https://hg.mozilla.org/mozilla-central --config phases.publishFalse这个仓库大小大概在 5GB 左右下载速度取决于网络环境我用了大概 20 分钟。3.2 修改源码打造属于你自己的标识源码拿到手里第一件事不是急着编译而是先在几个关键位置留下你的标记。我改了四处第一处是浏览器用户代理User-Agent。默认 UA 里会带有 Firefox 的版本号如果不改别人一眼就知道你用的是原版 Firefox 而不是自己的定制版。我找到了netwerk/protocol/http/nsHttpHandler.cpp把默认的 UA 字符串重写为Mozilla/5.0 (X11; Linux x86_64; rv:115.0) Gecko/20100101 Firefox/115.0这样既保持了和现代网站的兼容性又隐藏了定制痕迹。这里有个注意事项UA 字符串的格式必须严格遵循标准rv后面的版本号最好和实际编译的版本一致否则部分网站会因为你 UA 和页面代码不匹配而出现错版。第二处是默认主页。我改的是browser/app/profile/firefox.js里的browser.startup.homepage配置直接设成一个空白页不让它去访问 Mozilla 的什么内容页面。第三处是默认搜索引擎把默认搜索从 Google 换成了一个不追踪用户的无痕搜索服务。第四处是把代码里所有的mozilla.org品牌标识替换成自己的camofox字样这个纯属个人趣味不改不影响功能。这里要特别强调改代码之前先备份改完之后编译前再 review 一遍。我就吃过亏有一次在nsHttpHandler.cpp里加了一行中文注释结果忘了保存文件编码编译到一半直接报错说非法字符我花了快半小时才定位到问题。3.3 创建 mozconfig 并执行编译Firefox 的构建配置都集中在根目录的mozconfig文件里。我写的完整配置如下# 基础编译选项 ac_add_options --enable-applicationbrowser ac_add_options --enable-optimize ac_add_options --disable-debug # 禁用遥测和数据上报 ac_add_options --disable-telemetry ac_add_options --disable-crashreporter # 启用自定义品牌 ac_add_options --with-app-namecamofox ac_add_options --with-app-basenamecamofox-browser ac_add_options --with-brandingbrowser/branding/camofox # 减少非必要组件 ac_add_options --disable-webservices ac_add_options --disable-safe-browsing # 优化构建速度 mk_add_options MOZ_MAKE_FLAGS-j8逐行解释一下。--enable-optimize和--disable-debug是给正式版用的编译出来的体积更小、运行更快。--disable-telemetry在源码层面直接移除了遥测代码比事后配置更彻底因为有些数据采集逻辑是你关不掉的。--disable-crashreporter同理崩溃报告器本身也是个数据出口不要也罢。--disable-webservices会关掉 Firefox 的一些云同步功能如果你像我一样不需要账户体系这个选项能省不少编译时间。--disable-safe-browsing有争议——它禁用 Google 的安全浏览服务能减少对外通信但也意味着恶意网址警告失效纯粹是隐私和安全的权衡。最后的-j8是并行编译参数8 表示用 8 个线程同时编译。注意这个数字最好不超过你 CPU 的物理核心数否则会频繁切线程反而变慢。配置写好后开始编译./mach build首次编译会下载一堆工具链和依赖组件这阶段我一度以为卡死了其实它会在后台慢慢跑。整个过程在我的机器上大概 40 分钟期间风扇转得跟起飞一样如果你机器散热一般记得放它在一个通风良好的地方。编译完成后执行./mach run看到自己名字命名的浏览器窗口弹出来那一刻说实话还挺有成就感的。如果你想打包成独立的安装包./mach package产物会放在dist/目录下具体格式根据你的系统不同有的是 tar.bz2 压缩包有的是对应发行版的安装包。4. 日常使用配置与隐私基线4.1 装完必调的 about:config 重灾区编译完成、装上系统之后你以为就完事了还早。源码配置只是地基真正的精细调整都在about:config里。我整理了一份日常使用中觉得收益最大的配置清单建议按需开配置项推荐值作用privacy.resistFingerprintingtrue全局反指纹统一字体/时区/UAprivacy.firstparty.isolatetrue按顶级域名隔离所有存储network.cookie.cookieBehavior1只允许同站 Cookienetwork.http.referer.XOriginTrimmingPolicy2跨域请求只发送裸域名 Refererbrowser.privatebrowsing.autostarttrue启动即进入隐私窗口media.peerconnection.enabledfalse禁用 WebRTC防 IP 泄漏geo.enabledfalse关闭地理位置接口dom.storage.enabledfalse完全禁用 DOM 存储这里面privacy.firstparty.isolate我要多说一句。它开启后不同网站的 LocalStorage、Cookie 会被彻底隔开同一个第三方脚本在 A 网站存的数据在 B 网站完全读不到等于把跨站追踪的路全堵死了。代价是有些网站的多站登录会变得麻烦——比如你用同一个账号登录了博客和论坛它俩之间互相跳转时可能不会共享登录态需要你重新登录一次。这个权衡我觉得值。media.peerconnection.enabled我是直接关了的。WebRTC 可以用来做语音视频通话但它有一个著名的漏洞即使你在后台挂了代理或者走了加密链它也能通过 STUN 请求把你的真实内网 IP 甚至公网 IP 暴露出来。如果你平时不用浏览器开视频会议干脆关掉最省心。4.2 隐私和易用的平衡策略把上面这些配置全部打开之后你就拥有了一个连自己都不太认得出的浏览器。但这也会带来一个现实问题很多网站会把你当成机器人验证码能烦死你。我在实际使用中摸索出一个分级策略分享给大家。最高隐私档用于浏览新闻、看文档、逛社区这类不需要登录的网站。开启所有反指纹和隔离配置Cookie 全部按会话管理关浏览器就清。中间平衡档用于需要登录的网站比如邮箱、网盘、购物。这时候我会临时把privacy.resistFingerprinting关掉或者干脆直接用原版 Firefox 开一个单独的 Profile 来处理。因为很多网站的登录风控系统对异常浏览器指纹 无 Cookie的组合非常敏感你配置越隐身它越觉得你可疑。最低隐私档用于网银、政务网站这类对安全性和兼容性要求极高的场景。这时候我直接切换到系统里装的原版 Safari 或 Chrome因为它们被所有网站的风控系统充分测试过兼容性最好。这不是说 camofox-browser 不能用而是没必要在这种场景下给自己添堵。最后再分享一个我一直在用的验证方法用指纹检测网站来检验配置效果。这些网站会展示你能被识别出的熵值以及模拟出的设备指纹。每次调整完配置我都会刷新页面看看熵值变化。理想状态下你应该能看到和你相同系统、相同语言、相同分辨率的用户有好几百个这样你就成功隐身在人群里了。如果熵值依然很高说明还有某个暴露源没堵上回去继续排查。5. 常见问题与排查技巧实录5.1 编译阶段的玄学问题编译 Firefox 的过程不会总是一帆风顺我遇到的坑能凑满一张大桌子。第一个坑是磁盘空间不足。Firefox 构建过程中产生的中间文件和符号文件非常惊人我一开始以为 30GB 绰绰有余结果编译到一半系统提示磁盘满了。后来我用ncdu排查发现光obj-x86_64-pc-linux-gnu这个构建目录就吃掉了 18GB。解决办法是在编译前用du -sh *预估一下空间并在mozconfig里加一行mk_add_options MOZ_OBJDIR$HOME/camofox-build把构建目录放到空间更大的分区。第二个坑是链接阶段内存不足。第一次编译到 90% 左右时链接器因为占用内存过大直接被杀掉了。这是 Firefox 编译的经典问题解决方案是在mozconfig里加ac_add_options --disable-linkerlld export LDFLAGS-Wl,--no-keep-memory或者干脆加上-j4降低并行度虽然慢一点但稳定得多。我最后是用-j6--disable-linkerlld过的关。第三个坑是Clang 版本太新导致旧代码 warning 变 error。这个有点无解因为 Mozilla 官方仓库总是在追踪最新工具链但你本地装的 Clang 版本可能比预期的老或新。我的建议是装两个版本的 Clang 备用万一新版编不过就切到旧版试试反之亦然。5.2 日常使用中的兼容性问题编译成功只是万里长征的第一步真正让我血压升高的是各种网站的兼容性问题。首当其冲的是登录态保持。开了clearOnShutdown全清模式之后你每次重新打开浏览器都要重新登录这倒还好。真正的坑是有些网站会在你登录后通过 IndexedDB 存储一个设备信任标记如果这个标记被清了它就会强制让你做二次验证。我的解决方案是给少数常用网站设置 Cookie 白名单在站点权限里允许它们保存数据这样这些网站的 IndexedDB 就不会被清掉其他网站照旧。第二个问题是部分视频网站播放异常。原因大概率是启用了resistFingerprinting后浏览器的 Canvas 输出和网站的播放器做了兼容性校验算出来的哈希值不稳定。这种情况我没找到特别优雅的解决办法目前就是手动在about:config里临时把privacy.resistFingerprinting关掉看完视频再打开。反正配置项切换只需要在地址栏改一下值重启就生效不算太麻烦。第三个问题是某些网站加载不出图形。这通常和dom.storage.enabledfalse有关因为不少现代前端框架比如 React、Vue 开发的后台管理系统会把一些初始化数据放在 LocalStorage 里禁用后逻辑会崩。如果你日常需要用到这种业务型网站建议把dom.storage.enabled改回默认只保留其他隔离措施效果差不了太多。5.3 一个排查指纹暴露的实战案例最后分享一个我排查了很久的案例它让我对浏览器指纹的理解又深了一层。有一天我配置完所有隐私选项后在指纹检测网站上一测其他指标都很好唯独 WebRTC 的 DNS 解析泄露暴露了我的内网 IP。我明明已经关了media.peerconnection.enabled怎么还会泄漏后来发现原因是 Firefox 的 WebRTC 这个开关只管新建连接但系统层面的 mDNS 解析服务仍然在跑。最后我是通过修改about:config里的media.peerconnection.ice.default_address_only为true并同时把media.peerconnection.ice.obfuscate_host_addresses保持启用才解决的。这个经历告诉我一个隐私功能是否真的生效不能只看配置项名字一定要用工具实测。这也是我做 camofox-browser 最大的收获隐私不是某一个开关能搞定的而是一个需要反复验证、不断调整的系统工程。每一个配置项背后都有它自己的逻辑和副作用你必须理解它们才能真正掌握自己的浏览器。写在最后一点真心话Camofox-browser 到现在已经是我每天的主力生产工具了。它不完美——有些网站用起来会别扭偶尔也会遇到奇怪的兼容问题——但它让我重新找回了上网是自己的事这种感觉。每次点开那个还带着点编译气味的深蓝色图标我都知道这个浏览器背后没有隐藏的数据暗渠没有莫名其妙的推荐也没有无声的监听。如果你也想折腾一个自己的浏览器我给的建议是别急着抄我全部配置先原版 Firefox 用一周然后一两个星期加一个隐私设置用指纹检测网站验证效果慢慢磨合出最适合自己的组合。这个过程本身就是对自己数字生活的一次重新掌握。