You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让QUICHE生成Google QUIC密钥日志以解密Wireshark数据包

解决QUICHE库中Google QUIC版本(Q043/Q046/Q050)无法生成SSL密钥日志的问题

问题背景

使用bilibili维护的QUICHE仓库,通过toy_client.cc和toy_server.cc模拟QUIC连接,修改quiche/gquiche/quic/core/crypto/tls_server_connection.cc的KeylogCallback函数后,仅IETF QUIC版本(draft29、00000001)能生成密钥日志,Google QUIC早期版本(Q043/Q046/Q050)无日志输出,无法用Wireshark解密数据包,环境为Ubuntu 18.04且无法升级依赖。

原因分析

Google QUIC早期版本(Q043等)采用自定义加密握手栈,而非IETF QUIC基于标准TLS 1.3的实现。你修改的TlsServerConnection::KeylogCallback仅针对IETF QUIC的TLS逻辑触发,Google QUIC的密钥生成与日志逻辑完全封装在自身的加密流类中,不会调用该回调。

解决方案

针对Google QUIC的加密流实现添加密钥日志逻辑,步骤如下:

1. 修改服务端Google QUIC加密流代码

找到quiche/gquiche/quic/core/crypto/quic_crypto_server_stream.cc,这是Google QUIC服务端握手的核心实现文件,添加密钥日志写入逻辑:

第一步:添加密钥日志辅助函数

在文件头部引入依赖后,添加标准SSLKEYLOG格式的写入函数:

#include <fstream>
#include <string>

void WriteQuicKeyLog(const std::string& label, const std::string& client_random, const std::string& secret) {
    const char* filePath = "sslkeylogfile.log";
    std::ofstream keylogFile(filePath, std::ios::app);
    if (keylogFile.is_open()) {
        // 严格遵循SSLKEYLOG格式:<标签> <客户端随机数十六进制> <密钥十六进制>
        keylogFile << label << " " << client_random << " " << secret << std::endl;
        keylogFile.close();
    } else {
        std::cerr << "Failed to open keylog file: " << filePath << std::endl;
    }
}

第二步:在握手完成后写入密钥

找到QuicCryptoServerStream::OnHandshakeMessage方法,在握手完成的分支中添加密钥日志代码:

void QuicCryptoServerStream::OnHandshakeMessage(const CryptoHandshakeMessage& message) {
    // 保留原有逻辑...

    if (handshake_state_ == STATE_HANDSHAKE_COMPLETE) {
        const QuicCryptoNegotiatedParameters& params = crypto_negotiated_params();
        // 提取客户端随机数(十六进制格式)
        std::string client_random = params.client_random.ToHexString();
        // 提取主密钥(不同Google QUIC版本可能字段名略有差异,如forward_secure_master_secret)
        std::string master_secret = params.master_secret.ToHexString();
        
        // 写入CLIENT_RANDOM标签的密钥(Wireshark解密必需)
        WriteQuicKeyLog("CLIENT_RANDOM", client_random, master_secret);
        // 可选:写入EXPORTER_SECRET用于扩展解密场景
        std::string exporter_secret = params.exporter_secret.ToHexString();
        WriteQuicKeyLog("EXPORTER_SECRET", client_random, exporter_secret);
    }

    // 保留原有逻辑...
}

2. 客户端端补充(可选)

若需要客户端侧的密钥日志,同理修改quiche/gquiche/quic/core/crypto/quic_crypto_client_stream.cc,在握手完成后调用相同的WriteQuicKeyLog函数,确保双向密钥都被记录。

3. 重新编译QUICHE

执行编译命令重新构建工具:

bazel build //quiche/quic/tools:simple_quic_server //quiche/quic/tools:simple_quic_client

4. 验证效果

启动服务端和指定Q043版本的客户端后,检查sslkeylogfile.log是否生成对应版本的密钥条目,在Wireshark中配置该日志文件即可解密Google QUIC数据包。

注意事项

  • 不同Google QUIC版本的密钥字段可能有差异,若master_secret不存在,可尝试forward_secure_master_secret等字段;
  • 必须严格遵循SSLKEYLOG格式,否则Wireshark无法识别密钥;
  • 日志文件路径可根据需求调整,建议使用绝对路径避免权限问题。

内容的提问来源于stack exchange,提问作者Soumyajit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:02:41