返回博客
指纹

使用 BotBrowser 控制 CPU 核数

解释 navigator.hardwareConcurrency 如何暴露用于指纹识别的 CPU 信息,以及 BotBrowser 如何通过配置文件在所有上下文中控制报告的核数。

介绍

navigator.hardwareConcurrency 属性返回浏览器可用的逻辑 CPU 核心数。它被设计用于帮助 Web 应用优化并行工作负载,让 JavaScript 决定创建多少个 Web Worker 或如何划分数据处理任务。但同一属性也会泄露硬件信息,从而被用于浏览器指纹识别。报告 6 个逻辑核的设备远比报告 8 个核的设备少见,而报告 64 个核的服务器则立刻显得异常。由于 CPU 核数稳定、易于查询且在硬件配置间差异显著,它已成为指纹跟踪系统的标准组成部分。本文说明核数如何参与指纹识别、简单覆盖为何存在问题,以及 BotBrowser 如何通过配置文件提供一致的核数报告。

隐私影响

CPU 核数看似低价值的信号,但在上下文中其贡献显著。任何指纹属性的价值取决于其在总体中的分布。根据 AmIUnique 项目的数据,navigator.hardwareConcurrency 大约有 4.5 比特的熵,意味着它可把设备区分为约 23 个组。虽然 23 个组听起来不多,但与其他信号结合时,每增加一比特的熵都会成倍提高识别能力。

分布高度倾斜:4 和 8 的值占据桌面浏览器的大多数。值为 2(老旧机器、低端 Chromebook)、6(部分 Intel 配置)、12(某些 Ryzen 5)、16(高端桌面)以及大于 16 的值则逐渐罕少。报告 24、32 或 64 核的机器几乎肯定是服务器或工作站,在普通浏览行为中极其罕见。

移动设备进一步区分了这一信号。多数手机报告 4 或 8 个核,但特定 SoC(Snapdragon、Exynos、MediaTek、Apple Silicon)会将特定核数与其他可识别属性配对。带有特定用户代理模式且 hardwareConcurrency 为 8 的手机,可能缩小到少数几个型号。

隐私问题被放大,因为 hardwareConcurrency 在所有执行上下文中都可用:主线程、dedicated workers、shared workers 和 service workers。它无需任何权限,且无法被阻止而不破坏合法使用该属性进行性能优化的 Web 应用。

技术背景

hardwareConcurrency 如何工作

navigator.hardwareConcurrency 返回一个无符号长整数,表示可用的逻辑处理器数量。“逻辑处理器”指的是物理核心乘以每核线程数(例如带超线程的 4 核 CPU 报告 8)。

console.log(navigator.hardwareConcurrency); // 例如 8

该值也可在 worker 上下文中读取:

// 在 Web Worker 内
console.log(self.navigator.hardwareConcurrency); // 相同的值

值为何会不同

多个因素决定 hardwareConcurrency 的返回值:

  • 物理硬件。 核心数和线程数由处理器型号决定。Intel i5 常见 4-6 核并支持超线程,AMD Ryzen 7 常见 8 核并支持 SMT,Apple M 系列在能效/性能簇间有不同核数。
  • 虚拟化。 虚拟机报告分配的 vCPU 数量,可能与宿主机不同。分配 2 个 vCPU 的 VM 会报告 2。
  • 操作系统调度。 某些操作系统或容器环境允许限制可见处理器数。
  • 浏览器实现。 大多数浏览器直接报告来自操作系统的原始值;有些项目尝试进行上限或分桶处理,但 Chromium 通常报告实际数值。

与其他信号的相关性

CPU 核数并非孤立存在。跟踪系统会将其与:

  • navigator.deviceMemory — 例如 2 核且 8 GB RAM 的设备是合理的;2 核但仅 0.25 GB 则指向不同设备类别。
  • navigator.platform — “Linux x86_64” 且 4 核能够缩小到特定硬件;“Linux armv81” 且 8 核则暗示某些 ARM 服务器或手机。
  • User agent。 浏览器和 OS 版本会约束合理的核数。
  • 性能计时。 实际并行执行性能(通过计时测得)可与报告的核数进行比较。

报告的核数与实际并行性能不一致时,是一个强烈的篡改信号。

常见防护方法及其局限

通过扩展或 JavaScript 覆盖 hardwareConcurrency 是最常见的做法,但会带来若干问题:

  1. 性能不一致。 如果报告为 4 核但实际机器有 16 核,SharedArrayBuffer 或 Web Workers 的并行执行速度会明显高于 4 核机器,测得的时间差异可被检测。
  2. 原型检测。 通过检查属性描述符、原型链或 getter 的执行时间可以检测到 JavaScript 覆盖。
  3. Worker 上下文缺口。 有些扩展只修改主线程的 navigator,而未修补 worker。运行在 Web Worker 中的脚本会看到真实值。

