1. TLS握手基础:TLS协议概述、TLS 1.2与1.3对比、握手流程详解

1.1 什么是TLS?

TLS(传输层安全协议),说白了就是给网络通信加了一把锁。它工作在传输层之上,应用层之下。你每次访问HTTPS网站,背后都是TLS在干活。

我刚开始接触网络时,总觉得TLS就是个加密工具。后来踩过几次坑才明白——它远不止加密。TLS还负责身份认证、数据完整性校验,以及最重要的:密钥协商。

嗯,这里要注意一个概念:TLS和SSL的关系。SSL是TLS的前身,现在基本没人用SSL了。如果你还在配置SSLv3,赶紧停手。我见过一个老项目因为兼容SSLv3被安全审计挂了,那叫一个惨。

核心要点:TLS = 加密 + 认证 + 完整性校验。缺一不可。

1.2 TLS 1.2 vs TLS 1.3:到底差在哪?

很多同学问我:TLS 1.3到底比1.2强在哪?我直接说结论:快,而且更安全。

先看一个对比表格,一目了然:

对比维度 TLS 1.2 TLS 1.3
握手轮次 2-RTT(完整握手) 1-RTT(完整握手)
0-RTT 不支持 支持(需谨慎使用)
密码套件数量 30+(很多已不安全) 5个(全是强加密)
密钥交换算法 RSA、DH、ECDH等 仅支持(EC)DHE
前向安全性 可选(RSA不支持) 强制
会话恢复 Session ID / Ticket PSK + Ticket

你想想看,TLS 1.2有30多种密码套件,其中一半以上都有已知漏洞。我在一次渗透测试中,发现客户还在用TLS_RSA_WITH_AES_128_CBC_SHA——这个套件既不支持前向安全,又容易被BEAST攻击。当时我就建议他们直接升级到TLS 1.3。

我的建议:新项目直接上TLS 1.3。老项目如果必须兼容TLS 1.2,至少禁用掉RSA密钥交换和CBC模式。

1.3 握手流程详解

握手是TLS最核心的部分。说白了,就是客户端和服务器互相确认身份、商量加密方式、交换密钥的过程。

1.3.1 TLS 1.2 完整握手(2-RTT)

我画了一张流程图,帮你理清这4次消息交换:

TLS 1.2 完整握手流程(2-RTT) 客户端 服务器 ① ClientHello ② ServerHello + 证书 + ServerHelloDone ③ ClientKeyExchange + CCS + Finished ④ CCS + Finished 加密通信 加密通信 ⑤ 应用数据(加密) RTT1: ①→②(1个网络往返) | RTT2: ③→④(1个网络往返) | 总计: 2-RTT 💡 注意:TLS 1.2 完整握手需要2个RTT才能开始加密通信。 如果加上TCP三次握手(1-RTT),总共需要3-RTT才能发送应用数据。

流程拆开来看:

  1. ClientHello:客户端告诉服务器它支持的TLS版本、密码套件列表、以及一个随机数。
  2. ServerHello + 证书 + ServerHelloDone:服务器选好密码套件,发回证书和另一个随机数。
  3. ClientKeyExchange + CCS + Finished:客户端验证证书,生成预主密钥,用服务器公钥加密后发过去。然后通知切换加密,并发送Finished消息。
  4. CCS + Finished:服务器解密预主密钥,双方各自算出会话密钥。服务器也切换加密,发回Finished。

我曾经在一个跨国项目中,发现TLS 1.2握手耗时超过800ms。查了半天,问题出在证书链太长——服务器发了4级中间证书,每次都要验证。后来精简到2级,握手时间直接砍半。

1.3.2 TLS 1.3 握手(1-RTT)

TLS 1.3把握手压缩到了1个RTT。怎么做到的?说白了,就是把密钥交换提前了。

TLS 1.3 握手流程(1-RTT) 客户端 服务器 ① ClientHello + KeyShare ② ServerHello + KeyShare + CCS + Finished 加密通信 加密通信 ③ 应用数据(加密) RTT1: ①→②(1个网络往返) | 总计: 1-RTT 💡 关键优化:客户端在ClientHello中直接发送DH公钥(KeyShare), 服务器收到后立即计算共享密钥,后续消息直接加密发送。 相比TLS 1.2,节省了整整1个RTT。

核心变化就两点:

  • ClientHello里直接带KeyShare:客户端提前算好DH密钥对,把公钥发过去。服务器收到后立刻就能算出共享密钥。
  • 服务器回复直接加密:ServerHello、证书、Finished全部打包在一起,用协商好的密钥加密发送。

你想想看,少了1个RTT,对于高延迟链路(比如跨国、卫星网络)来说,体验提升是质的飞跃。我记得有一次帮一个东南亚客户优化支付接口,从TLS 1.2升级到1.3后,握手时间从600ms降到了200ms,用户投诉直接少了30%。

避坑指南:我曾经在升级TLS 1.3时,忽略了中间设备的兼容性。有些老旧的负载均衡器、WAF会拦截TLS 1.3的HelloRetryRequest消息,导致握手失败。升级前一定要先做兼容性测试。

1.4 0-RTT:更快,但有代价

TLS 1.3还支持0-RTT模式。说白了,就是如果你之前和服务器握过手,下次可以直接发加密数据,不用再握手。

但这里有个坑:0-RTT存在重放攻击风险。攻击者可以截获0-RTT数据包,重复发送给服务器。如果服务器处理了重复的请求(比如重复扣款),那就出大事了。

我的建议是:0-RTT只用于幂等操作,比如查询余额、获取静态资源。千万别用在支付、下单这类非幂等操作上。

1.5 握手过程中的常见丢包点

讲完握手流程,咱们聊聊丢包。我在生产环境排查过上百次TLS问题,总结出几个高频丢包点:

阶段 丢包表现 常见原因
ClientHello 客户端发完没收到回复 防火墙拦截、MTU问题
ServerHello 客户端收到但验证失败 证书链不完整、时间不同步
ClientKeyExchange 服务器解密失败 密钥协商参数不匹配
Finished 双方握手校验失败 密码套件不一致、中间人篡改

嗯,这里要特别提一下MTU问题。我曾经遇到一个案例:客户端在内网,MTU是1500;服务器在云上,中间经过了一个VPN隧道,MTU只有1400。ClientHello包超过1400字节,被分片后中间设备直接丢弃。最后我在客户端配置了MSS clamping才解决。

排查技巧:用tcpdump抓包,看是否有TCP重传。如果ClientHello重传了3次还没收到ServerHello,基本可以断定是中间链路丢包。这时候检查MTU、防火墙规则、以及中间设备的TLS拦截功能。

1.6 小结

这一章咱们把TLS握手的基础讲透了。从协议概述到1.2和1.3的对比,再到握手流程的每一步,最后聊了丢包定位的常见场景。