curl-impersonate JA3 指纹原理与复现

curl-impersonate JA3 指纹原理与复现

前言

本文通过实际抓包验证,深入分析 curl-impersonate 的 TLS 指纹生成机制,并完整复现了 curl_chrome110 的 JA3 哈希计算全过程。

环境说明:curl-impersonate 安装于 /root/PycharmProjects/python-api/curl-impersonate/

一、curl-impersonate 核心原理

curl-impersonate 是一个魔改版 curl,在标准 curl 基础上添加了一系列自定义 flag 来模拟特定浏览器的 TLS 和 HTTP 指纹。

1.1 TLS 指纹层级

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌─────────────────────────────────────────────┐
│ TLS 指纹 │
├──────────────┬──────────────┬────────────────┤
│ TLS 版本 │ Cipher 套件 │ TLS 扩展顺序 │
1.2 / 1.3 │ JA3 核心 │ Chrome 特有 │
└──────────────┴──────────────┴────────────────┘

┌─────────────────────────────────────────────┐
│ HTTP/2 指纹 │
├──────────────┬──────────────┬────────────────┤
│ Pseudo-header│ SETTINGS │ ALPS 扩展 │
│ 顺序 │ 帧顺序 │ (Chrome 私有) │
└──────────────┴──────────────┴────────────────┘

┌─────────────────────────────────────────────┐
│ HTTP Header 指纹 │
├──────────────┬──────────────┬────────────────┤
│ sec-ch-ua │ User-Agent │ Accept-Language
└──────────────┴──────────────┴────────────────┘

