任何网页都可以向你的浏览器打听你显卡的名字。不弹授权提示,也没有 cookie 横幅,几行 JavaScript 就够了。在一台典型的 Windows 笔记本上,拿到的答案大概长这样:ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 (0x00002503) Direct3D11 vs_5_0 ps_5_0, D3D11)。本页的小工具会告诉你,你的浏览器报的是什么。
这就是 WebGL 指纹识别。也正因如此,指纹检测工具会打印出 “WebGL fingerprinting is present”(存在 WebGL 指纹)这样的提示,或者更吓人的 “WebGL renderer info is spoofed”(WebGL 渲染器信息被伪造)。前一条对地球上几乎每一个浏览器都成立。后一条则说明你的浏览器被抓到了自相矛盾,而罪魁祸首通常是你自己装的某个扩展。
WebGL 指纹测试会从你的浏览器里读取什么
WebGL 是浏览器调用 GPU 绘制 3D 图形的 API。Google 地图、网页游戏和 3D 商品定制器都靠它运转,而要干好这份活,它就必须跟真实的硬件打交道。指纹脚本会从两个方向利用它。
它会问。 WEBGL_debug_renderer_info 扩展增加了两个常量:UNMASKED_VENDOR_WEBGL 和 UNMASKED_RENDERER_WEBGL。这名字有点言过其实:这个扩展什么也没”揭开”,它只是返回驱动报告的 GPU 名称,而不是 “WebKit WebGL” 这类占位符。与它并列的还有几十项能力参数:最大纹理尺寸、支持的扩展、着色器精度,这些数值在不同的 GPU 家族和驱动版本之间各不相同。合在一起,它们读取成本极低,而且几个月都不会变。
它会看。 脚本在屏幕外画一个小场景,用 readPixels 把像素读回来,再算出哈希。不同的 GPU 和驱动在颜色取整、边缘混合和着色器运算上都有细微差别,所以哈希也会跟着不同。这和 canvas 指纹 是同一个思路,只是离硬件又近了一层。
人们想象中的那个名字,大概是”Intel 显卡”这种含糊的说法。真实的字符串读起来却像一张参数表:
- ANGLE:把 WebGL 转换成 Direct3D、Metal 或 OpenGL 调用的中间层。Chrome 在所有桌面操作系统上都通过它绘图,Firefox 只在 Windows 上如此;这种确切的格式是 Chrome 独有的。
- GPU 厂商
- 确切的显卡芯片,顺带还暗示了这台机器有多贵
- PCI 设备 ID:用来区分以同一名称销售的不同芯片版本
- Direct3D:只存在于 Windows 上
Direct3D 只存在于 Windows 上,Metal 只存在于苹果硬件上,所以在大多数机器上,光凭 GPU 字符串就能把操作系统这个问题一锤定音,不管你的 User-Agent 怎么说。这和我们在 一个浏览器,五种操作系统声明 中讲过的交叉核对是同一回事。
WebGL 指纹有多独特?
单看它自己,没你担心的那么独特。拥有 RTX 3060 的人数以百万计,每一台 M2 MacBook 报告的都是同一个字符串。WebGL 只能把你归进某个硬件分组,而指纹正是靠把一个个分组叠起来构建的。RTX 3060 很常见。可一块 RTX 3060,配一块 1440p 屏幕,处在阿姆斯特丹时区,语言设为荷兰语和英语,这样的人就只剩一小撮了。
它对追踪者的价值在于持久:你可以换浏览器、清空所有 cookie,可你的 GPU 还是那块 GPU。研究人员走得更远。2022 年的 DrawnApart 研究通过测量微小工作负载在 GPU 各个执行单元上的耗时,能把硬件完全相同、渲染器字符串也完全相同的机器区分开来。
“WebGL fingerprinting is present” 不是警告
当检测工具说 “WebGL fingerprinting is present” 时,意思只有一个:WebGL 已开启,并且可以读取。每一款主流浏览器在每一台电脑和手机上都是这个状态。这并不说明哪里出了问题,WebGL 本身也不是你需要防范的东西:隐私上的代价在于指纹,而指纹正是本文余下部分要讲的。
最诱人的修复办法是关掉 WebGL。别这么干。关掉它,等于把一块和几百万人共用的 GPU,换成一个几乎没人有的特征,还会让所有用 GPU 绘图的网站统统罢工。一个拒绝标准 API 的浏览器,也正是那种会给你招来更多 CAPTCHA 的怪胎。
为什么检测工具会说 “WebGL renderer info is spoofed”
这句话最常出现在 Cloudflare Turnstile 的故障排查工具里,挂在一项名为 “Graphics Information Appears Fake”(图形信息疑似伪造)的检查下面。人们往往是在某个验证反复转圈、死活不放行之后才翻到它的。谁也没法直接看到你的 GPU,所以检测工具无法证明你用的是什么硬件。它能做的,是把各种声明拿来互相比对,而伪造的数值很少能挺过这一关。下面就是这些测试,本页的小工具会运行前四项:
- 图形 API 和操作系统对不上。 渲染器字符串里写着 Metal,发出它的浏览器的 User-Agent 却说自己是 Windows。
- 供应商和渲染器各说各话。 供应商(vendor)字段还写着 NVIDIA,因为伪造只改写了渲染器字符串。
- WebGL 函数被打了补丁。 要改变
getParameter的返回值,扩展就得把它替换掉,而一个被粗暴替换的内置函数就不再报告[native code]了。藏得更好的补丁需要更精细的检查。在我们的 机器人检测测试 里,同一个陷阱也会逮住自动化工具。 - 像素每次读取都不一样。 实际情况是,真实的 GPU 把同一个场景画两遍,返回的像素一模一样。有些反指纹扩展会在每次读取时注入新的随机噪声,于是画两次就得到两个哈希。作为一项特征,这种不稳定比市面上任何一款 GPU 都罕见。
- 名字和像素对不上。 反欺诈厂商可以把你的渲染输出和已知设备的输出做比对。自称 RTX 3060,画出来却像 Intel 核显,渲染哈希就会把你出卖。单个浏览器没法运行这项检查,所以小工具跳过了它。
在几种配置之间切换,看看每一种会露出哪些破绽:
ANGLE (Apple, ANGLE Metal Renderer: Apple M2, Unspecified Version)- 图形 API 与操作系统相符Windows User-Agent 配 Metal
- 供应商与渲染器一致供应商仍写着 NVIDIA
- WebGL 函数均为原生getParameter 已被替换
- 同一幅画,同样的像素画两次,同一个哈希
两种伪造配置里,GPU 本身都没毛病;每一个标记都出自伪造本身。如果你从没想过伪造什么,却收到了 “spoofed” 警告,去翻翻你的扩展列表,看看有没有 WebGL 或 canvas 的”防护”类扩展。它通常就是元凶,Cloudflare 的故障排查工具甚至直接点了其中一个的名:WebGL Fingerprint Defender。
什么时候警告是误报
不是每个标记都意味着有人动过你的浏览器。有几种再普通不过的配置也会触发检测工具:
- 远程桌面和虚拟机。 没有真实 GPU 可用时,浏览器会退回到软件渲染器,比如 llvmpipe 或微软的 Basic Render Driver,或者干脆彻底失去 WebGL。运行机器人的服务器看起来也是这副样子,所以检测工具会对此心存怀疑。
- 双显卡笔记本。 同时配有核显和独显的笔记本,可能因电源设置、或浏览器被分配到的显卡不同,而报告不同的 GPU。
- 有意保护你的浏览器。 Safari 对每个网站都报告一个笼统的 “Apple GPU”。Firefox 会把渲染器名称粗化成一个宽泛的系列。Brave 给所有用户同一个通用的 GPU 名称,并给其他 WebGL 输出加上按站点变化的微小扰动,它管这叫 farbling。好的检测工具会把这些列入白名单,偷懒的照样标记。
这些情况和伪造的区别在于一致性。Safari 在苹果设备上说 “Apple GPU”,是一个大家共用的诚实回答。一个 Windows 浏览器声称自己有 Apple GPU,那就是自相矛盾。
如何修改或屏蔽你的 WebGL 指纹
- 保持 WebGL 开启。 禁用它只会让你更稀有,而不是更安全,还会把正经网站搞坏。
- 卸掉 WebGL 伪造扩展。 改名工具和噪声注入工具,恰恰制造出了检测工具要找的那种矛盾。如果上面的小工具标记出被打补丁的函数或不稳定的像素,头号嫌疑人通常就是某个扩展。
- 如果你需要换一个身份,就把它的每一部分都换掉。 为广告核验、电商或社交媒体运营多个账号,意味着每个配置文件都需要一块与其操作系统相符的 GPU、一个与其渲染器相符的供应商,以及与其 GPU 相符的像素。这在 JavaScript 里很难伪造,所以防关联浏览器会在引擎内部完成这件事。Incogniton 在浏览器层面为每个配置文件提供一套一致的 WebGL 身份,没有任何被打过补丁的函数可供检测工具揪出来。
然后运行一次 完整浏览器扫描,看看你的 GPU 和浏览器报告的其他一切(从时区到字体)是否对得上。