JA3 指纹是从 TLS Client Hello 消息中的特定字段派生出的 MD5 哈希值,用于唯一标识发起 TLS 连接的客户端应用或库,因而成为 TLS 客户端指纹识别和代理检测的一种可靠方法。
理解 TLS 客户端指纹识别
当客户端发起 TLS 握手时,它会发送一条 Client Hello 消息,其中包含建立安全连接所需的各类参数。这些参数包括 TLS 版本、支持的 cipher suite 列表、扩展、椭圆曲线以及椭圆曲线格式。这些参数的具体组合和排列顺序,往往是某个客户端应用、操作系统和 TLS 库所独有的。凭借这种独特的签名,即使其他标识信息(如 user-agent 字符串)被修改或缺失,也能识别出客户端。
什么是 JA3 指纹?
JA3 由 Salesforce 开发,是一种为 Client Hello 消息生成标准化指纹的方法。它关注 Client Hello 中的五个关键字段:
- TLS 版本: 客户端支持的最高 TLS 版本。
- Cipher Suite: 客户端支持的 cipher suite 列表,按优先级排序,以逗号分隔。
- TLS 扩展: 客户端包含的 TLS 扩展列表,按类型排序,以逗号分隔。
- 椭圆曲线: 支持的椭圆曲线列表,以逗号分隔。
- 椭圆曲线格式: 支持的椭圆曲线格式列表,以逗号分隔。
这五个值会拼接成一个字符串:列表内部用 "," 分隔,五个主字段之间用 "-" 分隔。随后对该拼接字符串做 MD5 哈希,得到最终的 32 位 JA3 指纹。使用 MD5 是为了简短和一致,而非出于密码学安全考虑。
JA3 计算示例
假设有一个 Client Hello,参数如下:
- TLS 版本:
0x0303(TLS 1.2) - Cipher:
0xc02c,0xc02b,0xc030,0xc02f,0x009c,0x0095 - 扩展:
0x0000,0x000b,0x000a,0x0012,0x0023,0x0017,0x0010,0x0035,0xff01,0x000d,0x0005 - 椭圆曲线:
0x001d,0x0023,0x0024 - 椭圆曲线格式:
0x0000,0x0001,0x0002
拼接后的字符串为:
769,49164-49163-49168-49167-156-149,0-11-10-18-35-23-16-53-65281-13-5,29-35-36,0-1-2
该字符串的 MD5 哈希即为 JA3 指纹,例如 e66a3d11b302c086d0b604e769494441。
JA3 在代理检测中的作用
代理,尤其是正向代理以及执行 TLS 拦截的代理,常常会修改 TLS 连接,或将其终止后重新发起。这一过程必然改变 Client Hello 消息,从而产生与原始客户端不同的 JA3 指纹。
代理如何影响 JA3 指纹
-
正向代理(HTTPS): 当客户端连接到 HTTPS 代理时,代理会与目标服务器建立新的 TLS 连接。目标服务器看到的
Client Hello消息来自代理软件,而不是最终客户端。因此,JA3 指纹反映的是代理的 TLS 栈(例如 Squid、Nginx、HAProxy 或自研代理软件),而非终端用户实际使用的浏览器或应用。这种不一致是使用代理的强烈信号。 -
TLS 拦截代理(MITM): 这类代理会明确终止来自客户端的 TLS 连接,并与目标建立一条全新的、独立的 TLS 连接。这在企业环境的流量审查中很常见,恶意攻击者也会使用。发往目标服务器的
Client Hello由拦截代理生成,因而产生带有拦截软件特征的 JA3 指纹。 -
SOCKS 代理: SOCKS 代理可以工作在更低的层次,隧道转发原始 TCP 连接。如果 SOCKS 代理只是转发 TCP 流而不修改 TLS 握手,客户端的原始
Client Hello就可能原封不动地通过,JA3 指纹保持不变。不过,许多 SOCKS 实现或特定配置仍可能终止并重新发起 TLS,或改动头部信息,从而导致 JA3 发生变化。
用 JA3 识别代理
通过分析收到的 Client Hello 消息,服务器可以:
- 发现不一致: 将 JA3 指纹与
User-Agent头等其他客户端标识进行比对。如果User-Agent声称是 Windows 上的 Chrome,但呈现的 JA3 指纹已知属于某代理服务器或某个特定的抓取库,就说明存在代理使用或伪装。 - 对流量分类: 识别来自已知代理服务、数据中心或使用统一 TLS 栈的僵尸网络的流量。
- 拦截/限速: 制定策略,对与不良流量(例如爬虫、机器人或被入侵的系统)相关的特定 JA3 指纹进行封锁或限速。
JA3 与 JA3S
JA3 针对客户端的 Client Hello 生成指纹,而 JA3S(JA3 Server)针对服务器的 Server Hello 消息生成指纹。JA3S 关注 Server Hello 中的 TLS 版本、cipher suite 和扩展。它对识别服务器端的 TLS 实现很有用,但对客户端代理检测的直接适用性较弱。
局限性与规避手段
JA3 指纹识别虽然有效,却并非万无一失:
- 伪装: 成熟的客户端、机器人或代理服务可以被配置成刻意模仿特定的 JA3 指纹,从而伪装成合法浏览器。这需要能够控制 TLS 库的
Client Hello参数。 - TLS 库更新: TLS 库(例如 OpenSSL、NSS、BoringSSL)或操作系统的更新可能改变
Client Hello参数,使得原本完全相同的客户端产生不同的 JA3 指纹。因此必须持续监控并更新 JA3 特征库。 - 库的多样性: 不同的 HTTP 客户端库(例如 Python 的
requests、Go 的net/http、Node.js 的https)及其底层 TLS 实现(例如 OpenSSL、GnuTLS、BoringSSL、Go 的crypto/tls)天然会产生不同的 JA3 指纹。
JA3 是识别和检测各类客户端流量的有力工具,在代理服务和机器人检测场景中尤为重要。懂得如何解读并应对 JA3 指纹,对代理服务商和使用者双方都至关重要。
