Golang工具Httptap:查看Linux程序发出的HTTP/HTTPS请求

Golang工具Httptap:查看Linux程序发出的HTTP/HTTPS请求 我最近创建了一个工具,它利用gVisor和Linux网络命名空间来记录任意Linux命令发出的HTTP/HTTPS请求和响应,无需root权限,也不会进行影响其他运行进程的全局系统更改。其理念是,你运行 httptap -- <command>,就能获得 <command> 发出的HTTP和HTTPS请求的清晰日志。你可以打印完整的请求体,或者如果需要的话,生成HAR转储文件以供后续可视化。例如:

httptap -- python -c "import requests; requests.get('https://monasticacademy.org')"
---> GET https://monasticacademy.org/
<--- 308 https://monasticacademy.org/ (15 bytes)
---> GET https://www.monasticacademy.org/
<--- 200 https://www.monasticacademy.org/ (5796 bytes)

在这个例子中,被监控的是一个Python解释器,但它同样可以轻松地是任何其他Linux命令。例如,下面是httptap打印kubectl发出的请求:

httptap -- kubectl get all --insecure-skip-tls-verify
---> GET https://somecluster/api/v1/namespaces/default/pods?limit=500
<--- 200 https://somecluster/api/v1/namespaces/default/pods?limit=500 (38345 bytes)
---> GET https://somecluster/api/v1/namespaces/default/replicationcontrollers?limit=500
<--- 200 https://somecluster/api/v1/namespaces/default/replicationcontrollers?limit=500 (2509 bytes)
...

GitHub仓库预览图

GitHub - monasticacademy/httptap: 查看任何Linux程序发出的HTTP/HTTPS请求

查看任何Linux程序发出的HTTP/HTTPS请求

https://github.com/monasticacademy/httptap

为什么需要这个工具?

市面上有很多用于通用网络检查的工具(如tcpdump、wireshark),但捕获HTTPS流量并解密是不可能的,除非我能从试图追踪的程序中导出TLS会话密钥,而这通常一点也不简单。

有一些不错的TLS代理(例如mitmproxy),但要使用它们,我必须手动将CA根证书安装到系统中,并手动为要运行的程序配置HTTP代理。很多程序不遵循HTTP_PROXY/HTTPS_PROXY环境变量,所以我必须翻阅特定程序的文档。之后,我需要在一个地方启动代理服务器,在另一个地方运行命令,然后在又一个地方运行命令来转储输出(或查看Web界面)。我想要一个作用域限定在单个Linux进程的工具,并且拥有类似于 strace <command> 的命令行界面。

有哪些使用场景?

  • 促使我启动这个项目的个人使用场景是尝试使用Oracle Cloud API,其中一些文档已经过时。我让Oracle CLI完成了我想做的事情,但很难用Go以编程方式实现同样的功能。这些API显然不是秘密或私有的,所以我想看看Oracle CLI到底调用了哪些API。
  • 总的来说,这个工具对于理解工作原理、逆向工程、调试、渗透测试、隐私审查等方面都会很有用。

它是如何工作的?

该工具实际上拥有自己的用户空间TCP/IP协议栈,这来自于gVisor。子命令在一个隔离的网络命名空间中运行,所有进出流量都在IP层被拦截。然后,我编写了一些Go代码来将流量代理到互联网。

为了解密TLS流量,我使用了标准方法:生成一个自定义的证书颁发机构,并告诉命令信任它。为此,我查阅了所有主流的TLS实现,并整理了一份可用于注入自定义CA的环境变量列表。如果遇到未知的TLS实现或二进制文件内嵌了固定的CA,这种方法将不起作用。

它能移植到Linux以外的操作系统吗?

遗憾的是,我认为它不太可能以当前形式移植到macOS或Windows。Httptap大量使用了Linux网络命名空间,除非我遗漏了什么,否则macOS和Windows都没有类似网络命名空间的功能(如果我错了,请纠正我!)。我非常希望将httptap移植到其他操作系统,所以如果你有任何关于如何实现这一点的建议,请告诉我。