1.2 curl_chrome110 完整配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env bash
dir=${0%/*}

"$dir/curl-impersonate-chrome" \
--ciphers TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-CHACHA20-POLY1305,ECDHE-RSA-CHACHA20-POLY1305,ECDHE-RSA-AES128-SHA,ECDHE-RSA-AES256-SHA,AES128-GCM-SHA256,AES256-GCM-SHA384,AES128-SHA,AES256-SHA \
-H 'sec-ch-ua: "Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "Windows"' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36' \
--http2 --http2-no-server-push --false-start \
--tlsv1.2 --no-npn --alps --tls-permute-extensions \
--cert-compression brotli \
"$@"

1.3 关键 Flag 解析

Flag 作用
--ciphers TLS 加密套件列表,决定 JA3 哈希
--cert-compression brotli 证书压缩算法(Chrome 特有)
--false-start TLS False Start(Chrome 性能优化)
--alps ALPS 扩展(HTTP/2 早期加密,Chrome 私有)
--tls-permute-extensions 打乱 TLS 扩展顺序(BoringSSL 特性)
--http2-no-server-push 禁用 HTTP/2 Server Push

二、JA3 哈希算法详解

2.1 JA3 生成公式

1
2
3
4
5
6
7
8
9
JA3 = MD5(
TLS版本 +
Cipher数量 +
Cipher列表(Hex IANA, comma分隔) +
Extension数量 +
Extension列表(Decimal ID, dash分隔) +
椭圆曲线(Decimal ID, comma分隔) +
椭圆曲线点格式
)

2.2 TLS 版本字段

TLS 版本 Hex 值 JA3 中表示
TLS 1.0 0x0301 769
TLS 1.1 0x0302 770
TLS 1.2 0x0303 771
TLS 1.3 0x0304 772

Chrome 110 使用 TLS 1.2,所以版本字段为 771

2.3 Cipher Suites(15个)

序号 IANA 名称 Hex 值
1 TLS_AES_128_GCM_SHA256 1301
2 TLS_AES_256_GCM_SHA384 1302
3 TLS_CHACHA20_POLY1305_SHA256 1303
4 ECDHE-ECDSA-AES128-GCM-SHA256 c02c
5 ECDHE-RSA-AES128-GCM-SHA256 c02f
6 ECDHE-ECDSA-AES256-GCM-SHA384 c024
7 ECDHE-RSA-AES256-GCM-SHA384 c02b
8 ECDHE-ECDSA-CHACHA20-POLY1305 cca9
9 ECDHE-RSA-CHACHA20-POLY1305 cca8
10 ECDHE-RSA-AES128-SHA c013
11 ECDHE-RSA-AES256-SHA c014
12 AES128-GCM-SHA256 009c
13 AES256-GCM-SHA384 009d
14 AES128-SHA 002f
15 AES256-SHA 0035

2.4 TLS Extensions(16个,真实顺序)

Chrome 110 在 ClientHello 中发送的扩展顺序:

ID 名称 说明
23 ALPN 应用层协议协商
13 supported_versions TLS 1.3 版本支持
51 key_share TLS 1.3 密钥共享
5 status_request OCSP 证书状态请求
65281 0xff01 GREASE(Chrome 随机插入)
0 server_name SNI 主机名
27 compress_certificate 证书压缩
43 supported_versions TLS 1.2 客户端版本
16 encrypt_then_mac 加密后 MAC
10 supported_signature_algorithms 支持的签名算法
45 psk_exchange_modes PSK 交换模式
17513 0x4469 GREASE
18 signed_certificate_timestamp SCT 时间戳
35 session_ticket 会话票据
11 use_srtp SRTP 媒体加密
21 padding 填充

2.5 椭圆曲线

ID 名称
29 X25519
23 secp256r1
24 secp384r1

三、实际验证

3.1 抓取真实 TLS 指纹

使用 curl_chrome110 访问 Browserleaks:

1
./curl_chrome110 "https://tls.browserleaks.com/json"

返回结果:

1
2
3
4
5
6
7
{
"ja4": "t13d1516h2_8daaf6152771_e5627efa2ab1",
"ja3_hash": "7005d6191e610731aab6434cfa305597",
"ja3_text": "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,23-13-51-5-65281-0-27-43-16-10-45-17513-18-35-11-21,29-23-24,0",
"ja3n_hash": "aa56c057ad164ec4fdcb7a5a283be9fc",
"ja3n_text": "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-5-10-11-13-16-18-21-23-27-35-43-45-51-17513-65281,29-23-24,0"
}

3.2 JA3 与 JA3n 的区别

特性 JA3 JA3n
Extension 顺序 ClientHello 真实顺序 按 ID 从小到大排序
用途 追踪特定浏览器配置 简化版指纹匹配
1
2
JA3n extensions:  0-5-10-11-13-16-18-21-23-27-35-43-45-51-17513-65281  (排序)
JA3 extensions: 23-13-51-5-65281-0-27-43-16-10-45-17513-18-35-11-21 (真实顺序)

3.3 Chrome 109+ GREASE 随机化

Chrome 109 (2022年1月) 引入重大变化:GREASE 值从固定改为随机

Chrome 109 之前的 GREASE

Chrome 在 ClientHello 中插入固定的 GREASE 扩展值,JA3 指纹是稳定的

1
2
Chrome 109之前: JA3 = 771,4865-4866-...,23-13-51-5-65281-0-27-...  (固定)
↑ 固定 GREASE 值 0xff01 (65281)

Chrome 109 之后的 GREASE

每次连接 GREASE 值从池中随机选择,导致同一个版本的浏览器每次请求 JA3 都不同:

1
2
Chrome 109之后: JA3 = 771,0a0a-4865-4866-...,23-13-51-0a0a-5-65281-0-27-...  (随机)
↑ 随机插入一个 GREASE 值 (0a0a, 1a1a, 2a2a...)

GREASE 值池(Chrome 定义的保留值):

GREASE 值 用途
0x0a0a Application Settings
0x1a1a Reserved (GREASE)
0x2a2a Reserved (GREASE)
0x3a3a Reserved (GREASE)
0xFAFA Reserved (GREASE)

实际影响

对比 Chrome 109 之前 Chrome 109 之后
JA3 稳定性 固定,可用于识别 每次不同,指纹库匹配失效
JA3 Hash 数量 1个/浏览器版本 N个/浏览器版本
反爬策略 匹配 JA3 Hash 需要 JA3n 或多维度指纹

这就是为什么 curl-impersonate 的 curl_chrome110 在 Section 3.1 的返回中,JA3n(扩展排序后)是稳定的,而 JA3 依赖 GREASE 注入来模拟随机化。


3.4 JA4 哈希格式

JA4 是 2022 年发布的升级版指纹标准,比 JA3 更易读,且不受 GREASE 随机化影响

1
t13d1516h2_8daaf6152771_e5627efa2ab1

JA4 各字段含义(以 t13d1516h2_8daaf6152771_e5627efa2ab1 为例):

字段 位置 含义 示例值
p 1字符 传输协议 t=TLS over TCP, q=QUIC, d=DTLS
v 2字符 TLS 版本 13=1.3, 12=1.2, 10=1.0
s 1字符 SNI 有无 d=有域名, i=无 SNI
c 2字符 密码套件数量 15=15个
e 2字符 扩展数量 16=16个
a 2字符 ALPN 首尾字符 h2=http/2, h3=http/3
_ 分隔符 - -
b 12字符 密码套件列表的 SHA256 前12位 8daaf6152771
_ 分隔符 - -
d 12字符 扩展列表+签名算法的 SHA256 前12位 e5627efa2ab1

b 字段计算示例(15个密码套件按十六进制排序后哈希):

1
2
3
原始顺序: 1301,1302,1303,c02b,c02f,c02c,c030,cca9,cca8,c013,c014,009c,009d,002f,0035
排序后: 002f,0035,009c,009d,1301,1302,1303,c013,c014,c02b,c02c,c02f,c030,cca8,cca9
SHA256: 8daaf6152771...

c 字段计算示例(扩展按十六进制排序、去 SNI/ALPN 后再加签名算法哈希):

1
2
3
4
原始扩展: 001b,0000,0033,0010,4469,0017,002d,000d,0005,0023,0012,002b,ff01,000b,000a,0015
排序去重: 0005,000a,000b,000d,0012,0015,0017,001b,0023,002b,002d,0033,4469,ff01
加签名: 0005,000a,000b,000d,0012,0015,0017,001b,0023,002b,002d,0033,4469,ff01_0403,0804,0401...
SHA256: e5627efa2ab1...

关键设计:GREASE 值在计算 b 和 c 字段时会被忽略(不参与排序和哈希),因此 Chrome 109+ 的 GREASE 随机化对 JA4 没有影响,这是 JA4 优于 JA3 的核心原因。

JA4 的设计目标:

  1. 人类可读 — 不需要解码十六进制
  2. GREASE 免疫 — 不受 Chrome 109+ 随机 GREASE 影响
  3. 可组合 — 各字段独立,可做细粒度匹配
  4. 协议无关 — 支持 TLS、QUIC、HTTP/2、HTTP/3

四、Python 复现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import hashlib

def compute_ja3n(ciphers_hex, extensions_ids_sorted, curves):
"""
计算 JA3n 哈希(标准 Salesforce JA3 算法)
"""
ja3n_str = (
"771," # TLS 1.2
f"{len(ciphers_hex)},"
f"{','.join(ciphers_hex)},"
f"{len(extensions_ids_sorted)},"
f"{'-'.join(str(e) for e in extensions_ids_sorted)},"
f"{'-'.join(str(c) for c in curves)},"
"0"
)
return hashlib.md5(ja3n_str.encode()).hexdigest()

# curl_chrome110 的 JA3n
ciphers = ["1301","1302","1303","c02c","c02f","c024","c02b",
"cca9","cca8","c013","c014","009c","009d","002f","0035"]
extensions = [0,5,10,11,13,16,18,21,23,27,35,43,45,51,65281,17513]
curves = [29,23,24]

ja3n_hash = compute_ja3n(ciphers, extensions, curves)
print(f"JA3n: {ja3n_hash}") # aa56c057ad164ec4fdcb7a5a283be9fc ✅

五、相关工具与仓库

5.1 核心工具

仓库 Stars 说明
lexiforest/curl_cffi 5373 Python 版 curl-impersonate,推荐使用
salesforce/ja3 3085 原始 JA3 规范与实现
FoxIO-LLC/ja4 1851 JA4 升级版指纹

5.2 curl_cffi 使用示例

1
2
3
4
5
6
7
8
from curl_cffi import requests

# 直接模拟 Chrome 110
response = requests.get(
"https://tls.browserleaks.com/json",
impersonate="chrome110"
)
print(response.json())

5.3 指纹查询网站

六、总结

  1. JA3 哈希 = TLS ClientHello 的指纹,由 cipher 套件、扩展列表、椭圆曲线等字段计算得出
  2. Chrome 109 之前:同一浏览器版本的 JA3 固定,全球一致
  3. Chrome 109 之后:GREASE 值随机化,同一版本每次请求 JA3 都不同,JA3 Hash 匹配失效
  4. JA3n 是 JA3 的排序版本,将扩展按 ID 排序后计算哈希,更稳定
  5. JA4 是升级版指纹,人类可读、不受 GREASE 影响、支持多协议
  6. curl-impersonate 预置脚本已覆盖主流浏览器版本,直接使用即可复现真实浏览器指纹
  7. Python 推荐用 curl_cffi,比 bash 脚本更易于集成到项目

参考


curl-impersonate JA3 指纹原理与复现
https://kingjem.github.io/2026/04/09/curl-impersonate-JA3-TLS-Fingerprint/
作者
Ruhai
发布于
2026年4月9日
许可协议