wireshark 结合 go 对每个请求进行 https tls tcp 内容解密

发布时间 2023-05-28 22:30:02作者: burton_shi

众所周知,wireshark 是一款流行的抓包软件,我们可以很方便地查看每个 TCP 包的具体信息。对于 HTTP 协议的数据,还可以查看每个协议层具体信息内容。

但是对于 HTTPS 的数据,我们只能查看 IP 层以下的数据,TLS 及以上的数据都是被加密过的,如下图所示。

 

在某些特殊的场景下,我们想查看这个请求的具体内容就无从下手,即使使用 findler 等代理工具,也只能查看到最终的返回数据,没法查看 TCP 具体的传输内容。

以 HTTP 中 text/event-stream 为例,使用 apiPOST 我们可以直接得到响应内容,但是这个类型的具体是什么样的,我们无从得知。

 

这也是我最近工作遇到的一个问题,经过不断的尝试,发现 go 的 Transport 类型中有个 TLSConfigConfig 字段,可以打印在HTTPS 请求过程中生成的密钥,具体示例代理如下

func Test_Request2(m *testing.T) {
    // 创建一个文件, 用于保存tls key
    file, err := os.OpenFile(tlsKeyPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
    if err != nil {
        fmt.Printf("create tls key file failed, err: %s", err)
        return
    }
    defer file.Close()
    tlsConfig := &tls.Config{
        // 设置 key 保存的路径,关键之处
        KeyLogWriter: file,
    }

    client.Transport = &http.Transport{
        TLSClientConfig: tlsConfig,
    }

    req, err := http.NewRequest(method, url, reqData)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()

    fmt.Printf("Status: %s\n", resp.Status)
}
View Code

 

然后在 wireshark 中指定 pre-master key,具体操作如下,选中任一一条TCP数据,右击 -> Protocol Prefferences -> Transport Layer Security -> Pre Master Secret 来选择密钥的路径, 然后就可以看到解密后的数据