Thermoptic:用真实 Chrome 做底层客户端的 HTTP 隐身代理

安全
爬虫
开源
TOOL
2026/10/17
·

阅读时间: 大约 12 分钟

Thermoptic:用真实 Chrome 做底层客户端的 HTTP 隐身代理

Thermoptic 的请求转发链路:curl 经代理交给 CDP 控制的真实 Chrome,再访问目标站点

Thermoptic 是开发者 mandatoryprogrammer 开源的一个 HTTP 代理(MIT 生态、Docker Compose 一键起),目标很直接:让 curl、requests 这类轻量 HTTP 客户端在经过它代理后,对外呈现的指纹与一台真实 Chrome/Chromium 浏览器完全一致,从而绕过依赖 JA4+ 等网络指纹拦截非人类客户端的服务。本文基于项目官方 README 与作者自维护的 DOWNSIDES.md,解析它的技术路线、可核对的指纹样例,以及官方自己承认的代价与边界。

一、背景:为什么 curl 会被认出来

反爬体系早就不只看 User-Agent 字符串。现代 WAF(Cloudflare、Akamai、AWS WAF、F5 等)会在多个协议层采样客户端特征:TLS 握手的扩展顺序与密码套件偏好、HTTP/2 的帧与头部顺序、TCP 指纹、X509 证书行为等。JA4+ 是这一类指纹方案的代表套件,包含 JA4(TLS)、JA4H(HTTP)、JA4X(X509 证书)、JA4T(TCP)等子指纹。

问题在于:curl 自己实现的 TLS 栈与 HTTP 栈,和 Chrome 自带的网络栈在这些细节上天然不同。更隐蔽的是,有些站点先用真实浏览器建立会话,随后切换到 curl 继续请求,服务端可以通过”同一账号前后指纹不一致”识别这种混合抓取。传统对抗思路是”模拟”——重写 TLS 与 HTTP 栈去贴合 Chrome 的字节序列(如 curl-impersonate 一类),而 Thermoptic 选择了另一条路:不模拟,直接让真浏览器发请求。

二、它是什么:一个套在底层客户端前面的浏览器

Thermoptic 的定位是一个标准 HTTP 代理。开发者照常把 curl --proxy 指向它,业务代码、URL、请求方法几乎不用改;区别在于真正把字节发出去的不是 curl 自己的网络栈,而是代理后端通过 Chrome DevTools Protocol(CDP)控制的一台真实 Chrome。

项目名 “Thermoptic” 取自 1995 年动画《攻壳机动队》中少佐使用的”热光学迷彩”——原作里它能同时在可见光与红外等多个频谱隐藏穿戴者;作者借此比喻:这个工具要在 HTTP、TLS、TCP 等多个指纹通道上同时隐身。

三、技术机制:CDP puppet 真实浏览器

官方 README 把一次代理请求拆成五步:

  1. curl 等客户端把 Thermoptic 设为代理发起请求;
  2. Thermoptic 分析请求,判断它在真实浏览器里”应该是什么样”——直接地址访问、表单提交,还是一次 fetch();
  3. 通过 CDP 在浏览器里建立一个与该场景一致的页面上下文,复刻正常浏览器请求的发生方式;
  4. 在这个被 mock 的上下文中真正触发请求并捕获 HTTP 响应;
  5. 把响应回传给客户端。

因为最终请求是浏览器用完整网络栈发出的,所以 TLS、HTTP、TCP 各层指纹天然就是 Chrome 的,不需要逐字节手工对齐。

指纹样例(官方 README 给出的 JA4H 实测):

场景JA4H 指纹
curl 直连(未走代理)ge11nn090000_b6a016211e8a_000000000000_e3b0c44298fc
Chrome 直接访问同一 URLge11cn19enus_f2808f0d04cf_9a10d4221160_7068f58def6e
curl --proxy 走 Thermoptic 后ge11cn19enus_f2808f0d04cf_9a10d4221160_7068f58def6e(与 Chrome 一致)

官方称 JA4(TLS)、JA4H(HTTP)、JA4X(X509)、JA4T(TCP)四类指纹都会被对齐到所连 Chrome 的真实值。

