在排查 HTTPS 连接问题时,能够解密 TLS 流量是极其重要的技能。Wireshark 支持通过 SSLKEYLOGFILE 方式解密 TLS 流量,本文详细介绍其工作原理和实操步骤。

工作原理

TLS 加密通信的安全性来自密钥交换过程。如果能够获取客户端和服务端协商出的密钥(Master Secret 或 Traffic Keys),就能解密捕获的 TLS 流量。

SSLKEYLOGFILE 是 NSS 密码库引入的一个特性,被 Chrome、Firefox、curl 等支持。客户端在建立 TLS 连接时,会将密钥材料写入指定文件,Wireshark 读取该文件即可解密流量。

⚠️ 注意:本文仅用于调试自己的 TLS 连接。请勿用于窃听他人通信。

前置要求

  • Wireshark(支持 TLS 1.2 和 TLS 1.3 解密)
  • 支持 SSLKEYLOGFILE 的客户端(如 Chrome、Firefox、curl、OpenSSL s_client)

环境准备

1. 创建 Keylog 文件

1
2
3
# 创建空文件用于存储密钥
touch ~/ssl-keylog.txt
chmod 600 ~/ssl-keylog.txt

2. 配置环境变量

在 Linux/macOS 上:

1
export SSLKEYLOGFILE=~/ssl-keylog.txt

在 Windows 上(PowerShell):

1
$env:SSLKEYLOGFILE = "$env:USERPROFILE\ssl-keylog.txt"

3. 启动 Chrome(不阻止不安全)

启动 Chrome 并禁用证书警告:

1
2
3
4
5
# macOS
open -a Google\ Chrome --args --ignore-certificate-errors --ssl-version-min=tls1.2

# Linux
google-chrome --ignore-certificate-errors --ssl-version-min=tls1.2

4. 使用 OpenSSL s_client 生成 Keylog

1
2
# 使用 OpenSSL s_client 并指定 keylogfile
openssl s_client -connect example.com:443 -keylogfile /tmp/ssl-keylog.txt </dev/null

执行后会建立连接并把密钥写入文件。可以验证:

1
head -5 /tmp/ssl-keylog.txt

输出示例:

1
2
CLIENT_RANDOM 4A5D...8F2C 3B2A...9C1D...
CLIENT_RANDOM 7F8E...1A3B 8C4D...2E5F...

格式说明:

  • CLIENT_RANDOM + 32字节随机数 + 会话密钥

Wireshark 配置

方法一:设置环境变量

  1. 打开 Wireshark → Edit → Preferences
  2. 展开 Protocols → TLS
  3. (Pre)-Master-Secret log filename: 设置为上述 keylog 文件路径
  4. 点击 OK 保存

方法二:直接导入

如果无法设置环境变量,可以在捕获后导入:

  1. Wireshark → Edit → Preferences
  2. Protocols → TLS → (Pre)-Master-Secret log filename
  3. 浏览选择 keylog 文件

TLS 1.3 与 TLS 1.2 的区别

TLS 1.2

使用 CLIENT_RANDOM 方式:

1
CLIENT_RANDOM <32字节随机数> <48字节Master Secret>

解密流程:

  1. Wireshark 捕获 Client Hello 中的随机数
  2. 从 keylog 找到对应的 CLIENT_RANDOM
  3. 使用 PRF 派生所有会话密钥
  4. 解密流量

TLS 1.3

TLS 1.3 更加安全,使用以下几种密钥导出方式:

标签 含义
CLIENT_HANDSHAKE_TRAFFIC_SECRET 客户端握手流量密钥
SERVER_HANDSHAKE_TRAFFIC_SECRET 服务端握手流量密钥
CLIENT_APPLICATION_TRAFFIC_SECRET 客户端应用数据密钥
SERVER_APPLICATION_TRAFFIC_SECRET 服务端应用流量密钥
EARLY_EXPORTER_SECRET 早期导出密钥(0-RTT)

Keylog 文件示例(TLS 1.3):

1
2
3
CLIENT_HANDSHAKE_TRAFFIC_SECRET 4A5D... 3B2A...9C1D...
SERVER_HANDSHAKE_TRAFFIC_SECRET 4A5D... 8C4D...2E5F...
CLIENT_APPLICATION_TRAFFIC_SECRET 4A5D... 1A2B...3C4D...

完整解密流程

1
2
3
4
5
6
# 使用 curl 访问 HTTPS 网站(需要支持 TLS keylog 的版本)
export SSLKEYLOGFILE=/tmp/curl-keylog.txt
curl -v https://example.com > /dev/null 2>&1

# 查看生成的 keylog
cat /tmp/curl-keylog.txt

然后在 Wireshark 中配置该文件路径即可解密。

常见问题

Q: 解密失败怎么办?

  1. 确认 keylog 文件在 Wireshark 启动前已存在
  2. 检查文件格式是否正确
  3. 确认捕获的流量与 keylog 来自同一会话
  4. TLS 1.3 需要完整的握手过程

Q: 为什么只能解密切片流量?

确保在 TLS 握手完成前没有启动抓包。握手期间生成的密钥用于加密后续所有流量。

Q: 可以解密 Perfect Forward Secrecy 连接的流量吗?

可以。PFS 的特点是每次会话使用不同的密钥,但 SSLKEYLOGFILE 记录了当次会话的密钥,仍然可以解密。

Q: Chrome 不写入 keylog 怎么办?

某些 Chrome 版本可能需要特定启动参数。尝试:

1
chrome --ssl-key-log-file=$SSLKEYLOGFILE

安全提醒

  • SSLKEYLOGFILE 包含敏感密钥材料,切勿上传到公开仓库
  • 生产环境不要设置此环境变量
  • 调试完成后删除 keylog 文件:rm ~/ssl-keylog.txt
  • 只用于授权的调试场景

总结

通过 SSLKEYLOGFILE 方式解密 TLS 流量是排查 HTTPS 问题的利器:

  1. 设置 SSLKEYLOGFILE 环境变量
  2. 使用支持的客户端建立 TLS 连接
  3. 在 Wireshark 中配置 keylog 文件路径
  4. 即可解密 TLS 1.2 和 TLS 1.3 流量

掌握此技能后,再复杂的 TLS 问题都能迎刃而解。


参考来源: