01 · 指纹家族算法详解
1.1 JA3 / JA3S:五元组与MD5(Salesforce, 2017)
JA3是TLS指纹的奠基方法,由Salesforce检测云团队的John Althouse、Jeff Atkinson、Josh Atkins创建并开源。其对ClientHello提取五个字段,按出现顺序、以短横线连接列表元素、以逗号连接字段,生成待哈希字符串后取MD5:
五元组字段拼接
原始实现见Salesforce官方GitHub仓库(salesforce/ja3),提供Zeek脚本与Python解析器,并随仓库提供测试用pcap。
ServerHello三元组
JA3S单独使用时判别力有限,但"JA3+JA3S"联合查询可显著缩小实现族范围(如区分CDN后端与源站直连)——这也是指纹查询库(如JA3er)支持双字段检索的原因。
JA3的工程缺陷:其一,MD5黑盒导致指纹不一致时无法人工诊断差异来源;其二,对GREASE的处理依赖具体实现版本;其三,对TLS 1.3的supported_versions语义支持不佳;其四,顺序敏感——2023年起Chromium对扩展顺序进行随机化(Chrome 110正式启用),JA3在现代浏览器流量上系统性失稳(第1页已述Fastly的实测证据),社区以JA3N(排序归一化)缓解,根治方案是JA4。
1.2 JA4与JA4+家族:分段可读设计(FoxIO, 2023)
JA4由FoxIO发布(John Althouse主导设计),将指纹拆为三段:JA4_a为可读前缀——传输方式(t=TCP / q=QUIC)+ 最高版本(13=TLS 1.3 / 12=TLS 1.2)+ SNI有无(d/i)+ 密码套件数量与扩展数量(各两位十六进制计数,超过99封顶) + ALPN编码(取首个ALPN值的首字符与尾字符,如h2、http/1.1→h1);JA4_b为排序后密码套件列表的截断SHA256(12字符);JA4_c为排序后扩展列表与签名算法的截断SHA256(SNI与ALPN扩展不参与c段——二者的语义已在a段体现;签名算法列表保持原始顺序;规范要求剔除GREASE取值)。排序设计使JA4天然免疫扩展顺序随机化。
来自FoxIO官方文档:t13d1516h2_8daaf6152771_b186095e22b6
三段可独立比对:a段快速过滤(如"只可能是HTTP/2浏览器"),b/c段精确定位实现;调试时可直接读出"这是一个走TCP、TLS 1.3、带SNI、ALPN为h2的客户端"。规范另定义JA4_r原始变体(保留未排序的原始列表),供排查与离线比对使用。
JA4_a各字段语义速查
| 位置 | 取值示例 | 语义 |
|---|---|---|
| 第1位 | t / q | 传输方式:t=TCP,q=QUIC(HTTP/3) |
| 第2-3位 | 13 / 12 | 协商所得最高TLS版本(13=TLS 1.3,12=TLS 1.2) |
| 第4位 | d / i | 是否包含SNI:d=domain(含SNI),i=IP(无SNI) |
| 第5-6位 | 15 | 密码套件数量,两位十六进制(0x15=21个;超过99记为99) |
| 第7-8位 | 16 | 扩展数量,两位十六进制(0x16=22个;超过99记为99) |
| 第9-10位 | h2 / h1 / 00 | ALPN编码:首字符+尾字符;无ALPN扩展时记00 |
JA4+将同一思想推广到更多协议面,形成持续扩展的家族(以下清单以FoxIO仓库README公开列表为准):
| 变体 | 协议层 | 观测对象 | 典型用途 |
|---|---|---|---|
| JA4 | TLS客户端 | ClientHello(被动) | 浏览器/工具/恶意客户端识别,机器人预检主力特征 |
| JA4S | TLS服务端 | ServerHello + 选定参数(被动) | 服务器实现识别、CDN与源站区分 |
| JA4H | HTTP | HTTP请求头顺序与取值(被动) | 浏览器指纹补充、headless工具识别 |
| JA4X | X.509 | 证书字段(序列号、有效期、扩展、公钥参数) | 证书生态异常发现、自签/仿冒证书聚类 |
| JA4T / JA4TS | TCP客户端/服务端 | 初始窗口、MSS、选项顺序、TTL等 | 操作系统级被动识别(与p0f同类)/ 服务端TCP栈识别 |
| JA4L / JA4LS | 时序 | 握手往返时序与包长序列 | 距离推断、0-RTT/会话恢复场景补充 |
| JA4SSH | SSH | SSH握手算法协商 | SSH实现识别(HASSH思想的现代化重述) |
| JA4D / JA4N | DHCP / NTP | DHCP请求指纹 / NTP包特征 | 内网设备识别 / 时间服务实现识别 |
| JA4TScan / JA4Scan | 主动探测 | 主动TCP/TLS/QUIC扫描 | 授权环境资产与服务端实现测绘 |
工具支持:Wireshark 4.4起原生内置JA3/JA4客户端指纹显示(tls.handshake.ja4);JA4S等完整JA4+家族可安装FoxIO官方Wireshark插件(ja4.ja4s)。Python/Rust参考实现与Zeek脚本见同一仓库。
1.3 JARM:主动探测范式(Salesforce, 2020)
JA3/JA4是被动方法——必须等到目标主动发起握手。JARM反其道而行:探测者主动向目标IP:端口发送10个精心构造的ClientHello,每个探针在TLS版本、密码套件与扩展组合上各不相同(包括故意声明废弃版本与非常规套件),观察服务器如何处理:是否拒绝、以何种Alert拒绝、协商出什么版本与套件。10次响应的模式被哈希为62字符的JARM指纹。
- 价值:被动方法看不到"没人连接的服务器";JARM可主动测绘C2基础设施——Cobalt Strike、Metasploit等框架的默认TLS实现有特异响应模式,威胁情报平台常将其用于C2资产发现与聚类;
- 边界:指纹反映"服务器对探针的响应行为",可被定制配置显著改变;且主动探测本身产生流量,授权边界必须先行确认——这一约束与本学院攻防演练的授权规范一致。
1.4 HASSH:SSH协议的等价物(Salesforce, 2018)
HASSH由Salesforce检测云团队的Ben Reardon创建(Adel Karimi参与贡献,灵感来自JA3),2018年9月开源。它提取SSH_MSG_KEXINIT消息中的密钥交换、加密、MAC、压缩四类算法列表,以分号连接后取MD5,分别生成客户端hassh与服务器hasshServer。SSH在自动化运维、代理跳转与数据外传场景中大量使用,HASSH为无TLS场景提供同等的实现识别能力。可验证的生态事实:Wireshark自3.6.0起内置hassh/hasshServer字段(ssh.kex.hassh);Shodan支持ssh.hassh查询字段;Salesforce原始仓库现由其原作者在Corelight维护活跃分支;Zeek可通过社区软件包将HASSH写入ssh.log。JA4SSH可视为同一思路在JA4+框架内的现代化重述。
1.5 四种方法能力对比
02 · 提取工程管线
2.1 采集点选择:从SPAN到eBPF
指纹质量的上限在采集点决定。可选路径按侵入性与可见性排序:交换机SPAN/RSPAN端口镜像(零侵入但可能丢包、无时序保真)、网络TAP分光(硬件级复制,时序保真,成本较高)、主机侧eBPF/XDP探针(内核态抓取,可与本课题"eBPF实时检测框架"子课题复用同一探针体系,支持五元组过滤与只抓首包降低开销)、以及TLS终结点前采集(可见解密后流量,但失去"被动观察者视角"的证据效力——适合检测、不适合取证叙事)。检测侧推荐eBPF方案:仅对TCP首包或QUIC Initial触发解析,常态开销可忽略。
2.2 解析与归一化:正确性即生命线
解析器的正确性规范(任何一条违反都会导致指纹库污染):
流重组
按五元组重组TCP字节流;QUIC需解析Initial包中的CRYPTO帧;分片与乱序必须在指纹计算前完成。
GREASE剔除
按RFC 8701规则识别0x?a?a形态取值并从套件/扩展/曲线列表中剔除,保留相对顺序。
排序归一化
JA4的b/c段对列表排序后再哈希——必须实现为稳定归一化,否则浏览器扩展随机化会使同一实现产生不同指纹(JA3失稳的教训)。
版本语义
TLS 1.3以supported_versions扩展为准而非legacy_version;QUIC按JA4的q前缀规则处理传输参数。
真实世界的解析器缺陷(均已公开修复,可直接溯源):① nDPI的JA4实现曾把ALPN"http/1.1"的首尾字符误取为"ht"而非"h1"(ntop/nDPI Issue #2914,2025年7月),导致其指纹与Wireshark等其他实现互不兼容;② Wireshark 4.4.2修复JA4_c空字段哈希错误(Issue 20066)、4.4.4修复空密码套件列表场景的JA4错误(Issue 20394,均见官方发布说明)。这印证"解析器正确性即生命线"绝非口号——同一握手在不同解析器中产出不同指纹,是评估指纹库互操作性时必须实测的事项。
2.3 编码、存储与版本管理
生产指纹库应记录:指纹值、规范版本、采集点类型、解析器版本、首末观测时间与观测计数。规范仍在演进——JA4+文档持续修订,不同版本解析器对同一握手的计算结果可能不同,因此"指纹+规范版本"是不可拆分的复合主键。社区库(JA4DB)采用可信度评分与众包验证机制缓解标注质量问题;自建库则应保留原始ClientHello样本哈希,以便规范升级时重算指纹。表结构示意:
解析器正确性自检清单:① GREASE剔除——对固定实现多次握手,剔除后字段列表恒定;② 排序归一化——对随机化扩展顺序的输入,排序后哈希恒定;③ 官方测试向量——以FoxIO仓库附带的pcap样例与预期输出做自动化回归(仓库自带pytest比对脚本);④ 分桶——完整握手与PSK恢复握手分别建库;⑤ 版本记录——指纹值与规范版本、解析器版本作为复合主键留存;⑥ 交叉验证——同一pcap分别用Wireshark与自研解析器计算,比对结果应完全一致。
2.4 性能与资源预算
指纹管线位于流量路径上,性能设计直接决定可部署性。工程要点:①采集层"首包触发"——eBPF探针仅在SYN/ACK后首个TLS记录(或QUIC Initial)到达时唤醒解析逻辑,常态CPU开销趋近于零,这也与本课题"eBPF实时检测框架"子课题的探针体系同源;②解析层无载荷驻留——握手特征提取后即可释放缓冲,单条流内存占用为O(1);③存储层按键去重——以"指纹值+规范版本"为复合键,观测计数累加,热数据常驻内存、冷数据批量落盘。
公开吞吐基准可参考:nDPI官方CHANGELOG持续披露单核近似口径的测试数据——v3.4约1.29M pps / 3.35 Gbps,v4.0约3.35M pps / 8.68 Gbps(以官方记录为准);其开销主体在协议识别而非指纹计算本身,说明"握手特征提取"在千兆级链路上具备工程可行性。自建系统上线前应按目标链路的pps与并发连接数压测,并将GREASE剔除、排序归一化的回归测试纳入发布门禁。
2.5 哈希截断、冲突概率与许可边界
冲突定量分析(可直接推导复核)。JA4_b与JA4_c各取SHA-256摘要的前12个十六进制字符,即48比特输出空间。按生日界估算,独立均匀指纹约需2^24(≈1.7×107)条量级才会出现"任意两指纹碰撞"的期望;JA4DB与JA3er公开库当前十万条量级距该阈值尚有两个数量级以上余量。且JA4以"a_b_c三段联合"作为完整指纹,b段或c段单独冲突不会导致整体误判;工程上可保留JA4_r原始列表用于碰撞复核。JA3使用完整MD5(128比特摘要空间),其工程痛点始终是可读性与顺序敏感性,而非碰撞风险。
许可边界(商用集成前必读):FoxIO将核心JA4方法以BSD 3-Clause许可发布;JA4+家族中的其余方法(JA4H、JA4S、JA4X、JA4T等)采用FoxIO自有许可且部分专利在审——商业产品集成前须查阅github.com/FoxIO-LLC/ja4仓库的Licensing说明。nDPI作者在公开技术分享中亦专门指出了JA4核心与JA4+其他成员的许可差异。这一区分直接影响选型:Wireshark内置JA4、Zeek JA4脚本等开源路径,与商业产品所需授权范围并不相同,采购评估时应将其列为尽调项。
03 · TLS 1.3 / QUIC / ECH 适配要点
TLS 1.3下的指纹适配
TLS 1.3(RFC 8446)握手为1-RTT:ClientHello的supported_versions扩展宣告真实版本,legacy_version恒为0x0303;ServerHello之后全部消息加密,被动观察者失去证书明文。指纹层面:密码套件列表仅剩5个AEAD套件可选,判别信息密度下降,扩展组合(key_share、supported_versions、psk_key_exchange_modes、signature_algorithms的取舍)成为主要判别维度;JA3原始五元组在1.3下仍可计算但稳定性受扩展随机化侵蚀,JA4_a直接编码版本语义且列表排序,因而更稳健。
QUIC/HTTP3下的指纹适配
QUIC(RFC 9000)将传输与加密合并:版本协商、传输参数与TLS握手共存于Initial加密包。JA4对QUIC客户端以"q"前缀区分,其判别维度除TLS参数外还包括QUIC版本与传输参数的组合。HTTP/3(RFC 9114)使浏览器指纹体系从纯TLS扩展到"TLS+QUIC"联合观测,单一维度仿冒难度显著上升。探测侧注意:QUIC基于UDP,传统TCP重组管线需扩展支持CRYPTO帧提取。
ECH(RFC 9849)下的指纹适配
ECH以HPKE(RFC 9180)加密的ClientHelloInner封装真实SNI与目标扩展,外层ClientHelloOuter仅暴露public_name;ECHConfig公钥经HTTPS/SVCB DNS记录(RFC 9460)与配套的配置发布机制(RFC 9848)分发。影响分层:域名级明文识别失效;但外层ClientHello的密码套件、扩展结构仍由真实客户端实现决定——指纹信号完整保留,只是失去与明文域名的绑定。JA3/JA4从设计上不读取SNI明文(JA4_a仅用计数与长度编码),ECH前后其值域稳定。ECH同时要求客户端发送GREASE ECH扩展(伪造的加密负载),使网络中间盒无法简单按"是否含ECH扩展"分流,进一步模糊识别边界。检测实践应将"指纹命中+目的IP信誉"替代"指纹命中+明文SNI"作为ECH时代的主查询模式。
会话恢复与0-RTT的影响
TLS 1.3会话恢复通过pre_shared_key扩展实现,0-RTT通过early_data扩展宣告。两者改变扩展组合与包序列:恢复握手中key_share可能缩减、Certificate消息缺席。JA3/JA4计算以ClientHello为对象,恢复握手同样产生可计算指纹,但其值域与完整握手不同——指纹库必须区分"完整握手指纹"与"恢复握手指纹"两类样本,否则同一客户端会被聚成两个簇。EarlyData的流量形态(首包载荷较大)则可作为JA4L时序特征的补充信号。
04 · 隐私与合规边界
TLS指纹处于"网络监测"与"设备识别"的交叉地带,部署时必须回答三个合规问题:采集是否最小化——建议只提取握手特征并丢弃载荷,eBPF探针开启首包过滤;用途是否限定——指纹数据仅用于授权范围内的安全检测,不得用于个人追踪(指纹本身通常不指向自然人,但与账号日志关联后即具备画像能力);是否可审计——留存策略、访问控制与导出审批应成文。对迪妙网络空间安全学院的企业培训场景,我们将其浓缩为一句可执行的话:"指纹是线索,不是结论;采集有边界,使用有授权。"
小结:本页完成了从算法(JA3/JA4/JARM/HASSH)到工程(采集/解析/存储)再到协议演进适配的体系构建。第3页将收束于检测应用实践:C2识别、机器人预检、对抗与误报控制、评估基准与全部参考文献。
终审核验声明:本页算法细节(JA3五元组、JA4三段式与a段字段语义、JARM十探针、HASSH四类算法列表)、解析器缺陷案例(nDPI Issue #2914、Wireshark 4.4.2/4.4.4)与工具版本信息,已于2026年9月15日对照官方仓库与发布说明逐条复核。