分析某些业务进程的 HTTPS 请求时,类似 tcpdump 和 Fiddler 等工具无法获得请求明文,不方便进行分析。本文探讨使用 BPF
解决 HTTPS
的可观测性问题。
一个简单的示例,向第一个命令行参数指定的 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;
}
以 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 的可观测性问题。大多数使用 Golang 编写的应用程序都会使用标准库,故上文的 Golang 示例具有通用性,我们可以很方便地追踪分析所有 Golang 程序的 HTTPS
调用
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。