4. TLS 流量特征分析:记录层与协议结构

大家好,欢迎来到第四章。前面我们聊了TLS握手的基本流程,也看了加密套件如何工作。但真正要分析加密流量,核心还是要看懂TLS的“包装纸”——也就是记录层协议。

很多人刚开始抓包时,看到一堆“Application Data”就头大。其实,TLS自己把数据分得很清楚。你只要搞懂它的格式,加密流量也就没那么神秘了。我个人习惯先从记录层格式入手,这就像拆快递,先看外包装,再看里面装了什么。

核心观点: TLS 记录层是 TLS 协议在最底层的封装格式。所有握手、警告、应用数据,最终都要打成记录层的包发出去。

4.1 TLS 记录层格式

记录层的结构非常固定。它像是一个通用的信封,信封外面写着“这是什么类型的数据”、“用了哪个版本的TLS”、“数据有多长”。说白了,就是三层元数据加上一层负载。

每个TLS记录层包(Record)的格式如下:

字段 长度(字节) 说明
Content Type 1 记录类型(20=ChangeCipherSpec, 21=Alert, 22=Handshake, 23=Application Data)
Protocol Version 2 协议版本(如 0x0303 代表 TLS 1.2,0x0304 代表 TLS 1.3)
Length 2 后续负载的长度,最大值为 2^14 字节(16384)
Fragment(负载) 可变 实际内容,取决于 Content Type

注意这里有个细节:Protocol Version 字段在 TLS 1.3 之后是有争议的。我遇到过几次抓包发现版本字段写的是 0x0303,但实际上是对端在跑 TLS 1.3。为什么?因为 TLS 1.3 为了兼容性,在记录层还是写 TLS 1.2 版本号。真正的版本信息藏在了 Handshake 消息内部的扩展里。记得不要只看记录层的版本号就下结论,否则会踩坑。

小经验: 分析 TLS 记录层时,Length 字段非常关键。如果发现记录层长度大于 16384,很可能是分片或者重组出了问题。我曾经在分析一个自定义加密隧道时,就是因为没处理分片,导致解密失败。

4.2 Content Type:数据的分拣员

记录层的第一个字节就是 Content Type。它决定了服务器或客户端收到这个包后,该交给哪个模块处理。说白了,就是数据的分拣标签。

Content Type 的取值虽然只有几种,但意义完全不同。我们直接看表:

类型值(十进制) 类型名 用途 常见场景
20 ChangeCipherSpec(CCS) 通知对方切换加密参数 TLS 1.2 中每个握手完成时发送;TLS 1.3 中已移除该类型(但仍可能出现)
21 Alert 传递警告或错误 证书错误、解密失败、连接关闭等
22 Handshake 传输握手消息(ClientHello、ServerHello 等) 连接建立阶段的核心流量
23 Application Data 传输加密后的应用层数据 实际业务流量,比如 HTTP、DNS over TLS
24 Heartbeat TLS 心跳检测(RFC 6520) 心跳扩展启用后使用,较少见

这里要特别提一下 Alert 类型。很多人看到抓包里出现 Alert 就紧张,觉得出问题了。其实 Alert 分为两个等级:warning(等级 1)和 fatal(等级 2)。比如,连接正常关闭时,会发一个 close_notify 的 warning 级别的 Alert。只有 fatal 级别的 Alert 才会终止连接。

避坑指南: 我曾经遇到过一个奇怪的问题:客户端每隔十几秒就发一个 Application Data,服务器也回复一个。但我们的业务明明已经空闲了。最后抓包发现,是 TLS 的 Heartbeat 扩展在作祟。Heartbeat 类型虽然少见,但在某些心跳检测场景下会出现。如果你看到 Content Type 是 24,别慌,这不是攻击,可能是正常的保活机制。

4.3 Handshake / Alert / Application Data 结构

我们真正需要反复打交道的,是 Handshake 和 Application Data。先说 Handshake。

4.3.1 Handshake 结构

当 Content Type 为 22 时,负载部分就是 Handshake 消息。它本身又有一个子头部。每次拆这种嵌套结构,我都有种剥洋葱的感觉。

+------------+------------+------------+-----------------------+
| Handshake  |  Length    |  Message   |  ...                  |
| Type (1B)  |  (3B)      |  Body      |  (更多握手消息)       |
+------------+------------+------------+-----------------------+

关键字段解释:

  • Handshake Type:1 字节。比如 1 代表 ClientHello,2 代表 ServerHello,11 代表 Certificate,16 代表 EncryptedExtensions(TLS 1.3 中常用)。
  • Length:3 字节。这是个“大端”编码,表示后续 Message Body 的长度。注意是 3 字节,不是 2 字节。
  • Message Body:可变。根据 Handshake Type 的不同,解析方式也不同。