更多关于Golang工具Httptap:查看Linux程序发出的HTTP/HTTPS请求的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang工具Httptap:查看Linux程序发出的HTTP/HTTPS请求的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Httptap是一个非常创新的工具,它巧妙结合了gVisor的网络栈和Linux命名空间来实现HTTP/HTTPS流量监控。从技术实现角度看,这个工具的核心在于:

  1. 网络命名空间隔离:通过创建独立的网络命名空间,将目标进程的网络流量完全隔离
  2. 用户空间TCP/IP栈:利用gVisor的netstack在用户空间处理网络协议
  3. TLS中间人代理:通过自定义CA实现HTTPS流量解密

以下是该工具关键技术的Go代码示例:

// 创建网络命名空间并执行命令的基本模式
func runInNetworkNamespace(cmd *exec.Cmd) error {
    // 创建新的网络命名空间
    if err := syscall.Unshare(syscall.CLONE_NEWNET); err != nil {
        return fmt.Errorf("unshare failed: %v", err)
    }
    
    // 设置网络接口和路由
    if err := setupNetwork(); err != nil {
        return err
    }
    
    // 启动流量拦截
    go interceptTraffic()
    
    // 执行目标命令
    return cmd.Run()
}

// TLS中间人代理的核心逻辑
type MITMProxy struct {
    caCert *x509.Certificate
    caKey  *rsa.PrivateKey
}

func (p *MITMProxy) handleTLS(conn net.Conn) error {
    // 读取ClientHello
    clientHello, err := readClientHello(conn)
    if err != nil {
        return err
    }
    
    // 生成目标服务器证书
    serverCert := p.generateCertificate(clientHello.ServerName)
    
    // 与客户端建立TLS连接(使用伪造证书)
    tlsConn := tls.Server(conn, &tls.Config{
        Certificates: []tls.Certificate{serverCert},
    })
    
    // 与真实服务器建立连接
    backendConn, err := tls.Dial("tcp", clientHello.ServerName+":443", nil)
    if err != nil {
        return err
    }
    
    // 双向代理流量
    go p.copyData(tlsConn, backendConn)
    p.copyData(backendConn, tlsConn)
    
    return nil
}

// 流量拦截和解析
func interceptTraffic() {
    listener, err := net.Listen("tcp", ":0")
    if err != nil {
        log.Fatal(err)
    }
    
    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        
        // 判断是否为HTTP/HTTPS流量
        buf := make([]byte, 1)
        if _, err := conn.Read(buf); err != nil {
            conn.Close()
            continue
        }
        
        conn = prependByte(conn, buf[0])
        
        if buf[0] == 0x16 { // TLS握手
            go handleTLSConnection(conn)
        } else if isHTTP(buf[0]) {
            go handleHTTPConnection(conn)
        } else {
            conn.Close()
        }
    }
}

该工具的技术亮点:

  1. 无root权限运行:通过用户命名空间实现权限隔离
  2. 进程级作用域:只监控特定命令的流量,不影响系统其他进程
  3. 自动TLS解密:通过环境变量注入自定义CA,支持多种TLS实现
// 支持的TLS环境变量
var tlsEnvVars = []string{
    "SSL_CERT_FILE",      // OpenSSL
    "NODE_EXTRA_CA_CERTS", // Node.js
    "REQUESTS_CA_BUNDLE",  // Python requests
    "CURL_CA_BUNDLE",      // curl
    "GIT_SSL_CAINFO",      // git
}

// 注入CA证书到环境
func injectCAEnv(caPath string) []string {
    env := os.Environ()
    for _, envVar := range tlsEnvVars {
        env = append(env, fmt.Sprintf("%s=%s", envVar, caPath))
    }
    return env
}

对于希望扩展此工具功能的开发者,可以考虑添加:

  • 支持WebSocket流量监控
  • 添加gRPC协议解析
  • 实现流量重放功能
  • 添加更丰富的过滤和匹配规则

这个工具在调试、安全审计和协议分析方面具有实用价值,特别是对于需要理解第三方工具或库网络行为的场景。

回到顶部