3. TLS握手参数分类归纳总结
说真的,做了这么多年安全审计,我见过最让人头疼的不是握手失败,而是——日志里堆了一大堆参数,你完全不知道哪些该记、哪些可以忽略。TLS握手涉及的参数少说几十个,如果不做分类,审计日志就是一堆乱码。
我个人习惯是先把参数按“从哪来、到哪去、干什么用”梳理清楚。说白了,参数就三类:客户端告诉服务器的、服务器回复客户端的、以及双方协商后定下来的。但真要落审计日志,还得再细分。
这一章我们就来把TLS握手参数做一个系统的分类归纳。你拿去直接匹配你手里的日志字段,基本都能对号入座。
参数分类的总体思路
我一开始分类时也走过弯路——按协议栈分层分,按加密算法族分,都不太好用。后来在给一个大型银行做TLS审计规范时,我试了两种维度:握手阶段和审计用途。你想想看,审计日志既要知道参数出现在哪个阶段,也要知道这个参数是“身份标识类”还是“安全级别类”。
| 分类维度 | 优点 | 缺点 |
|---|---|---|
| 按握手阶段(ClientHello / ServerHello / 证书 / Finished) | 跟抓包顺序一致,排查问题快 | 相同用途的参数(如密钥长度)分散在各阶段 |
| 按审计用途(身份类 / 加密类 / 扩展类 / 状态类) | 审计策略容易映射,能直接回答“这条连接安全吗” | 参数顺序与握手顺序不同,新手容易懵 |
| 同时使用两个维度 | 兼顾定位和审计 | 表结构略复杂 |
嗯,这里要注意:我建议你在设计审计日志表时,至少保留一个“phase”字段,同时把参数按用途打上标签。下面我展开讲每个维度。
按握手阶段分类
一个完整的TLS 1.3握手(不算0-RTT)有四个主要阶段,每个阶段产出一组核心参数。我按RFC 8446的顺序列出来,你看看是不是跟你的抓包记录对得上。
| 握手阶段 | 核心参数(审计必记) | 典型用途 |
|---|---|---|
| ClientHello | 协议版本(supported_versions)、密码套件列表、扩展列表(SNI / ALPN / key_share / signature_algorithms) | 识别客户端能力,判断兼容性 |
| ServerHello | 协商版本、选定密码套件、选定扩展(key_share / pre_shared_key) | 记录服务端最终选择,验证是否降级 |
| EncryptedExtensions + 证书(可选) | 证书链(subject / issuer / notBefore / notAfter)、证书类型、签名算法 | 身份认证审计,吊销检查 |
| Finished + 后续 | 会话ID / 会话票据、keylog(如需)、加密后的应用数据首包 | 会话追踪,完整性验证 |
我记得之前排查过一个“TLS版本协商异常”的case,审计日志里只记了协商版本,没记ClientHello的supported_versions字段。结果服务端声称支持TLS 1.3,但实际上客户端只发了TLS 1.2的版本号——你根本没法判断是谁的问题。所以两个阶段的版本参数必须同时记录。
按审计用途分类
如果你要写审计策略(比如“所有TLS连接必须使用ECDHE密钥交换”),那按用途分类更方便。我把常用参数归为五类,配合一个速查表格。
| 分类 | 审计参数 | 审计关注点 |
|---|---|---|
| 身份标识类 | SNI(server_name)、证书Subject/Issuer、证书序列号、OCSP stapling状态 | 是否访问了预期域名?证书是否可信? |
| 加密强度类 | 协商的密码套件(CipherSuite)、密钥交换算法、对称加密算法 / 模式 / 密钥长度、MAC算法(TLS 1.2及以前) | 是否使用了弱加密套件?密钥长度是否合规? |
| 版本兼容类 | 客户端支持的版本列表、服务端协商版本、ALPN协议、协议降级标志 | 是否允许了旧版本?降级攻击检测 |
| 会话追踪类 | 会话ID、会话票据(Session Ticket)、PSK标识、连接时间戳、握手完成时间 | 会话重用分析,异常连接持续时间 |
| 扩展与行为类 | SNI、ALPN、key_share(公钥)、signature_algorithms(签名算法列表)、supported_groups、max_fragment_length、padding | 是否存在恶意扩展?扩展值是否正常? |
实战小技巧:审计日志的字段命名建议统一加前缀,比如 tls_handshake_phase、tls_cipher_suite_negotiated、tls_cert_subject。我之前接手过一个项目,日志字段名乱七八糟,有的叫“cipher”,有的叫“cipher_suite”,有的叫“encryption_algorithm”——写分析脚本时差点崩溃。
整体分类结构一览
下面这张图帮你把三个阶段和五大用途串起来,形成一个完整的参数分类体系。你可以把它贴在审计规范文档里当“速查地图”。
实际审计中的分类经验
光分类还不够,你得知道哪些分类最容易被忽略。我曾经在一个金融客户的生产环境里审计日志,发现他们记录了完整的CipherSuite和证书链,但偏偏没记supported_groups(椭圆曲线组)。结果有一次客户端发了一个secp256r1,服务端也选了secp256r1,但日志里只显示“CipherSuite=TLS_AES_128_GCM_SHA256”。后来出安全事件,需要排查是否存在弱曲线降级攻击——日志里没有曲线信息,根本没法还原握手过程。
注意:TLS 1.3中,客户端在ClientHello的key_share扩展里会携带一组公钥,对应的曲线组必须单独记录。TLS 1.2则要通过ServerKeyExchange中的named_curve记录。这两个阶段的曲线数据在审计日志里不能合并成一个字段,否则会丢失哪一方发起的。
另外,扩展类参数容易被当成“非紧急”字段忽略。但SNI、ALPN、max_fragment_length这些扩展,在高级威胁分析中非常关键。我记得有一个APT攻击案例,攻击者利用非标准的SNI值绕过防火墙——审计日志里如果不记SNI,根本发现不了异常。
一句话总结:TLS握手参数分类不是理论游戏,它决定了你的审计日志能否回答这三个问题——
- 这条连接是谁发起的?(身份标识类 + SNI)
- 它用了多强的加密?(加密强度类 + 曲线组)
- 是否存在降级或异常行为?(版本兼容类 + 全部扩展)