SSL/TLS 的握手过程,是我这两年被问得最多的高频八股之一,几乎每次技术面试都会被拿出来当“试金石”。面试官爱问这个问题不奇怪,这一过程能把证书验证、非对称加密、对称加密、哈希校验、随机数生成这些知识点全部串起来,答得好说明基础扎实。但最近群里有朋友发来一张告警截图,内容是 Windows 3389 端口上监测到 SSL/TLS 协议信息泄露漏洞(CVE-2016-2183),问怎么排查和修复。这一下把我拉回现实:很多人“会背握手过程”,但真的遇到密码套件协商这种落地问题时,还是会懵。这篇文章我打算换个讲法,不光是背八股,而是把握手过程拆到抓包数据包层面,再结合 CVE-2016-2183 这个真实漏洞案例,讲清楚握手协商机制到底哪里有坑,以及排查手段。
1. 先搞懂:握手过程在整个 TLS 体系里是什么角色
1.1 从一次 HTTPS 访问说起
你在浏览器里输入https://example.com,按下回车,浏览器底部状态栏通常会先转几圈,然后出现一把锁。这几圈里,浏览器和服务器之间发生的事,就是 TLS 握手。TLS 的全称是 Transport Layer Security,前身是 SSL(Secure Sockets Layer),因为历史原因,大家习惯叫 SSL/TLS。它的作用概括起来就三件事:加密通信内容、验证对方身份、保证数据完整性。
但有个细节很多人没想过:如果直接用非对称加密(比如 RSA)加密所有业务数据,性能会非常差。非对称加密的计算开销比对称加密高几个数量级,一个 2048 位 RSA 私钥操作,可能要花 AES 密钥加密同样大小数据几百上千倍的时间。所以 TLS 的工程实现采用“混合加密”思路:用非对称加密安全地协商出一个临时会话密钥,后续业务数据全部用对称加密(比如 AES)来加解密。这个“协商临时密钥”的过程,就是握手过程本身。
1.2 握手在 TLS 协议栈里的位置
一个完整的 TLS 协议栈从下到上大致是:TCP 层、TLS 记录协议(Record Protocol)、TLS 握手协议(Handshake Protocol),再往上是 HTTP、FTP 等应用层数据。记录协议负责把数据分块、压缩(可选)、加加密 MAC、再通过 TCP 发送;握手协议则负责在正式传输数据之前,完成版本协商、密码套件协商、身份认证和密钥交换。
换句话说,记录协议是“运输工具”,握手协议是“安全交接流程”。抓包时你在 Wireshark 里看到的一堆 ClientHello、ServerHello、Certificate、Finished,就是握手协议跑出来的报文。理解这一点,后面抓包看记录层格式就会容易很多,否则看到一堆十六进制字段,基本是看了个寂寞。
1.3 为什么面试官总爱把握手过程当“必考题”
从面试角度看,握手过程能考察几个层次:第一层是“背流程”,说明你见过这个知识点;第二层是“讲原理”,说明你理解证书、密钥交换、随机数的作用;第三层是“结合实际”,比如问 CVE-2016-2183 是什么,或者问为什么有的服务器强制禁用 3DES,这要求你把握手中的“密码套件协商”环节和真实安全事件联系起来。
我自己面试别人的时候,通常会从“握手需要几个往返”问起,然后追问“你抓过包吗”。大部分候选人能答出 RSA 密钥交换和 1.2 的流程,但问到“ServerKeyExchange 什么场景会出现”“为什么 1.3 快那么多”就卡壳了。这说明八股背熟了,但协议栈没有真正“跑”过。所以这篇文章后面会用 Wireshark 实际抓一个 TLS 握手包,逐条对照解释,顺便把 CVE-2016-2183 这种漏洞的排查思路串进去,让大家从“会背”升级到“会聊”。
2. TLS 1.2 完整握手流程拆解(含密钥协商原理)
2.1 第一阶段:ClientHello 到底在“聊”什么
TLS 握手的第一步,是客户端向服务器发送一个 ClientHello 消息。这一步的目的不是传业务数据,而是“打招呼 + 报菜单”。
里面携带的关键字段包括:
- 客户端支持的 TLS 版本列表,比如 TLS 1.0、1.1、1.2、1.3;
- 客户端支持的密码套件列表(Cipher Suites),这是一份长长的“菜单”,可能包含几十个套件;
- 一个客户端生成的随机数 ClientHello.random,32 字节,后面生成主密钥要用;
- 可选的 Session ID 或 Session Ticket,用于会话恢复;
- SNI(Server Name Indication)扩展,用于在同一个 IP 上放多个证书的场景。
抓包时,你会在 Wireshark 里看到类似TLSv1.2 Record Layer: Handshake Protocol: Client Hello这样的结构。点开后能看到一个很长的 Cipher Suites 列表,像TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256这种。这里有个关键点:客户端把菜单端上来,但最终点哪个菜,由服务器决定。这就是密码套件协商的开始,也是 CVE-2016-2183 这类漏洞出现的第一个入口,因为如果“菜单”里有弱套件,而服务器允许选择它,后续安全强度就被拉低了。
2.2 第二阶段:ServerHello、证书和 ServerKeyExchange
服务器收到 ClientHello 后,会回一个 ServerHello,内容包括:
- 选定的 TLS 版本,比如 TLS 1.2;
- 从客户端菜单里挑中的密码套件;
- 服务器随机数 ServerHello.random;
- 如果是会话恢复,还会带上 Session ID。
紧接着,服务器一般会把证书发送给客户端,也就是 Certificate 消息。证书里面包含服务器公钥、证书签发机构(CA)的信息、有效期、签名等。客户端收到后会做一件很重要的事:验证证书链是不是可信的。如果证书是自己签的、过期了、或者域名不匹配,浏览器就会拦下连接并报错。这个过程在最开始面试的时候经常被忽略,但它恰恰是防止中间人攻击的关键一步。
在某些场景下,服务器还会发一条 ServerKeyExchange 消息。比如选用 DHE(Ephemeral Diffie-Hellman)或 ECDHE 密钥交换算法时,服务器需要临时生成一组 DH 参数发过去。如果是 RSA 密钥交换,这条消息一般可以省略,因为服务器的 RSA 公钥已经在证书里了。这就是一个很实在的八股点:看到 ServerKeyExchange 出现,你就要意识到密钥交换用的是 DHE/ECDHE,而不是 RSA。
最后服务器发送 ServerHelloDone,表示“我这边能说的都说完了,轮到你了”。
2.3 第三阶段:客户端密钥交换与 Finished 校验
客户端收到 ServerHelloDone 后,首先要验证服务器证书。验证内容包括证书链、签名、有效期、主机名,有的场景还会检查证书吊销状态(OCSP)。一项验证没过,握手直接终止。
验证通过后,客户端要生成“预主密钥”(pre-master secret)。如果使用 RSA 密钥交换,客户端生成一个 48 字节的随机数,其中前两个字节是协议版本号,剩下 46 字节随机数,然后用服务器公钥加密,通过 ClientKeyExchange 消息发给服务器。如果是 ECDHE 密钥交换,客户端会生成自己的临时 DH 私钥/公钥对,把公钥参数发过去。
到这里,双方手里都有了 client_random、server_random、pre-master secret,然后把这三者按约定方式做 PRF(伪随机函数)运算,生成最终的主密钥(master secret),再从主密钥派生出后续用于对称加密的密钥、MAC 密钥和 IV。这些细节你不用背公式,但记住一个核心:pre-master secret 只有客户端和服务器知道,任何第三方都拿不到。
随后客户端发送 ChangeCipherSpec,意思是“我开始切换到对称加密通信了”。紧接着发送 Finished 消息,里面是一段用会话密钥加密的握手消息摘要。服务器收到后用相同方式解密并校验,校验通过则说明之前所有消息都没有被篡改。服务器同样回一个 ChangeCipherSpec + Finished,客户端做同样的校验。到这里握手完成,进入应用数据传输阶段,也就是真正收发 HTTP 请求响应。
2.4 会话恢复:1-RTT 的秘密
完整握手需要两个往返(2-RTT),这在高延迟网络下体验不好。所以 TLS 设计了会话恢复机制。简单说,服务器用 Session ID 把会话状态缓存起来,客户端再次连接时,ClientHello 里带上之前的 Session ID,如果服务器还记得,直接跳过证书重传和密钥交换步骤,双方重新算一遍密钥,握手变成 1-RTT。
更现代的做法是 Session Ticket。服务器把会话状态加密成 ticket 发给客户端,客户端下次直接带上 ticket,服务器解密验证通过后即可恢复会话,不占用服务器内存。这个机制在你的抓包里非常常见,同一台机器第一次连是完整握手,马上再连第二次可能就是 Abbreviated Handshake,这就是 1-RTT 的体现。很多面试题会问“TLS 1.3 为什么能做到 1-RTT,甚至 0-RTT”,本质就是从这些扩展机制演化过来的。
3. 实战:抓包分析 SSL/TLS 握手过程
3.1 抓包前的环境准备
要真正把握手过程看出门道,建议自己动手抓一次。我常用的组合是 Wireshark + curl 或浏览器访问 HTTPS 站点。如果没有图形界面,用 tcpdump 抓 pcap 文件再放到 Wireshark 里分析也是一样。
一个最小化操作流程是:
- 打开 Wireshark,选择你的网卡(如果是本机访问本地服务,选 loopback 接口);
- 设置抓包过滤器为
tcp port 443,或者更精确的host example.com and tcp port 443; - 启动抓包后,用浏览器或者
curl -v https://example.com发起一次 HTTPS 请求; - 停止抓包,然后在显示过滤器里输入
tls或者ssl; - 找到第一条 ClientHello,右键选择 Follow -> TLS Stream,能看到整个握手报文序列。
这个抓包过程我建议所有人至少完整做一次。我面试过的不少候选人能把握手流程背得一字不差,但问他“ClientHello 的 record 层和 handshake 层分别在哪几层”就含糊了。实际抓包后你会发现,一个 ClientHello 报文会被记录层先包一层,记录层头部包含版本、类型、长度,然后再装握手层数据。这种层级关系,光靠读文档很难形成肌肉记忆。
提示:抓自己本机的包,尽量用 HTTPS 访问一个你完全信任的站点。不要尝试拦截别人网络中的流量,那涉及安全和法律风险。
3.2 一个标准 TLS 1.2 握手的报文序列
抓包完成后,你通常会在 Wireshark 里看到这样的顺序:
| 序号 | 源 -> 目的 | 协议 | 信息概要 |
|---|---|---|---|
| 1 | 客户端 -> 服务器 | TLSv1.2 | Client Hello |
| 2 | 服务器 -> 客户端 | TLSv1.2 | Server Hello |
| 3 | 服务器 -> 客户端 | TLSv1.2 | Certificate |
| 4 | 服务器 -> 客户端 | TLSv1.2 | Server Key Exchange |
| 5 | 服务器 -> 客户端 | TLSv1.2 | Server Hello Done |
| 6 | 客户端 -> 服务器 | TLSv1.2 | Client Key Exchange |
| 7 | 客户端 -> 服务器 | TLSv1.2 | Change Cipher Spec |
| 8 | 客户端 -> 服务器 | TLSv1.2 | Encrypted Handshake Message |
| 9 | 服务器 -> 客户端 | TLSv1.2 | Change Cipher Spec |
| 10 | 服务器 -> 客户端 | TLSv1.2 | Encrypted Handshake Message |
打开 Server Hello 那一条,展开 Handshake Protocol -> Cipher Suite 字段,你能看到服务器最终选中的密码套件。比如TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,这条套件包含几层含义:密钥交换用 ECDHE,证书认证用 RSA,对称加密用 AES-128-GCM,完整性校验用 SHA256。如果这里选中的是TLS_RSA_WITH_3DES_EDE_CBC_SHA,那就要引起警惕,这正好就是 CVE-2016-2183 影响的弱套件之一。
再展开 Certificate 消息,能看到服务端证书,双击证书字段,Wireshark 甚至可以把证书导出,然后你可以在系统里查看证书链。实操中我经常用这个方式快速确认服务器下发的证书是不是预期的那个,尤其是排查证书过期或者多证书配错的问题。有一次我帮朋友排查内网 HTTPS 服务异常,发现服务端下发的是自签名证书,而客户端要求验证 CA,最后定位到配置里挂错了证书文件,抓包只需要几十秒就锁定了。
3.3 密钥计算与 TLS 1.3 的变化
在 TLS 1.2 里,客户端发送 ClientKeyExchange 之后,双方各自用 client_random + server_random + pre-master secret 算出 master secret。这个计算过程用 PRF 完成,PRF 的输入在 1.2 里跟协议版本强相关,所以 TLS 1.0/1.1/1.2 的密钥派生方式不完全一样,这也是为什么协议版本协商很重要:如果双方最终协商出一个老版本,后续整个安全强度都会变差。Wireshark 的 “Decrypt TLS” 功能可以在你拿到服务器私钥的前提下解密会话数据,前提是你在抓包前配置好 RSA keys 或 (Pre)-Master-Secret 日志。Chrome 和 Firefox 可以通过设置SSLKEYLOGFILE环境变量导出密钥日志,这个技巧在分析混合加密细节时非常好用,但要注意不要把私钥和密钥日志文件公开出去。
TLS 1.3 的握手结构变化非常大。它把 ServerHello 之后的内容做了合并,很多消息被精简,整个握手只需要 1 个往返。密码套件列表也大幅缩短,移除了 RSA 密钥交换和 CBC 模式,不支持 3DES、RC4 这些弱算法。这就是为什么在很多安全基线里,推荐把最低 TLS 版本设置为 1.2 并开放 1.3,而不要后退到 1.0/1.1,那个版本区间的薄弱点特别多。
3.4 抓包排查中最常见的三种“握手失败”
抓包不只是为了看流程,更是为了排查问题。我归纳了工作中最常见的三种握手失败场景:
客户端报“证书不受信任”。看抓包,Certificate 消息已经发出,但 Application Data 阶段没有任何数据,客户端直接发了一个 Alert 消息,通常是Handshake Failure或者Certificate Unknown。对策是检查证书链、证书有效期、颁发者,以及客户端是否有对应根证书。
握手反复重传,迟迟没有 ServerHello。这种情况通常是服务器端防火墙或负载均衡把 TLS 流量拦截了,或者后端服务只监听了一个 IP 的某个端口。抓包看到大量 TCP 重传,ClientHello 发出去没有响应,就要往网络层排查。
版本协商失败,客户端和服务端支持的最高版本不一致。比如客户端只支持 TLS 1.3,服务器只支持 TLS 1.0,握手里会在 ServerHello 直接返回 AlertProtocol Version。这种问题在老旧系统和现代浏览器之间特别常见,也是很多合规扫描报告里出现“SSL/TLS 协议信息泄露漏洞”的触发场景之一。
4. CVE-2016-2183 和 Windows 3389 端口:握手协商里的真实漏洞
4.1 SWEET32 漏洞是什么一回事
CVE-2016-2183 是 2016 年公开的漏洞,属于 SWEET32 攻击技术的一部分,影响的算法核心是 3DES。你可能在安全扫描报告里经常看到类似“SSL/TLS 协议信息泄露漏洞(CVE-2016-2183)”、“Windows 3389 端口 SSL/TLS 协议信息泄露漏洞”这样的描述,它指向的就是 3DES 之类的 64 位分组密码套件。
为什么 64 位分组有风险?因为分组加密算法如果分组长度太短,在 CBC 模式下长时间传输大量数据后,会以一定概率出现碰撞。攻击者通过被动监听大量密文分组,等到两个密文分组相同,就可以利用碰撞推断出部分明文信息。3DES 的分组长度是 64 位,根据生日攻击原理,大约在 2^32 个分组(约 32GB 数据)之后就有较大概率出现碰撞。随着当今网络带宽不断提升,这个数据量不再是“天文数字”,所以 3DES 在 TLS 握手里被视为高风险算法。
做个简单对比:
| 算法 | 分组长度 | 碰撞需要的密文量 | 状态 |
|---|---|---|---|
| 3DES | 64 bit | 约 32GB | 不建议使用 |
| AES-128 | 128 bit | 约 2^64 分组以上 | 安全 |
| AES-256 | 128 bit | 同上 | 安全 |
在握手过程的语境里,这一步对应的是“密码套件协商”。客户端在 ClientHello 里送上支持的套件,如果在客户端和服务端的共同列表中包含 3DES,且没有更优的 AES 套件被选择,服务端就可能选中TLS_RSA_WITH_3DES_EDE_CBC_SHA这类套件。一旦这个套件被建立,攻击者开始监听大量数据,最终可能恢复出认证 Cookie、会话令牌等敏感信息。
4.2 为什么 Windows 3389 端口常出现这个告警
Windows 3389 端口是远程桌面服务(RDP)默认监听端口。RDP 在较新的 Windows 版本中使用 CredSSP 和 TLS 进行加密保护,部分场景下会把 NLA(网络级身份验证)和 TLS 组合使用。如果 Windows 系统启用 TLS 时,密码套件列表里仍然保留了 3DES 套件,那么扫描器就会在 3389 端口上探测到 SSL/TLS 协议信息泄露漏洞(CVE-2016-2183)。
很多企业内网的老旧 Windows Server 默认密码套件顺序可能包含 3DES,尤其当系统未打补丁或组策略没有显式禁用旧套件时,这个扫描告警很容易出现。实际等保和渗透测试报告中,3389 端口报 CVE-2016-2183 的比例很高,就是因为它默认开启了 TLS 但密码套件策略比较宽松。
从这里也能看出,理解握手过程不光是面试用,遇到安全通告时你真的能知道问题出在哪个环节。这个漏洞发生在握手第一个阶段的“密码套件协商”完成后,导致双方选择了强度不足的加密算法,而不是证书机制或随机数生成器的问题。
4.3 手工验证与抓包观察弱套件
在修复之前,最好先确认目标端口到底有没有暴露弱套件。我常用的方法是用 openssl 从外部做一次探测:
# 检查某个主机 3389 端口支持的 TLS 套件 openssl s_client -connect 192.168.1.10:3389 -tls1_2不过这条命令会进入一个交互式命令行,你可以在里面输入Q退出。如果想快速枚举支持的套件,更简单的是用sslscan或nmap --script ssl-enum-ciphers:
nmap -p 3389 --script ssl-enum-ciphers 192.168.1.10执行后你会看到目标端口支持的 TLS 版本列表和密码套件列表。如果看到类似TLS_RSA_WITH_3DES_EDE_CBC_SHA的套件标记为弱加密,那基本可以判定漏洞存在。抓包层面,你可以在本地起一个 RDP 会话,用 Wireshark 过滤tcp.port == 3389 and tls,在 ServerHello 的 Cipher Suite 字段里直接看到协商结果,这是最直观的证明。
注意:对没有授权的系统做端口扫描和套件探测,在任何环境下都可能违反安全规定。请先确认你有合法授权,或者在自己的测试机上实验。
4.4 修复与加固:从密码套件协商入手
修复 CVE-2016-2183 的思路非常清晰:让 3DES 不出现在协商菜单里,或者阻止服务器选择它。具体措施如下:
- 升级系统补丁。微软在相关安全更新中改进了密码套件默认策略,打过补丁后,部分场景下 3DES 默认从系统优先级列表移除。
- 禁用 3DES 密码套件。在 Windows Server 上,可以通过组策略或注册表调整 Schannel 的密码套件顺序。比较稳妥的做法是启用
AES 128/128和AES 256/256,把Triple DES 168取消勾选,并确保RC4相关项也禁用。 - 配置 RDP 安全层。将远程桌面设置为“使用网络级别身份验证”并启用 TLS 1.2,相当于在握手阶段主动抬高版本门槛。
- 在 TLS 网关或负载均衡层面过滤弱套件。如果 3389 端口前面有网关,或者这是一台 Web 服务器,可以直接在 Nginx、IIS 或云负载均衡配置里显式禁止 3DES。Nginx 的示例配置如下:
ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5:!3DES; ssl_prefer_server_ciphers on;!3DES就是把 3DES 套件从名单里干掉。即使客户端菜单里有 3DES,服务端也不会选中它。这个思路同样适用于其他服务,TLS 握手的最终决策权在服务端手里,所以服务端的套件白名单/黑名单策略非常重要。
在 Windows 上,一个常见的做法是通过 PowerShell 查询当前的 TLS 密码套件顺序:
Get-TlsCipherSuite | Format-Table Name然后可以用Enable-TlsCipherSuite和Disable-TlsCipherSuite精确控制。比如:
# 禁用 3DES 相关套件 Disable-TlsCipherSuite -Name "TLS_RSA_WITH_3DES_EDE_CBC_SHA"执行完重启相关服务,再用 nmap 或 sslscan 复查,如果弱套件不再出现,告警就能消掉。这个排查恢复闭环,本质上就是从握手协商的“Cipher Suite”字段入手,因为它记录了双方到底选了什么加密算法,安全扫描器的工作方式也和这个逻辑一致:主动发起握手,从 ServerHello 里提取服务端支持的套件,然后跟弱算法库比对。
5. 面试追问与实操经验补充
5.1 握手过程相关高频追问清单
除了“背流程”,面试官还会从握手过程延伸出一堆问题,提前准备能少踩不少坑。我列几个被问到的真实问题,还有最容易踩的答法:
问题 1:TLS 1.2 和 TLS 1.3 的握手差在哪?
1.3 把握手压缩到 1-RTT,客户端在 ClientHello 里直接携带密钥共享参数,服务端在 ServerHello 返回协商结果后,双方马上就能算密钥。同时 1.3 废除了 RSA 密钥交换、CBC 模式、SHA-1、RC4、3DES,只保留了前向保密算法,例如 ECDHE。回答的时候最好顺带提一句前向保密,能明显加分。
问题 2:Session Ticket 和 Session ID 恢复会话有什么区别?
Session ID 是服务端保存会话状态;Session Ticket 是服务端把状态加密后发给客户端,服务端不存状态。集群环境下 Ticket 更有优势,因为请求可以落在不同节点,但需要统一配置 Ticket 密钥,否则节点之间无法解密彼此的 Ticket。
问题 3:什么是前向保密?
即使服务器的长期私钥泄露,攻击者也无法解密历史上记录下来的加密流量。实现方式是使用 DHE/ECDHE 这类临时密钥交换算法,每次会话的密钥都是临时生成的,不和长期私钥绑定。这也是为什么现在安全基线普遍要求禁用静态 RSA 密钥交换。
问题 4:CVE-2016-2183 为什么会影响握手?
因为握手协商阶段选中的密码套件包含 3DES,这是一个 64 位分组算法,长时间大量加密数据后存在碰撞泄露风险。修复手段是禁用 3DES 套件,让服务器不会选中它。
问题 5:客户端发送的密码套件列表很长,服务端怎么选?
服务端不是挑第一个,而是按照自己的套件优先级列表,从上到下匹配客户端列表里的第一个交集项。所以服务端配置顺序极其重要,这也是为什么安全基线要求服务端把强套件放在前面。
5.2 从“会背”到“会讲”:我的实操建议
如果你想真正掌握握手过程,光看文章不够,建议动手做三件事:
第一,抓包看一次完整握手。虽然上面给了推荐流程,但我还是建议你把每个包点开,逐字段看一遍。不要只看协议层次,要点开 ServerHello 里的 Cipher Suite、Certificate 里的证书详情、Finished 的 Encrypted Handshake Message。这样你对“握手在数据包层面到底长什么样”会有具体认知。
第二,在本地起一个只支持 TLS 1.2 的测试服务,分别用 Chrome、curl、openssl 连接,然后观察不同客户端发送的 ClientHello 有哪些差异。你会发现有的客户端支持 TLS 1.3,有的只支持到 1.2,这对理解业务兼容性很有帮助。
第三,用 openssl 查看一个站点的证书链和套件:
openssl s_client -connect example.com:443 -servername example.com -showcerts-servername会带上 SNI 扩展,才能拿到对应域名的证书。遇到证书配置错误、套件顺序有问题的时候,这条命令是最快的诊断手段。
5.3 我在实际工作中踩过的几个坑
第一个坑是用 Wireshark 抓包时开了解密功能,结果忘记关闭,导致记录了很多敏感密钥日志。排查结束一定要清理SSLKEYLOGFILE,这个文件一旦泄露,别人能直接解密你的 TLS 流量。
第二个坑是只关注了服务端套件配置,忽略了客户端。比如把 Windows 3389 端口的 3DES 禁用了,但客户端旧机器如果只支持 3DES,连不上。所以修复前最好先确认客户端兼容范围,再决定是彻底禁用还是通过优先级降级。
第三个坑是修完不复查。安全扫描器报了个“CVE-2016-2183”,修复后一定要重新扫描,而且最好用抓包确认 ServerHello 里已经没有 3DES 套件。我遇到过申请了漏洞消除报告之后,服务还在用弱套件的情况,就是因为只改了 Nginx 配置但没重载,握手结果没有变化。
最后一个个人心得:每次排查 SSL/TLS 问题,我都会提醒自己先看握手的第一个环节,密码套件协商。无论是加密强度不够、协议版本过低,还是不兼容导致连接失败,绝大多数问题都藏在 ClientHello 和 ServerHello 这两条消息里。把抓包工具用熟,把协商过程看透,很多安全告警都不再是黑盒,而是一目了然的逻辑问题。