在 Go 中提取 TLS 机密

atr*_*ia6 7 ssl go wireshark

我不完全确定这是否真的是 Wireshark、Go 或 Syncthing 问题;我尝试了Wireshark 开发列表Go 开发列表,但没有得到回应,所以我想我会在这里尝试:

我正在开发Wireshark Syncthing 解析器。由于大多数 Syncthing 协议都封装在 TLS 中,因此我需要向 Wireshark 提供 TLS 机密。

我阅读了Wireshark TLS 文档;Syncthing 是用 Go 编写的,因此我对其进行了修补以导出 TLS 密钥,如下所示(这只是 Syncthing 上游代码,添加了最后两行):

// The TLS configuration is used for both the listening socket and outgoing
// connections.

var tlsCfg *tls.Config
if a.cfg.Options().InsecureAllowOldTLSVersions {
    l.Infoln("TLS 1.2 is allowed on sync connections. This is less than optimally secure.")
    tlsCfg = tlsutil.SecureDefaultWithTLS12()
} else {
    tlsCfg = tlsutil.SecureDefaultTLS13()
}
tlsCfg.Certificates = []tls.Certificate{a.cert}
tlsCfg.NextProtos = []string{bepProtocolName}
tlsCfg.ClientAuth = tls.RequestClientCert
tlsCfg.SessionTicketsDisabled = true
tlsCfg.InsecureSkipVerify = true

// The following two lines open a file in the current directory and configure the application to dump its TLS secrets there
// See: https://pkg.go.dev/crypto/tls#example-Config-KeyLogWriter

w, err := os.OpenFile("tls-secrets.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
tlsCfg.KeyLogWriter = w
Run Code Online (Sandbox Code Playgroud)

这可行,并且各种内容都会写入指定文件,但将该文件提供给 Wireshark 不会启用 TLS 解密。我检查了该文件,发现它包含CLIENT_HANDSHAKE_TRAFFIC_SECRETSERVER_HANDSHAKE_TRAFFIC_SECRETCLIENT_TRAFFIC_SECRET_0SERVER_TRAFFIC_SECRET_0行,但不包含关键CLIENT_RANDOM行。我做错了什么或者错过了什么吗?

atr*_*ia6 1

在@zangw 的帮助下我想通了。有两个问题:

  • 虽然Wireshark中一些关于TLS解密的讨论提到CLIENT_RANDOM,但这仅适用于TLS 1.2;当前的 Syncthing 通常使用 TLS 1.3,其中涉及我看到的其他秘密(CLIENT_HANDSHAKE_TRAFFIC_SECRET、、、和) - 请参阅NSS Key Log FormatSERVER_HANDSHAKE_TRAFFIC_SECRET官方文档CLIENT_TRAFFIC_SECRET_0SERVER_TRAFFIC_SECRET_0
  • 我开始捕获的时间太晚了(因为我正在等待将机密写入文件以便能够将它们提供给 Wireshark),因此 Wireshark 错过了初始 TLS 握手,从而导致错误识别协议为 TLS 1.2 而不是 1.3,并且无法解密流量。正确的方法是在 TLS 协商开始之前开始捕获,然后在创建机密文件后向 Wireshark 提供该文件。(这可能需要保存并重新加载捕获。)

Wireshark 现在已成功解密 TLS 数据;可以通过选择“加密的应用程序数据”,然后单击窗口底部的“解密的 TLS”选项卡来查看它。