专栏首页Serverless+使用 BPF 进行 HTTPS 抓包 —— 以 Golang 和 cURL 为例
原创

使用 BPF 进行 HTTPS 抓包 —— 以 Golang 和 cURL 为例

背景

分析某些业务进程的 HTTPS 请求时,类似 tcpdump 和 Fiddler 等工具无法获得请求明文,不方便进行分析。本文探讨使用 BPF 解决 HTTPS 的可观测性问题。

实验环境

  • 内核版本 4.1 及以上的 Linux 机器
  • 未删除符号表的目标二进制

操作步骤

  • 阅读源码,找到要插入探针的函数
  • 编写代码,捕获 HTTPS 请求并打印

Golang 示例

目标程序

一个简单的示例,向第一个命令行参数指定的 URL 发起 HTTP GET 请求,目标进程代码如下:

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

func main() {
	resp, err := http.Get(os.Args[1])
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(data))
}

探针代码

稍稍阅读一下 Go 标准库的代码就知道,我们要插入的探针的代码位点在:

crypto/tls.(*Conn).writeRecordLocked(typ recordType, data []byte)

第二个参数就是我们所需要的,知道了这个我们就可以插入探针输出这个参数了

探针代码如下:

#include <uapi/linux/ptrace.h>

BPF_PERF_OUTPUT(trace);

inline int crack_https(struct pt_regs *ctx) {
    u8 buf[256] = {0};
    u64* addr = (u64*)ctx->sp;
    u64 val = 0;

    bpf_probe_read(&val, sizeof(val), addr + 2);
    if (val != 23) {
        return 0;
    }

    val = 0;
    bpf_probe_read(&val, sizeof(val), addr + 3);
    addr = (u64*)val;
    bpf_probe_read(buf, sizeof(buf), addr);

    trace.perf_submit(ctx, &buf, sizeof(buf));
    return 0;
}

实验结果

bpf-https-golang.png

cURL 示例

目标程序

以 curl 7.68.0 为例。通常情况下,各 Linux 发行版上实用程序的符号表可能被 strip 掉了,所以需要获取代码重新编译,此过程略去不表。

探针代码

稍稍阅读一下 cURL 的源代码就知道,我们要插入的探针的代码位点在:

CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
                              struct connectdata *conn,

                              /* add the number of sent bytes to this
                                 counter */
                              curl_off_t *bytes_written,

                              /* how much of the buffer contains body data */
                              size_t included_body_bytes,
                              int socketindex)

Curl_send_buffer 的定义如下:

struct Curl_send_buffer {
  char *buffer;
  size_t size_max;
  size_t size_used;
};

探针代码如下:

#include <uapi/linux/ptrace.h>

BPF_PERF_OUTPUT(trace);

inline int crack_https(struct pt_regs *ctx) {
    u8 buf[256] = {0};
    u64 val = 0;

    // Curl_send_buffer**
    u64* addr = (u64*)ctx->di;

    // Curl_send_buffer*
    bpf_probe_read(&val, sizeof(val), addr);
    addr = (u64*)val;

    // Curl_send_buffer
    bpf_probe_read(&val, sizeof(val), addr);
    addr = (u64*)val;

    // Curl_send_buffer.buffer
    bpf_probe_read(buf, sizeof(buf), addr);

    trace.perf_submit(ctx, &buf, sizeof(buf));
    return 0;
}

实验结果

bpf-https-curl.png

总结

本文通过两个简单的例子,演示了如何使用 BPF 解决 HTTPS 的可观测性问题。大多数使用 Golang 编写的应用程序都会使用标准库,故上文的 Golang 示例具有通用性,我们可以很方便地追踪分析所有 Golang 程序的 HTTPS 调用

原创声明,本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

登录 后参与评论
0 条评论

