tech/protocol · 集群 B · 加密与安全边界 · 2/6
TLS 指纹是什么:ClientHello 特征、JA3/JA4 与客户端兼容的关系
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 随之变化,与服务端或中间网络的兼容情况也可能改变,遇到问题可先确认客户端版本。
信息来源与更新时间
- 信息来源
- 品牌清单资料(品牌公开信息整理)
- 测试范围
- 本站未进行测速与解锁实测,所有能力描述均为资料声明或未测试状态。
- 发布时间
- 待核实
- 核实日期
- 待核实
- 最近更新
- 待核实