随机化数值 会产生不真实的配置。随机到 7 或 13 等值并不对应任何实际 CPU 架构。合理的值应为常见配置或真实设备设定。

使用固定常见值(例如总是报告 8)比随机化好,但如果与其他信号冲突仍有风险。例如在用户代理标识为某型号 Android 且该型号出厂为 4 核时报告 8 核则不一致。

根本要求是:报告的核数必须与其他设备属性内部一致,且不得与可观察到的性能特征相冲突。

BotBrowser 的引擎级方法

BotBrowser 通过其指纹配置文件系统在 Chromium 引擎级控制 navigator.hardwareConcurrency。这种方法相较于 JavaScript 级修改有若干优势。

基于配置文件的值

每个 BotBrowser 指纹配置文件指定一个 hardwareConcurrency 值,与被建模设备的实际 CPU 配置相匹配。Windows 10 桌面 i7 配置的档案会报告 8 或 16 核;使用 Snapdragon 888 的 Android 档案会报告 8 核。取值源自真实设备配置,而非任意数字。

所有上下文一致

由于是在引擎层进行控制,所有上下文返回相同值:

  • 主线程 navigator.hardwareConcurrency
  • Dedicated Worker self.navigator.hardwareConcurrency
  • Shared Worker self.navigator.hardwareConcurrency
  • Service Worker self.navigator.hardwareConcurrency

不存在某一上下文返回真实值而另一上下文返回档案值的差异。

跨信号一致性

配置文件中的 hardwareConcurrency 值是完整设备身份的一部分,会与:

  • 用户代理字符串和平台
  • deviceMemory 值
  • 屏幕分辨率及其它硬件信号
  • 浏览器品牌和版本

这能确保交叉核验不会揭示不一致。

无 JavaScript 痕迹

由于在引擎层设置该值,不会留下修改属性描述符的痕迹,也没有非原生 getter 或时间差。该属性的行为与真实设备上的原生访问完全一致。

配置与使用

基本配置文件加载

chrome --bot-profile="/path/to/profile.enc" \
       --user-data-dir="$(mktemp -d)"

配置文件会自动决定报告的核数。

验证该值

// 在浏览器控制台或自动化脚本中
console.log(navigator.hardwareConcurrency);
// 返回配置文件中的核数,而非你的实际硬件

Playwright 集成

const { chromium } = require('playwright');

const browser = await chromium.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

const cores = await page.evaluate(() => navigator.hardwareConcurrency);
console.log(`Reported cores: ${cores}`);

// 验证 worker 上下文一致
const workerCores = await page.evaluate(() => {
  return new Promise(resolve => {
    const blob = new Blob([
      'postMessage(self.navigator.hardwareConcurrency)'
    ], { type: 'application/javascript' });
    const worker = new Worker(URL.createObjectURL(blob));
    worker.onmessage = e => resolve(e.data);
  });
});
console.log(`Worker cores: ${workerCores}`);
// 两者应相同

Puppeteer 集成

const puppeteer = require('puppeteer');