相关文章

  • 使用 BPF 进行 HTTPS 抓包 —— 以 Golang 和 cURL 为例

    分析某些业务进程的 HTTPS 请求时,类似 tcpdump 和 Fiddler 等工具无法获得请求明文,不方便进行分析。本文探讨使用 BPF 解决 HTTPS...

    啦啦啦
  • [译]eBPF 概念和基本原理

    大约一年前,有个朋友想要用 Rust 开发一个 EVM Assembler。在他的一再要求之下,我开始帮忙编写单元测试。那时候我还不大了解操作系统的相关知识,只...

    崔秀龙
  • 程序员开发效率神器汇总!

    本文作者:neonliu,腾讯 CSIG 开发工程师 neon 是鹅厂的一位资深后台开发工程师,多年工作下来他总结了很多效率神器,今天分享给大家。 一. 开发工...

    腾讯技术工程官方号
  • 程序员开发效率神器汇总!

    本文作者:neonliu,腾讯 CSIG 开发工程师 neon 是鹅厂的一位资深后台开发工程师,多年工作下来他总结了很多效率神器,今天分享给大家。 一. 开发...

    腾讯大讲堂
  • 使用 BPF 记录 TCP 重传和丢包记录

    在云函数的日常运营中,经常有用户提出要求协助排查网络问题。一般的手段就是使用 tcpdump 抓包,但是部署抓包往往是在问题发生之后,而且抓包后复现的时机也不确...

    ritchiechen
  • 使用 eBPF 和 XDP 高速处理数据包

    XDP 是一种特殊的 eBPF 程序,在数据包处理上因为在协议栈之前就可以处理数据,所以有非常高的性能。

    黑光技术
  • 用来组流的网络数据包嗅探器:Streamdump

    在平时需要对数据包进行分析和统计,亦或是进行抓包时,通常会使用 Wireshark 或者 tcpdump 等工具。这两个工具以及 tshark(wireshar...

    C4rpeDime
  • 云原生项目实践DevOps(GitOps)+K8S+BPF+SRE,从0到1使用Golang开发生产级麻将游戏服务器—第3篇

    这将是一个完整的,完全践行 DevOps/GitOps 与 Kubernetes 上云流程的 Golang 游戏服务器开发的系列教程。

    为少
  • linux 内核跟踪神器 BPF 及实战

    作为一个程序员,在日常工作中,我们往往对于程序的运行情况十分关注,而随着计算机系统变得越来越复杂,人们想要详细地了解软件和系统内核的行为也变得越来越困难,这导致...

    用户3147702
  • 高性能:BPF performance Tools 学习笔记-2工具的安装

    还需要启用某些内核配置选项。现在,在许多发行版中默认启用了这些选项,因此您通常不需要更改它们。它们是:

    二狗不要跑
  • 你的第一个TC BPF 程序

    https://github.com/nevermosby/linux-bpf-learning

    nevermosby
  • 实现一个基于XDP_eBPF的学习型网桥

    eBPF技术风靡当下,eBPF字节码正以星火燎原之势被HOOK在Linux内核中越来越多的位置,在这些HOOK点上,我们可以像编写普通应用程序一样编写内核的HO...

    Linux阅码场
  • eBPF技术简介

    “eBPF 是我见过的 Linux 中最神奇的技术,没有之一,已成为 Linux 内核中顶级子模块,从 tcpdump 中用作网络包过滤的经典 cbpf,到成为...

    CNCF
  • BPF过滤器

    (1)BPF本质上来说是一个设备驱动(devicedriver),能够被应用程序用来读取网络上通过这个网络适配器的包。但是BPF又是一个特殊的驱动,因为它并没有...

    随心助手
  • 性能工具之 Goreplay 安装及入门使用

    只需要在生产服务器上启动一个 gor 进程,它负责所有的工作包括监听、过滤和转发。它的设计遵循 Unix 设计哲学:一切都是由管道组成的,各种输入将数据复用为输...

    高楼Zee
  • 使用tcpdump和Wireshark看下TCP握手

    tcpdump 和 Wireshark 是最常用的网络抓包和分析工具,作为经常和网络打交道的划水选手,怎么能不了解下呢?补篇博文回顾下相关操作。这里以 exam...

    Cloud-Cloudys
  • 云原生项目实践DevOps(GitOps)+K8S+BPF+SRE,从0到1使用Golang开发生产级麻将游戏服务器—第2篇

    这将是一个完整的,完全践行 DevOps/GitOps 与 Kubernetes 上云流程的 Golang 游戏服务器开发的系列教程。

    为少
  • 观察HTTP/2流量是困难的,但eBPF可以帮助

    在当今充满微服务的世界中,获取服务之间发送的消息的可观察性对于理解和排除问题至关重要。

    CNCF

扫码关注腾讯云开发者

领取腾讯云代金券