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 特征
JA3 是识别和检测各类客户端流量的有力工具,在代理服务与机器人检测场景中尤为如此。懂得如何解读并应对 JA3 指纹,对代理服务商和使用者而言都至关重要。
