Skip to content

Commit

Permalink
Bump libbpf version and add http trace
Browse files Browse the repository at this point in the history
  • Loading branch information
feiskyer committed Jul 7, 2024
1 parent df4f0a7 commit 1256949
Show file tree
Hide file tree
Showing 35 changed files with 153,941 additions and 133,540 deletions.
13 changes: 12 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@
*.x86_64
*.hex

# Binaries
bpf-apps/bashreadline
bpf-apps/block_shell
bpf-apps/execsnoop
bpf-apps/execsnoop_v2
bpf-apps/hello
bpf-apps/hello_btf
bpf-apps/tc_block_tcp
bpf-apps/xdppass
bpf-apps/http_trace

# Debug files
*.dSYM/
*.su
Expand All @@ -60,4 +71,4 @@ dkms.conf
target

# Other
.DS_Store
.DS_Store
2 changes: 1 addition & 1 deletion bpf-apps/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
APPS = hello execsnoop execsnoop_v2 bashreadline hello_btf block_shell xdppass tc_block_tcp
APPS = hello execsnoop execsnoop_v2 bashreadline hello_btf block_shell xdppass tc_block_tcp http_trace
bpftool = $(shell which bpftool || ../tools/bpftool)
LIBBPF_SRC := $(abspath ../libbpf/src)
LIBBPF_OBJ := $(abspath libbpf/libbpf.a)
Expand Down
3 changes: 2 additions & 1 deletion bpf-apps/bashreadline.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(__u32));
__uint(value_size, sizeof(__u32));
} events SEC(".maps");
}
events SEC(".maps");

SEC("uretprobe/readline")
int BPF_KRETPROBE(printret, const void *ret)
Expand Down
3 changes: 2 additions & 1 deletion bpf-apps/bashreadline.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ int main(int argc, char **argv)
goto cleanup;
}

pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES, handle_event, handle_lost_events, NULL, NULL);
pb = perf_buffer__new(bpf_map__fd(obj->maps.events), PERF_BUFFER_PAGES,
handle_event, handle_lost_events, NULL, NULL);
if (!pb) {
err = -errno;
warn("failed to open perf buffer: %d\n", err);
Expand Down
634 changes: 332 additions & 302 deletions bpf-apps/bashreadline.skel.h

Large diffs are not rendered by default.

27,134 changes: 13,578 additions & 13,556 deletions bpf-apps/block_shell.skel.h

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions bpf-apps/execsnoop.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(u32));
__uint(value_size, sizeof(u32));
}
events SEC(".maps");
} events SEC(".maps");

// tracepoint for sys_enter_execve.
SEC("tracepoint/syscalls/sys_enter_execve")
Expand Down
4 changes: 2 additions & 2 deletions bpf-apps/execsnoop.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ int main(int argc, char **argv)
goto cleanup;
}


pb = perf_buffer__new(bpf_map__fd(skel->maps.events), 64, handle_event, handle_lost_events, NULL, NULL);
pb = perf_buffer__new(bpf_map__fd(skel->maps.events), 64, handle_event,
handle_lost_events, NULL, NULL);
err = libbpf_get_error(pb);
if (err) {
pb = NULL;
Expand Down
2,716 changes: 1,371 additions & 1,345 deletions bpf-apps/execsnoop.skel.h

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion bpf-apps/execsnoop_v2.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(u32));
__uint(value_size, sizeof(u32));
} events SEC(".maps");
}
events SEC(".maps");

static __always_inline bool valid_uid(uid_t uid)
{
Expand Down
3 changes: 2 additions & 1 deletion bpf-apps/execsnoop_v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ int main(int argc, char **argv)
goto cleanup;
}

pb = perf_buffer__new(bpf_map__fd(skel->maps.events), 64, handle_event, handle_lost_events, NULL, NULL);
pb = perf_buffer__new(bpf_map__fd(skel->maps.events), 64, handle_event,
handle_lost_events, NULL, NULL);
err = libbpf_get_error(pb);
if (err) {
pb = NULL;
Expand Down
32,411 changes: 16,238 additions & 16,173 deletions bpf-apps/execsnoop_v2.skel.h

Large diffs are not rendered by default.

334 changes: 178 additions & 156 deletions bpf-apps/hello.skel.h

Large diffs are not rendered by default.

541 changes: 283 additions & 258 deletions bpf-apps/hello_btf.skel.h

Large diffs are not rendered by default.

94 changes: 94 additions & 0 deletions bpf-apps/http_trace.bpf.c
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";
131 changes: 131 additions & 0 deletions bpf-apps/http_trace.c
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;
}
15 changes: 15 additions & 0 deletions bpf-apps/http_trace.h
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 */
Loading

0 comments on commit 1256949

Please sign in to comment.