tech/protocol · 集群 B · 加密与安全边界 · 2/6

TLS 指纹是什么:ClientHello 特征、JA3/JA4 与客户端兼容的关系

发布时间 待核实核实日期 待核实最近更新 待核实测试状态 Not Tested
Answer First · 核心结论

TLS 指纹是由 ClientHello 中的协议版本、密码套件、扩展列表及其顺序等特征组合而成的标识,不同的 TLS 实现会产生不同的指纹。代理客户端常通过 uTLS 生成与常见浏览器相近的 ClientHello,订阅中的 fingerprint 参数即用于选择这一形态。普通用户应按订阅填写该参数,它影响兼容性,不影响加密强度。

什么是 TLS 指纹

TLS 指纹,是从 TLS 握手第一条消息 ClientHello 中提取出的一组特征,用来区分「是什么软件发起的这次握手」。浏览器、操作系统自带的网络库、各种编程语言的 TLS 库,在生成 ClientHello 时各有自己的习惯,这些习惯组合起来,就形成了相对稳定的指纹。

可以用一个类比来理解:TLS 规范像一张表格的模板,规定了能填哪些项;但不同的人填表时,选择填写的项目、填写顺序、默认值都不一样,看字迹和格式就能大致判断是谁填的。

ClientHello 中构成指纹的主要特征:

特征 内容 为什么能区分实现
协议版本 支持的 TLS 版本列表 新旧库支持范围不同
密码套件列表 支持的加密套件及顺序 每个库的默认列表与排序不同
扩展列表 SNI、ALPN、supported_groups 等 扩展种类和顺序差异明显
椭圆曲线与点格式 支持的曲线 各实现默认集合不同
签名算法 支持的签名方式 同上
GREASE 值 随机占位值 部分浏览器会插入,部分库不会

JA3 与 JA4:指纹如何被表示

为了让指纹可以被记录和比较,业界发展出了若干表示方法,JA3 与 JA4 是其中较常被提及的两种。

JA3 的做法是把 ClientHello 中的版本、密码套件、扩展、曲线、点格式等字段按固定顺序拼接成字符串,再计算哈希,得到一个固定长度的标识。它简单直观,但有一个弱点:当浏览器开始随机化扩展顺序后,同一个浏览器每次握手可能得到不同的 JA3 值。

JA4 是后来提出的方法,在设计上考虑了这类变化,例如对扩展进行排序后再计算,并把结果组织成带有可读前缀的结构,便于人工分析。两者的共同点是:它们都只是「描述」ClientHello 的方式,而不是检测手段本身。

ClientHello 原始字段
        │
        ├─ JA3:按顺序拼接 → 哈希 → 固定长度标识
        │
        └─ JA4:分组、排序 → 可读前缀 + 哈希片段

代理场景中为什么会谈到指纹

在代理场景中谈到 TLS 指纹,是因为代理客户端通常使用编程语言自带的 TLS 库(例如 Go 语言的标准库)发起握手,它生成的 ClientHello 与主流浏览器明显不同。当一个连接声称自己在访问某个普通网站,但 ClientHello 的形态与常见浏览器都不一致时,这本身就是一个可被观察的特征。

这正是集群 A 中 REALITY 等方案需要处理的问题:它们希望对外的握手形态尽量接近常见浏览器。协议识别是一个综合多种信号的领域,指纹只是其中之一,原理概述见 协议识别的原理。本站只做原理说明,不提供针对任何网络管理系统的规避方法。

uTLS 与 fingerprint 参数

uTLS 是一个可以按模板生成 ClientHello 的 TLS 库,许多代理内核用它来生成与常见浏览器相近的握手消息。订阅中出现的 fingerprint(或 client-fingerprint、fp)参数,就是在选择使用哪一种模板。

