-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bump libbpf version and add http trace
- Loading branch information
Showing
35 changed files
with
153,941 additions
and
133,540 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
|
||
#include "vmlinux.h" | ||
#include <bpf/bpf_helpers.h> | ||
#include <bpf/bpf_endian.h> | ||
#include "http_trace.h" | ||
|
||
#define ETH_HLEN 14 | ||
#define ETH_P_IP 0x0800 /* Internet Protocol packet */ | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_RINGBUF); | ||
__uint(max_entries, 256 * 1024); | ||
} events SEC(".maps"); | ||
|
||
SEC("socket") | ||
int http_trace(struct __sk_buff *skb) | ||
{ | ||
struct event_t *event; | ||
__u8 ip_proto; | ||
__u16 h_proto; | ||
|
||
// 只跟踪 IP 协议的数据包 | ||
bpf_skb_load_bytes(skb, offsetof(struct ethhdr, h_proto), &h_proto, 2); | ||
if (h_proto != bpf_htons(ETH_P_IP)) { | ||
return 0; | ||
} | ||
|
||
// 只跟踪 TCP 协议的数据包 | ||
bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, protocol), | ||
&ip_proto, 1); | ||
if (ip_proto != IPPROTO_TCP) { | ||
return 0; | ||
} | ||
|
||
// 计算IP头部长度(ihl单位为4字节,所以需要乘以4) | ||
struct iphdr iph; | ||
bpf_skb_load_bytes(skb, ETH_HLEN, &iph, sizeof(iph)); | ||
__u32 ip_total_length = iph.tot_len; | ||
__u32 iph_len = iph.ihl; | ||
iph_len = iph_len << 2; | ||
|
||
// 根据TCP数据偏移(doff)计算TCP头部长度(doff单位为4字节,所以需要乘以4) | ||
struct tcphdr tcph; | ||
bpf_skb_load_bytes(skb, ETH_HLEN + sizeof(iph), &tcph, sizeof(tcph)); | ||
__u32 tcp_hlen = tcph.doff; | ||
tcp_hlen = tcp_hlen << 2; | ||
|
||
// 只跟踪 TCP 80 端口的数据包 | ||
if (tcph.source != bpf_htons(80) && tcph.dest != bpf_htons(80)) { | ||
return 0; | ||
} | ||
|
||
// 计算HTTP payload的偏移和长度 | ||
__u32 payload_offset = ETH_HLEN + iph_len + tcp_hlen; | ||
__u32 payload_length = bpf_ntohs(ip_total_length) - iph_len - tcp_hlen; | ||
// HTTP 报文最短为7个字节 | ||
if (payload_length < 7) { | ||
return 0; | ||
} | ||
|
||
// 只跟踪 GET、POST、PUT、DELETE 方法的数据包 | ||
// HTTP 开头的数据包是服务器端的响应 | ||
char start_buffer[7] = { }; | ||
bpf_skb_load_bytes(skb, payload_offset, start_buffer, 7); | ||
if (bpf_strncmp(start_buffer, 3, "GET") != 0 && | ||
bpf_strncmp(start_buffer, 4, "POST") != 0 && | ||
bpf_strncmp(start_buffer, 3, "PUT") != 0 && | ||
bpf_strncmp(start_buffer, 6, "DELETE") != 0 && | ||
bpf_strncmp(start_buffer, 4, "HTTP") != 0) { | ||
return 0; | ||
} | ||
|
||
// 读取HTTP信息并将其提交到环形缓冲区 | ||
event = bpf_ringbuf_reserve(&events, sizeof(*event), 0); | ||
if (!event) { | ||
return 0; | ||
} | ||
event->sport = bpf_ntohs(tcph.source); | ||
event->dport = bpf_ntohs(tcph.dest); | ||
event->payload_length = payload_length; | ||
__u32 read_length = | ||
payload_length > MAX_LENGTH ? MAX_LENGTH : payload_length; | ||
bpf_skb_load_bytes(skb, payload_offset, event->payload, read_length); | ||
bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, saddr), | ||
&event->saddr, 4); | ||
bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, daddr), | ||
&event->daddr, 4); | ||
bpf_ringbuf_submit(event, 0); | ||
|
||
return 0; | ||
} | ||
|
||
char _license[] SEC("license") = "GPL"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include <stdio.h> | ||
#include <unistd.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <errno.h> | ||
#include <arpa/inet.h> | ||
#include <linux/if_ether.h> | ||
#include <linux/if_packet.h> | ||
#include <net/if.h> | ||
#include <arpa/inet.h> | ||
#include <sys/resource.h> | ||
#include <bpf/libbpf.h> | ||
#include <sys/socket.h> | ||
#include <time.h> | ||
|
||
#include "http_trace.h" | ||
#include "http_trace.skel.h" | ||
|
||
// 用于打印调试信息 | ||
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, | ||
va_list args) | ||
{ | ||
#ifdef DEBUGBPF | ||
return vfprintf(stderr, format, args); | ||
#else | ||
return 0; | ||
#endif | ||
} | ||
|
||
// 创建原始套接字 | ||
static inline int open_raw_sock(const char *name) | ||
{ | ||
struct sockaddr_ll sll; | ||
int sock; | ||
|
||
sock = | ||
socket(PF_PACKET, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, | ||
htons(ETH_P_ALL)); | ||
if (sock < 0) { | ||
printf("cannot create raw socket\n"); | ||
return -1; | ||
} | ||
|
||
memset(&sll, 0, sizeof(sll)); | ||
sll.sll_family = AF_PACKET; | ||
sll.sll_ifindex = if_nametoindex(name); | ||
sll.sll_protocol = htons(ETH_P_ALL); | ||
if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) < 0) { | ||
printf("bind to %s: %s\n", name, strerror(errno)); | ||
close(sock); | ||
return -1; | ||
} | ||
|
||
return sock; | ||
} | ||
|
||
// 输出 HTTP 请求和响应信息(注意:长度截断至MAX_LENGTH) | ||
static int handle_event(void *ctx, void *data, size_t data_sz) | ||
{ | ||
const struct event_t *e = data; | ||
char saddr[16] = { }, daddr[16] = { }; | ||
|
||
inet_ntop(AF_INET, &e->saddr, saddr, sizeof(saddr)); | ||
inet_ntop(AF_INET, &e->daddr, daddr, sizeof(daddr)); | ||
printf("%s:%d -> %s:%d (length: %d)\n%s\n\n", saddr, e->sport, daddr, | ||
e->dport, e->payload_length, e->payload); | ||
return 0; | ||
} | ||
|
||
// 提升RLIMIT_MEMLOCK以允许BPF子系统执行任何需要的操作 | ||
static void bump_memlock_rlimit(void) | ||
{ | ||
struct rlimit rlim_new = { | ||
.rlim_cur = RLIM_INFINITY, | ||
.rlim_max = RLIM_INFINITY, | ||
}; | ||
|
||
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) { | ||
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n"); | ||
exit(1); | ||
} | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
struct http_trace_bpf *skel; | ||
struct ring_buffer *rb = NULL; | ||
int err = 0; | ||
|
||
// 设置libbpf的错误和调试信息回调 | ||
libbpf_set_print(libbpf_print_fn); | ||
|
||
// 提升RLIMIT_MEMLOCK以允许BPF子系统执行任何需要的操作 | ||
bump_memlock_rlimit(); | ||
|
||
// 加载BPF程序 | ||
skel = http_trace_bpf__open_and_load(); | ||
if (!skel) { | ||
fprintf(stderr, "Failed to open and load BPF skeleton\n"); | ||
return 1; | ||
} | ||
// 创建ring buffer并绑定事件处理回调 | ||
rb = ring_buffer__new(bpf_map__fd(skel->maps.events), handle_event, | ||
NULL, NULL); | ||
if (!rb) { | ||
fprintf(stderr, "Failed to create ring buffer\n"); | ||
goto cleanup; | ||
} | ||
// 将eBPF程序挂载到原始套接字 | ||
int sock = open_raw_sock("eth0"); | ||
if (sock < 0) { | ||
fprintf(stderr, "Failed to open raw socket\n"); | ||
goto cleanup; | ||
} | ||
int prog_fd = bpf_program__fd(skel->progs.http_trace); | ||
if (setsockopt | ||
(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd, sizeof(prog_fd))) { | ||
fprintf(stderr, "Failed to attach eBPF prog\n"); | ||
goto cleanup; | ||
} | ||
// 从ring buffer中读取数据 | ||
printf("Tracing HTTP traffic... Hit Ctrl-C to end.\n"); | ||
while ((err = ring_buffer__poll(rb, 100)) >= 0) ; | ||
printf("Error polling perf buffer: %d\n", err); | ||
|
||
cleanup: | ||
// 释放资源 | ||
ring_buffer__free(rb); | ||
http_trace_bpf__destroy(skel); | ||
return err != 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#ifndef __HTTP_TRACE_H | ||
#define __HTTP_TRACE_H | ||
|
||
#define MAX_LENGTH 100 | ||
|
||
struct event_t { | ||
__u32 saddr; | ||
__u32 daddr; | ||
__u16 sport; | ||
__u16 dport; | ||
__u32 payload_length; | ||
__u8 payload[MAX_LENGTH]; | ||
}; | ||
|
||
#endif /* __HTTP_TRACE_H */ |
Oops, something went wrong.