围绕主链路,项目还提供了几样配套能力:

  • Hook 框架:ON_START(浏览器启动)、BEFORE_REQUEST(请求前)、AFTER_REQUEST(请求后)三个钩子,可在 Node 里用 CDP 驱动浏览器点击、过验证;仓库自带一个绕过 Cloudflare Turnstile 的 onstart.js 示例。
  • Cookie 注入:客户端在 Cookie 头里带的 cookie 会被载入浏览器上下文,避免服务端从 cookie 顺序等细节反推客户端身份。
  • Xpra Web 控制面板(http://127.0.0.1:14111):直接在浏览器里目视操作容器内的 Chrome,适合手动登录站点后,再让代理以已登录会话发请求。
  • 上游代理:通过 UPSTREAM_PROXY 把受控 Chrome 再接到任意 HTTP/SOCKS 上游(含带凭证的)。
  • 健康检查与自愈:内置探针检测冻结的浏览器会话,无人工干预自动重启。
  • 同时支持 HTTP/1.1 与 HTTP/2(客户端到代理、代理到目标站点可协商不同协议)。

Xpra Web 控制面板里可见的浏览器控制界面,以及作者用于自测的 Bot 检测页结果

四、路线对比:租浏览器,还是重写浏览器栈

官方在 README 里明确把自己和”重实现浏览器栈”的路线对立起来,并给出后者的三类根本缺陷:

  1. 必须完美对齐:任何行为怪癖(quirk)与真实浏览器的偏差都可被用来区分客户端;
  2. 只修一层不够:Chrome 跨 TCP/TLS/HTTP 多层协同,TLS 层对齐了,HTTP 层头部顺序仍可能暴露;
  3. 持续追赶成本:Chrome 频繁更新行为,栈重实现工具需要长期维护才能跟上新指纹。

Thermoptic 的对应优势是:各层由真浏览器自然产生,浏览器行为变化时只需更新被控制的 Chrome 版本,代理本身不用跟着改。

五、官方自认的局限与口径(不可回避)

作者专门维护了 DOWNSIDES.md,把这条路的代价写在明面上,这里按其原文口径归纳:

  • 资源与延迟开销大:每路隐身请求背后都是一个完整 Chrome 进程/会话,相比轻量栈模拟,内存、CPU 与往返延迟都显著更高,不适合海量并发。
  • CDP 本身可被探测:作者指出,CDP 控制通道(如 Runtime.enable 的使用痕迹)在特定行为下会成为新的机器人信号;Hook 临时切到全浏览器模式时尤其需要小心,这部分并没有被指纹方案自动掩盖。
  • 代理不会”读心”:Origin、Referer、X-Fetch-* 等上下文头部必须由调用方正确提供;缺省时代理会填可疑默认值(如 Origin: null、不发 Referer),反而暴露。
  • Cookie 会残留:请求注入的 cookie 在请求结束后仍留在浏览器里,清理逻辑需要自己写 AFTER_REQUEST 钩子,官方没有自动回收。
  • 只给可信客户端用:README 安全章节明确,Thermoptic 不应对不可信用户暴露,默认甚至建议自行设置 PROXY_USERNAME/PROXY_PASSWORD。
  • 上游代理可能破坏一致性:经过带 NAT/改写的上游代理时,TCP 等低层元数据可能改变,削弱与住宅浏览器的对等性。
  • JA4 之外不在覆盖范围:JS 运行时指纹、鼠标轨迹、行为节奏、渲染画布噪声等检测需要 Hook 手动配合,网络指纹对齐并不等于全量通过人机验证。

需要强调:上表中的 JA4H 字符串是作者在自家环境(特定 Chrome 版本)下测得的样例,换浏览器版本、换目标站点,指纹串会变;“逐字节一致”指的是”与当前这台受控 Chrome 一致”,而非固定等于某个公开指纹库的值。

六、适用与不适用场景

适合:结构化批量抓取中需要绕过 JA4+ 拦截的任务;需要复用一次手动登录会话、随后用脚本续跑的场景;浏览器过验证 + 底层客户端取数据的混合抓取;对成本不敏感、强调稳定性而非吞吐的小规模采集。

不适合:高并发、超低延迟的实时接口调用;纯移动端私有 API(无浏览器对应物);要求部署在极小内存环境的场景;把它当作对外公开代理服务暴露给第三方。

七、它意味着什么

Thermoptic 代表的思路转变值得关注:对抗指纹不再追求”在代码里复刻浏览器”,而是”在基础设施里租用一台真浏览器”。这把军备竞赛的成本模型从软件维护转向了资源消耗——防御方要面对的是成排的真实 Chrome 实例,而不是一个写得越来越像的协议栈。作者在 README 的伦理章节也直言,抓取与反爬已经变成一场资本消耗战,开源这把工具是为了让负担不起商业 Unlocker 服务的小团队也能获取公开信息;这一立场本身存在争议,使用者仍需遵守目标站点条款与当地法律。

参考来源