const browser = await puppeteer.launch({
  executablePath: '/path/to/botbrowser/chrome',
  defaultViewport: null,
  args: [
    '--bot-profile=/path/to/profile.enc'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

const cores = await page.evaluate(() => navigator.hardwareConcurrency);
console.log(`Reported cores: ${cores}`);

验证

值检查。 查询 navigator.hardwareConcurrency 并确认其与所加载配置文件的预期值一致,应与实际硬件无关。

Worker 一致性。 在 Web Worker 中查询 self.navigator.hardwareConcurrency,其值应与主线程一致。

跨属性一致性。 验证核数在配置文件的平臺、用户代理和 deviceMemory 上是合理的。8 核且 8 GB 内存、Windows 10 的配置是现实的;Android 用户代理却报告 64 核则不现实。

跨会话稳定性。 在相同配置文件下的多个会话中查询该值,结果应保持不变。

最佳实践

  • 使用完整配置文件。 不要单独覆盖 hardwareConcurrency。该值必须与其他设备属性内部一致,BotBrowser 的配置文件自动保证这一点。
  • 选择真实配置的档案。 常见值(4、8)更容易融入人群,而异常值(6、12、24)则更显眼。选择与目标用例相匹配的档案。
  • 在 worker 上下文测试。 始终验证 worker 返回值与主线程一致。
  • 避免手动覆盖核数。 BotBrowser 的配置文件经过内部一致性设计,手动更改核数却不调整其他属性会产生可检测的不一致。

常见问题

Q: 最常见的 hardwareConcurrency 值有哪些? A: 在桌面端,4 和 8 最为常见,共计超过 70%。移动端同样以 4 和 8 为主。2、6、10、12、16 及更高值逐渐罕见。

Q: 网站能否测出我真实的核数而不管 hardwareConcurrency 报告什么? A: 理论上,站点可以尝试通过 SharedArrayBuffer 和高精度计时测量并行执行性能。但浏览器的安全缓解(降低计时精度、COOP/COEP 要求)使这变得困难。BotBrowser 的引擎级控制也有助于一致性,因为报告值与配置文件的预期行为一致。

Q: hardwareConcurrency 会随浏览器更新而变化吗? A: 不会。该值反映硬件和操作系统配置,而非浏览器版本。在同一台机器上浏览器更新不会改变该值。

Q: navigator.hardwareConcurrency 在所有浏览器中都可用吗? A: 是的。主流浏览器(Chrome、Firefox、Safari、Edge)都支持该属性,并且其已作为 HTML 规范的一部分。

Q: 为什么某些 VM 报告的核数与宿主不同? A: 虚拟机报告由管理程序分配的 vCPU 数量。宿主有 16 核但可能只给 VM 分配 2 或 4 个 vCPU,VM 内部看到的就是这些分配数。

Q: 核数会影响 BotBrowser 中的 Web Worker 性能吗? A: BotBrowser 控制的是报告值,而非实际 CPU 调度。代码仍在你的实际硬件上执行。配置文件的值仅影响 JavaScript 查询时看到的数值。

摘要

navigator.hardwareConcurrency 是一个简单的属性,其返回单个数字,但当与其他硬件信号结合时,该值对浏览器指纹识别的贡献不容忽视。BotBrowser 通过配置文件在 Chromium 引擎层控制该值,确保所有 JavaScript 执行上下文中的一致性。由于该值属于完整设备档案的一部分,它能与用户代理、平台、内存等其他身份信号保持一致。

有关主题,请参见 What is Browser FingerprintingNavigator Property ProtectionScreen and Window ProtectionDeterministic Browser Behavior

title: "BotBrowser CPU 核心数控制" description: "BotBrowser 如何通过指纹配置文件控制 navigator.hardwareConcurrency,在所有上下文中实现一致的 CPU 核心数报告。" date: "2025-05-14" locale: zh category: fingerprint tags: ["cpu", "cores", "hardwareConcurrency", "fingerprinting", "privacy"] published: true

隐私风险

navigator.hardwareConcurrency 返回浏览器可用的逻辑处理器核心数。这个值是一个追踪信号,因为它揭示了设备类别: 服务器、台式机、笔记本或移动设备。它不需要权限,可从主线程、Web Worker 和 iframe 中访问。

BotBrowser 的解决方案

BotBrowser 在浏览器引擎层面从指纹配置文件设置核心数,在任何 JavaScript 执行之前生效。该值在所有执行上下文中保持一致。

加载配置文件

chrome --bot-profile="/profiles/windows-chrome-122.enc" \
       --user-data-dir="$(mktemp -d)"

如果配置文件来自 8 核台式机,navigator.hardwareConcurrency 将返回 8,无论宿主机有 2 个核心还是 96 个核心。

所有上下文匹配

配置文件的核心数适用于:

  • 主页面 navigator.hardwareConcurrency
  • Web Worker 和 SharedWorker 上下文
  • Service Worker 上下文
  • Iframe navigator 对象

服务器自动化场景

在云服务器上运行时,宿主机的核心数会暴露服务器环境。BotBrowser 呈现配置文件中消费级设备的核心数:

const { chromium } = require('playwright-core');

const browser = await chromium.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/profiles/windows-chrome-122.enc',
  ],
  headless: true,
});

const page = await (await browser.newContext()).newPage();
const cores = await page.evaluate(() => navigator.hardwareConcurrency);
console.log('报告核心数:', cores); // 8, 而非 96

验证

验证跨上下文的核心数一致性:

const page = await (await browser.newContext()).newPage();

// 主线程
const mainCores = await page.evaluate(() => navigator.hardwareConcurrency);

// Web Worker
const workerCores = await page.evaluate(() => {
  return new Promise(resolve => {
    const blob = new Blob([
      'self.postMessage(navigator.hardwareConcurrency)'
    ], { type: 'application/javascript' });
    const w = new Worker(URL.createObjectURL(blob));
    w.onmessage = e => resolve(e.data);
  });
});

console.log('主线程:', mainCores);
console.log('Web Worker:', workerCores);
console.log('匹配:', mainCores === workerCores);

两个值都应与配置文件记录的核心数匹配,而非宿主机的实际核心数。

快速开始

  1. GitHub 下载 BotBrowser
  2. 配置文件仓库 选择配置文件
  3. 使用 --bot-profile 启动以应用完整硬件身份
  4. 在浏览器控制台中使用 navigator.hardwareConcurrency 验证
#cpu#fingerprinting#hardwareConcurrency#privacy