举个例子,如果你想提取 ClientHello 中的 SNI(服务器名称指示)字段,你需要先找到 Handshake Type=1 的消息,然后跳过固定的一些头部,再进入扩展字段寻找。别着急,我们后面会详细讲。

4.3.2 Alert 结构

当 Content Type 为 21 时,负载就是 Alert 消息。格式极其简单:

字段 长度(字节) 说明
Level 1 1=warning, 2=fatal
Description 1 错误码,如 40=handshake_failure, 42=bad_certificate

很多安全扫描工具就是通过监听 TLS Alert 来发现问题的。比如,你看到大量 fatal / handshake_failure,八成是证书链验证出问题了。

4.3.3 Application Data 结构

当 Content Type 为 23 时,负载是加密后的应用层数据。这也是我们分析学最难啃的部分。为什么呢?因为数据已经加密了,你看到的是一堆随机字节。但是!通过分析加密流量的长度、时间间隔、数据包大小分布,我们可以推断出一些上层信息。我把它叫做“流量指纹”。

举个例子,HTTP/2 的 TLS 流量有个明显特征:应用数据记录的长度不会超过 16384(MTU 限制),但有时候即使没有数据发送,也会发一些空记录或者“心跳”记录。这些模式是可以被机器学习模型捕捉到的。

小技巧: 分析 Application Data 时,不妨统计一下每个记录的 Length 字段分布。如果发现大量长度为 50~100 字节的记录,可能是语音通话(如 WebRTC over TLS);如果记录长度比较大且频繁,可能是网页加载。这些模式在我做的项目中非常有效。

4.4 TLS 扩展字段:隐藏在握手里的细节

TLS 为什么这么灵活?很大程度上是因为它的扩展机制。扩展字段出现在 ClientHello 和 ServerHello 的尾部,由一系列 Type-Length-Value(TLV)结构组成。你可以把它想象成协议里的“插件”系统,用于协商各种额外特性。

常见的扩展类型码如下(我挑几个最常用的):

扩展类型码(十进制) 扩展名称 作用 存在版本
0 server_name(SNI) 告知服务器要连接的域名 TLS 1.2, 1.3
5 status_request(OCSP Stapling) 允许服务器在握手时直接提供证书吊销状态 TLS 1.2, 1.3
13 signature_algorithms 客户端支持的签名算法列表 TLS 1.2+
16 application_layer_protocol_negotiation(ALPN) 协商应用层协议(如 h2、http/1.1) TLS 1.2, 1.3
43 supported_versions TLS 1.3 中使用,明确列出支持的版本 TLS 1.3
51 key_share TLS 1.3 中用于密钥交换 TLS 1.3

我个人认为,ALPN 扩展是分析 TLS 流量时最有价值的信息之一。为什么?因为它直接告诉你,加密隧道里面跑的是什么协议。是 HTTP/2(h2)?还是 HTTP/1.1?还是别的自定义协议?这个信息在解密前就能拿到。我在做企业级加密流量检测时,就经常根据 ALPN 来分类流量——比如 h2 流量可能跟 Web 浏览有关,而自定义 ALPN 可能代表私有应用。

再提一个细节:SNI 扩展。在多数 TLS 流量中,SNI 字段是明文传输的。这意味着,即使你不解密,也可以知道客户端要访问哪个域名。这对网络管理员做流量审计非常有用。但要注意,现在有些加密技术(如 ESNI,Encrypted SNI)已经让 SNI 不可见了。未来的趋势一定是越来越难分析。

TLS 记录层与上层协议结构图 TCP 传输层(下层承载) TLS 记录层(Record Layer) Content Type + Version + Length + Fragment Handshake (Type=22) ClientHello / ServerHello / Certificate Alert (Type=21) Level + Description Application Data (Type=23) 加密后的应用层数据 ⚠ Handshake 内部包含扩展字段(TLV 结构),如 SNI、ALPN、Key Share 等 扩展字段是分析 TLS 指纹和最上层应用协议的关键 💡 Application Data 的特征(长度、时间间隔、分布)可用于流量指纹分析 例如:语音通话多短包、视频流多长包、空闲连接多心跳包

最后再强调一点:扩展字段的排列顺序也是有意义的。在 TLS 1.3 中,一些扩展是强制性的,比如 supported_versions 和 key_share。如果你在做流量分类或异常检测,不妨把扩展列表当作一组“特征”。不同客户端(比如 Chrome 和 Firefox)的扩展数量和顺序都不一样。我曾在一次渗透测试中,就靠分析扩展列表识别出了对方的浏览器类型,进而推测出可能的漏洞攻击面。

好了,这一章的内容就到这里。TLS 记录层和扩展字段就像是一栋大楼的骨架和管线——外表看起来都一样,但内行能从细节看出门道。希望你们能在实际抓包中多观察记录层的这些字段,慢慢建立“流量直觉”。