"我不相信,热光学迷彩!"
这是一个 HTTP 代理,旨在绕过使用 JA4+ 等指纹识别技术来阻止某些 HTTP 客户端的服务。使用这个代理,你可以使用你偏好的 HTTP 客户端(如 curl),同时获得与真实(Chrome/Chromium)网页浏览器神奇地无法区分的指纹。thermoptic 还附带一些有趣的功能,用于缓解基于 JavaScript 的指纹识别。它还让你能够轻松地混合使用网页浏览器和底层 HTTP 客户端进行混合抓取。
即使你不熟悉 JA4+ 指纹识别,如果你做过任何网页抓取,你很可能以前就被它拦截过。诸如 Cloudflare 之类的流行服务会使用此类技术(以及其他技巧)来检测“非人类”HTTP 客户端的使用,从而阻止请求。这些服务还可以利用这种指纹识别来检测你是否在用真实浏览器启动会话后,随后切换到像 curl 这样的底层客户端。thermoptic 通过为所有抓取请求呈现统一的“真实”浏览器指纹来解决所有这些问题。
以下是未使用代理时 curl 的 JA4H(HTTP)指纹示例:```
$ curl https://ja4db.com/id/ja4h/
ge11nn090000_b6a016211e8a_000000000000_e3b0c44298fc
这与直接访问URL时Chrome生成的指纹截然不同:```
ge11cn19enus_f2808f0d04cf_9a10d4221160_7068f58def6e
然而,当我们使用代理发出请求时,我们的 JA4H 指纹竟然完全相同:``` $ curl --proxy http://thermoptic:1234 https://ja4db.com/id/ja4h/ ge11cn19enus_f2808f0d04cf_9a10d4221160_7068f58def6e
(我们的 JA4 TLS 指纹也是如此,等等)。
## 设置
要启动一个 `thermoptic` 代理,它通过 Ubuntu 22.04 上的容器化 Chrome 实例来伪装你的流量:
常规 Docker 设置(适用于没有 GPU 运行时的主机):```
docker compose up --build
就这样,现在你可以通过它来代理流量:``` curl --proxy http://127.0.0.1:1234 --insecure https://ja4db.com/id/ja4h/
重要说明:
* 默认情况下,代理在无认证模式下运行。如果你打算将代理暴露到外部,请务必通过环境变量 `PROXY_USERNAME` 和 `PROXY_PASSWORD` 设置认证。
* 如果你不想使用 `---insecure`,则需要使用位于 `./ssl/rootCA.crt` 的生成的 CA 文件。该文件会在你首次运行 `thermoptic` 时生成。
* 你可以将 `thermoptic` 连接到任何以 `--remote-debugging-port` 标志启动的 Chrome/Chromium 实例。这一点至关重要,因为你需要在更常用的环境中进行设置和代理,以尽可能保持低指纹画像(例如 Windows 上的 Chrome)。
* GPU compose 覆盖配置面向已安装 Docker NVIDIA runtime/toolkit 的 NVIDIA 主机。它会预留 GPU 设备、挂载 `/dev/dri`,并让捆绑的 Chrome 容器切换到 NVIDIA/Vulkan 渲染路径。要使用此配置,请运行 `docker compose -f docker-compose.yml -f docker-compose.gpu.yml up --build`。
## Features
- 🕵️ [浏览器级代理](#how-does-this-cloaking-work-exactly):通过真实 Chrome 会话重放请求,以逐字节匹配 JA4 指纹。
- 🤝 几乎无需自定义代码即可将你的 HTTP 客户端(例如 `curl`、`requests` 等)与 `thermoptic` 集成,只需[设置代理](#setup),指纹问题便交由它处理。
- 🪝 [钩子框架](#handling-browser-javascript-fingerprinting-with-thermoptic-hooks):提供请求前/请求后/启动时自动化,让你可以驱动完整浏览器来解决问题或捕获工件。
- 📘 一个 Cloudflare Turnstile 求解钩子的示例见 [`./hooks/onstart.js`](https://github.com/mandatoryprogrammer/thermoptic/blob/main/hooks/onstart.js)。
- 🖥️ [Web 浏览器控制 UI](#control-the-dockerized-chrome-browser-via-web-ui-xpra)(位于 `http://127.0.0.1:14111`),用于控制 Docker 化 Chrome 浏览器窗口。可手动登录网站,然后无缝地通过代理以你登录的会话发起请求(也便于调试)。
- 🔌 可通过 `docker-compose.yml` 中的 `UPSTREAM_PROXY` 环境变量设置上游 HTTP 或 SOCKS 代理 URI。
- 🛡️ 内置健康检查和重启控制循环,可检测冻结的浏览器并无操作员看护地自动恢复。
- ⚡ 支持 HTTP/1.1 和 HTTP/2,允许通过任一协议进行代理。(_注意:你可以与代理使用 HTTP/1.1 通信,而被操控的 Chrome 可能以另一种协议与目标站点协商。_)
## How does this cloaking work exactly?