参数值示例 含义
chrome 生成与 Chrome 类浏览器相近的 ClientHello
firefox 生成与 Firefox 相近的 ClientHello
safari / ios 生成与 Apple 平台浏览器相近的 ClientHello
random / randomized 按内核规则随机选择或随机化
留空 使用内核默认 TLS 库的原生 ClientHello

几点需要理解的边界:

  • 这个参数只改变 ClientHello 的「外观」,不改变协商出来的加密算法强度,也不会让连接更快;
  • 不同内核支持的参数值不完全相同,填写客户端不认识的值可能报错或回退到默认行为;
  • 对于 REALITY 节点,fingerprint 是必需参数,留空或与服务端预期不符可能导致握手失败。

因此用户层面的建议很简单:照订阅填写,不随意修改。

指纹与客户端兼容

指纹问题在实际使用中更多表现为兼容性问题,而不是安全问题。常见情况包括:

现象:同一订阅,客户端 A 可用,客户端 B 握手失败
├─ B 的内核不支持 uTLS 或不认识该 fingerprint 值
├─ B 的版本较旧,uTLS 模板与服务端预期不一致
└─ B 不支持该节点的安全层类型(如 REALITY)

处理思路:
1. 确认两个客户端的内核类型与版本
2. 升级 B 到较新版本后重试
3. 仍失败 → 改用 A,或向服务商确认支持的客户端列表

客户端更新有时会更换 uTLS 模板,以跟进浏览器自身的变化,这意味着同一客户端在不同版本下的 ClientHello 可能不同。遇到「升级后突然连不上」或「降级后才能用」的情况,可以把客户端版本作为一个排查方向,同时参考 桌面客户端 与 移动客户端 专题。

指纹与隐私的关系

TLS 指纹标识的是软件,而不是个人,但这并不意味着它与隐私无关。在网站一侧,TLS 指纹常与浏览器指纹、IP、Cookie 等信息一起用于识别自动化流量或异常访问;在代理一侧,客户端指纹不会直接暴露你的身份,但同一设备长期使用固定特征,在理论上增加了关联的可能。

需要明确的是,代理协议的加密保护的是传输内容,浏览器层面的指纹(屏幕、字体、插件等)与 TLS 指纹是两个不同的概念,前者完全不受代理协议影响。这一区别在 加密不等于匿名 中有更多讨论。

小结

TLS 指纹是 ClientHello 在实现层面的「笔迹」,JA3、JA4 是把这种笔迹记录下来的方法,uTLS 与 fingerprint 参数则是代理客户端调整握手外观的手段。对普通用户而言,最实用的结论只有一条:按订阅填写、保持客户端版本较新,遇到握手失败时把内核与版本作为排查方向。

更多协议原理可回到 代理协议 专题总览;查看品牌的协议与客户端资料,可以前往 机场品牌库 或 对比工具。

常见问题

TLS 指纹会泄露我的个人身份吗?

TLS 指纹标识的是生成 ClientHello 的软件或库,而不是具体的人。但它与其他特征组合后,可能成为识别客户端类型的依据之一。

订阅里的 fingerprint 参数要不要改?

建议按订阅填写。REALITY 等方案依赖该参数生成特定形态的 ClientHello,随意修改可能导致握手失败,也不会提升加密强度。

JA3 和 JA4 有什么区别?

两者都是把 ClientHello 特征转换为可比较标识的方法。JA3 对字段直接拼接后取哈希;JA4 在设计上考虑了扩展顺序随机化等变化,结构更具可读性。

为什么同一个代理客户端在不同版本下表现不同?

客户端更新可能更换 TLS 库或 uTLS 模板,ClientHello 随之变化,与服务端或中间网络的兼容情况也可能改变,遇到问题可先确认客户端版本。

信息来源与更新时间

信息来源
品牌清单资料(品牌公开信息整理)
测试范围
本站未进行测速与解锁实测,所有能力描述均为资料声明或未测试状态。
发布时间
待核实
核实日期
待核实
最近更新
待核实

字段含义与数据状态见 字段说明;核查进度见 品牌动态与核查日志。