* 使用 HTTP 客户端(如 `curl`)并将 `thermoptic` 设置为代理来发起 HTTP 请求。
* `thermoptic` 分析请求,以最佳方式判断它*应该*属于哪种浏览器请求类型(例如手动访问 URL?表单提交?`fetch()` 请求?)。
* `thermoptic` 使用 [Chrome 调试协议 (CDP)](https://chromedevtools.github.io/devtools-protocol/) 来操控浏览器,并设置一个页面,以模拟真实 Web 浏览器中正常请求的发生方式。
* `thermoptic` 通过模拟的上下文触发请求,并捕获 HTTP 响应。
* `thermoptic` 将 HTTP 响应发送回客户端。
由于请求实际是由浏览器使用其完整技术栈发出的,因此产生的 JA4 指纹是完全一致的。
注意:由于许多 WAF 会对 Web 浏览器进行 JavaScript 层面的指纹识别,`thermoptic` 还提供了钩子,以便在抓取过程的关键步骤中利用浏览器。有关更多信息,请参见[此部分](#handling-browser-javascript-fingerprinting-with-thermoptic-hooks)。
## Why *this* approach vs other solutions?
坦率地说:其他方法存在根本性缺陷,无法成为浏览器指纹识别问题的长期实用解决方案。
许多其他试图“击败”浏览器 JA4+ 指纹识别的方法,都是通过重新实现浏览器技术栈的各个层来做到的。这种方法有许多严重缺点,例如:
* 需要非常小心地完美匹配“真实”浏览器实现的行为。因此,*任何*怪癖或差异都可能被用来将这些客户端与“真实”浏览器实现区分开来。
* 尝试仅解决技术栈中某一层的问题。Chrome 使用多种协议来提供网页浏览体验。因此,即使你制作了完美匹配的 TLS 层,如果你的 HTTP 层不是逐字节一致,也可能会暴露你。
* 由于“真实”浏览器会定期改变其行为,它们的指纹也会发生变化,因此这些工具需要不断进行更密集的开发工作来弥补。
相比之下,因为 `thermoptic` 使用浏览器本身来执行 HTTP 请求:
* TCP、TLS、HTTP 等技术栈的每一层都与真实浏览器无法区分,因为请求是通过真实浏览器以*正常*方式发出的。
* 浏览器行为在各层的变化影响极小,只需更新 `thermoptic` 所控制的浏览器,即可匹配最新的指纹集合。
当然,没有解决方案是没有缺点的。有关 `thermoptic` 方法的完整缺点列表,请参阅 `DOWNSIDES.md` 文档。
## FAQ
### 为什么叫 `thermoptic`?
“Thermoptic”(“热光学迷彩”的简称)指的是 [《攻壳机动队》(1995) 动画中少佐所使用的虚构迷彩](https://ghostintheshell.fandom.com/wiki/Thermoptic_camouflage)。在电影中,这种迷彩可以在多种探测频谱下隐藏穿戴者,包括可见光和热辐射。同样,该工具试图在多个渠道(HTTP、TLS 等)上隐藏用户,防止其被指纹识别。
### JA4+ 是一整套指纹!它会伪装哪些?
该工具会将以下 JA4 指纹伪装成你所连接的 Chrome/Chromium 浏览器的完全一致指纹:
* JA4(TLS 指纹)
* JA4H(HTTP 指纹)
* JA4X(X509 TLS 证书指纹)
* JA4T(TCP 指纹)
### 如果我想配合使用其他上游 HTTP/SOCKS 代理怎么办?
`thermoptic` 现在会将受控的 Chrome 实例路由到内部的 `proxyrouter` 服务,因此你可以让 Chrome 指向上游 HTTP 或 SOCKS 代理(包括需要凭据的代理)。通过编辑 `docker-compose.yml` 中 `proxyrouter` 服务下的 `UPSTREAM_PROXY` 值来设置上游代理 URI。如果将其留空,Chrome 将通过集群内未认证的代理直接与互联网通信。
设置上游 SOCKS 代理的示例:```yaml
proxyrouter:
environment:
UPSTREAM_PROXY: "socks5://username:[email protected]:1080"
请注意,某些上游代理可能会改变底层指纹(例如 TCP 元数据),从而降低与住宅浏览器的一致性。
thermoptic 会使用你的客户端在 Cookie 头中指定的 cookie 加载浏览器。请求在浏览器上下文中执行后,将包含这些 cookie。这样做是为了确保服务器无法对 cookie 的顺序或任何其他类似的小把戏进行指纹识别。
注意:这些 cookie 在请求结束后也会保留。如果你想为 cookie 实现清理逻辑,请编写一个 thermoptic 钩子。
是的,thermoptic 支持这样的混合用法,更多信息请参阅本节。
你需要确保正确设置 X-Fetch-*、Origin 和 Referer 等请求头。如果你不告诉 thermoptic 这些请求头,它将无法以适当隐蔽的方式执行请求。
如果不设置上下文相关的请求头,thermoptic 将设置默认值,这些默认值可能无法准确反映目标网站的期望。例如,如果你不设置 Origin 头,它会将 Origin 设置为 null;如果你不设置 Referer 头,它根本不会发送 Referer。
为了尽可能隐蔽,建议你最好包含这些上下文相关的请求头!thermoptic 无法读懂你的心思,它只能读取你的请求 :)。
通常这仅适用于 thermoptic 钩子临时利用完整网页浏览器来通过 JavaScript/浏览器级别检查的情况。当临时使用这些钩子和完整浏览器模式时,你必须小心不要被指纹识别为机器人(例如,避免诸如 Runtime.enable 之类的陷阱)。
这里的伦理考量和复杂的博弈论远非 README 能够回答。尽管如此,当你通过电子邮件/Twitter/Github 抨击我时,请随意反驳这些过于简化的观点中的任何一点:
如果想就爬取军备竞赛继续闲聊,我要求你至少先请我喝杯啤酒。说实话,我讨厌在 README 里写这些无聊的伦理文章,所以你可以随意把我想象成一个想让你的生活更艰难的邪恶极客。
thermoptic 钩子处理浏览器 JavaScript 指纹识别thermoptic 允许你配置自定义脚本,以便在以下时机执行浏览器操作:
ON_START_HOOK_FILE_PATH)BEFORE_REQUEST_HOOK_FILE_PATH)AFTER_REQUEST_HOOK_FILE_PATH)这使你能够使用 Chrome 调试协议进行点击操作,并为那些需要真实网页浏览器来完成验证步骤的网站设置相应的 cookie。然后你可以使用 thermoptic 代理,通过同一个浏览器继续以隐蔽方式维持你的会话。