|
@@ -73,6 +73,25 @@ struct connection {
|
|
|
__u64 bytes_received;
|
|
__u64 bytes_received;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+// char* get_tcp_state_name(int state_number) {
|
|
|
|
|
+// switch (state_number) {
|
|
|
|
|
+// case 1: return "BPF_TCP_ESTABLISHED";
|
|
|
|
|
+// case 2: return "BPF_TCP_SYN_SENT";
|
|
|
|
|
+// case 3: return "BPF_TCP_SYN_RECV";
|
|
|
|
|
+// case 4: return "BPF_TCP_FIN_WAIT1";
|
|
|
|
|
+// case 5: return "BPF_TCP_FIN_WAIT2";
|
|
|
|
|
+// case 6: return "BPF_TCP_TIME_WAIT";
|
|
|
|
|
+// case 7: return "BPF_TCP_CLOSE";
|
|
|
|
|
+// case 8: return "BPF_TCP_CLOSE_WAIT";
|
|
|
|
|
+// case 9: return "BPF_TCP_LAST_ACK";
|
|
|
|
|
+// case 10: return "BPF_TCP_LISTEN";
|
|
|
|
|
+// case 11: return "BPF_TCP_CLOSING";
|
|
|
|
|
+// case 12: return "BPF_TCP_NEW_SYN_RECV";
|
|
|
|
|
+// case 13: return "BPF_TCP_MAX_STATES";
|
|
|
|
|
+// default: return "Unknown State";
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
struct {
|
|
struct {
|
|
|
__uint(type, BPF_MAP_TYPE_LRU_HASH);
|
|
__uint(type, BPF_MAP_TYPE_LRU_HASH);
|
|
|
__uint(key_size, sizeof(struct connection_id));
|
|
__uint(key_size, sizeof(struct connection_id));
|
|
@@ -93,6 +112,8 @@ int inet_sock_set_state(void *ctx)
|
|
|
}
|
|
}
|
|
|
__u64 id = bpf_get_current_pid_tgid();
|
|
__u64 id = bpf_get_current_pid_tgid();
|
|
|
__u32 pid = id >> 32;
|
|
__u32 pid = id >> 32;
|
|
|
|
|
+ cw_bpf_debug("socket inet_sock_set_state oldstate=%d --> newstate=%d\n", args.oldstate, args.newstate);
|
|
|
|
|
+ // cw_bpf_debug("socket inet_sock_set_state oldstate=%s --> newstate=%s\n", get_tcp_state_name(args.oldstate), get_tcp_state_name(args.newstate));
|
|
|
|
|
|
|
|
if (args.oldstate == BPF_TCP_CLOSE && args.newstate == BPF_TCP_SYN_SENT) {
|
|
if (args.oldstate == BPF_TCP_CLOSE && args.newstate == BPF_TCP_SYN_SENT) {
|
|
|
__u64 *fdp = bpf_map_lookup_elem(&fd_by_pid_tgid, &id);
|
|
__u64 *fdp = bpf_map_lookup_elem(&fd_by_pid_tgid, &id);
|
|
@@ -152,6 +173,40 @@ int inet_sock_set_state(void *ctx)
|
|
|
type = EVENT_TYPE_LISTEN_CLOSE;
|
|
type = EVENT_TYPE_LISTEN_CLOSE;
|
|
|
map = &tcp_listen_events;
|
|
map = &tcp_listen_events;
|
|
|
}
|
|
}
|
|
|
|
|
+ if (args.oldstate == BPF_TCP_SYN_RECV && args.newstate == BPF_TCP_ESTABLISHED) {
|
|
|
|
|
+ // __u64 *fdp = bpf_map_lookup_elem(&fd_by_pid_tgid, &id);
|
|
|
|
|
+ __u64 id2 = bpf_get_current_pid_tgid();
|
|
|
|
|
+ cw_bpf_debug("socket inet_sock_set_state entry tgid %d\n", id2);
|
|
|
|
|
+ // if (!fdp) {
|
|
|
|
|
+ // cw_bpf_debug("socket inet_sock_set_state no fd %d\n", id);
|
|
|
|
|
+ // return 0;
|
|
|
|
|
+ // }
|
|
|
|
|
+ // cw_bpf_debug("socket inet_sock_set_state Connection accepted: fd=%d\n", *fdp);
|
|
|
|
|
+ // bpf_map_delete_elem(&fd_by_pid_tgid, &id);
|
|
|
|
|
+ struct SOCK_TUPLE {
|
|
|
|
|
+ char laddr[16];
|
|
|
|
|
+ char raddr[16];
|
|
|
|
|
+ uint16_t sport;
|
|
|
|
|
+ uint16_t dport;
|
|
|
|
|
+ uint8_t proto;
|
|
|
|
|
+ };
|
|
|
|
|
+ // struct sock *sock = (struct sock *)BPF_CORE_READ(args, skaddr);
|
|
|
|
|
+ struct sock *sock = (struct sock *)args.skaddr;
|
|
|
|
|
+ __u64 hash;
|
|
|
|
|
+ bpf_probe_read(&hash, sizeof(hash), &sock->__sk_common.skc_hash);
|
|
|
|
|
+ struct SOCK_TUPLE stuple = {};
|
|
|
|
|
+ // bpf_probe_read_kernel(stuple->laddr, sizeof(args->saddr), BPF_CORE_READ(args, saddr));
|
|
|
|
|
+ // bpf_probe_read_kernel(stuple->raddr, sizeof(args->daddr), BPF_CORE_READ(args, daddr));
|
|
|
|
|
+ __builtin_memcpy(&stuple.laddr, &args.saddr, sizeof(stuple.laddr));
|
|
|
|
|
+ __builtin_memcpy(&stuple.raddr, &args.daddr, sizeof(stuple.raddr));
|
|
|
|
|
+ // stuple->lport = BPF_CORE_READ(args, sport);
|
|
|
|
|
+ // stuple->rport = BPF_CORE_READ(args, dport);
|
|
|
|
|
+ stuple.sport = args.sport;
|
|
|
|
|
+ stuple.dport = args.dport;
|
|
|
|
|
+ cw_bpf_debug("socket inet_sock_set_state Connection accepted: sk=%x, %lld\n", sock, hash);
|
|
|
|
|
+ cw_bpf_debug("socket inet_sock_set_state Connection accepted: dport=%d, lport=%d\n", stuple.sport, stuple.dport);
|
|
|
|
|
+ cw_bpf_debug("socket inet_sock_set_state Connection accepted: saddr=%s, daddr=%s\n", stuple.laddr, stuple.raddr);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
if (type == 0) {
|
|
if (type == 0) {
|
|
|
return 0;
|
|
return 0;
|
|
@@ -232,3 +287,171 @@ int sys_enter_close(void *ctx) {
|
|
|
}
|
|
}
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+void u32_to_ip(__u32 ip) {
|
|
|
|
|
+ // 将32位整数拆分为四个8位整数
|
|
|
|
|
+ unsigned char bytes[4];
|
|
|
|
|
+ bytes[0] = (ip >> 24) & 0xFF;
|
|
|
|
|
+ bytes[1] = (ip >> 16) & 0xFF;
|
|
|
|
|
+ bytes[2] = (ip >> 8) & 0xFF;
|
|
|
|
|
+ bytes[3] = ip & 0xFF;
|
|
|
|
|
+
|
|
|
|
|
+ // 使用sprintf将这些整数格式化为字符串
|
|
|
|
|
+ cw_bpf_debug("[Go] [socket/IP: %u.%u", bytes[0], bytes[1]);
|
|
|
|
|
+ cw_bpf_debug("[Go] [socket/IP: %u.%u", bytes[2], bytes[3]);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// 用于存储文件描述符和套接字指针的 map
|
|
|
|
|
+struct {
|
|
|
|
|
+ __uint(type, BPF_MAP_TYPE_HASH);
|
|
|
|
|
+ __type(key, __u64); // 使用进程 ID 作为键
|
|
|
|
|
+ __type(value, struct sock *);
|
|
|
|
|
+ __uint(max_entries, 1024);
|
|
|
|
|
+} socket_map SEC(".maps");
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+struct ipv4_tuple_t {
|
|
|
|
|
+ __u32 saddr;
|
|
|
|
|
+ __u32 daddr;
|
|
|
|
|
+ __u16 sport;
|
|
|
|
|
+ __u16 dport;
|
|
|
|
|
+ __u8 protocol;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+#define ___bpf_nth(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, _b, _c, N, ...) N
|
|
|
|
|
+#define ___bpf_concat(a, b) a ## b
|
|
|
|
|
+#define ___bpf_apply(fn, n) ___bpf_concat(fn, n)
|
|
|
|
|
+#define ___bpf_narg(...) \
|
|
|
|
|
+ ___bpf_nth(_, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
|
|
|
|
+#define ___bpf_kretprobe_args0() ctx
|
|
|
|
|
+#define ___bpf_kretprobe_args1(x) ___bpf_kretprobe_args0(), (void *)PT_REGS_RC(ctx)
|
|
|
|
|
+#define ___bpf_kretprobe_args(args...) ___bpf_apply(___bpf_kretprobe_args, ___bpf_narg(args))(args)
|
|
|
|
|
+
|
|
|
|
|
+#define BPF_KRETPROBE(name, args...) \
|
|
|
|
|
+name(struct pt_regs *ctx); \
|
|
|
|
|
+static __attribute__((always_inline)) typeof(name(0)) \
|
|
|
|
|
+____##name(struct pt_regs *ctx, ##args); \
|
|
|
|
|
+typeof(name(0)) name(struct pt_regs *ctx) \
|
|
|
|
|
+{ \
|
|
|
|
|
+ _Pragma("GCC diagnostic push") \
|
|
|
|
|
+ _Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \
|
|
|
|
|
+ return ____##name(___bpf_kretprobe_args(args)); \
|
|
|
|
|
+ _Pragma("GCC diagnostic pop") \
|
|
|
|
|
+} \
|
|
|
|
|
+static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
|
|
|
|
|
+
|
|
|
|
|
+#define bpf_core_read(dst, sz, src) \
|
|
|
|
|
+ bpf_probe_read(dst, sz, (const void *)__builtin_preserve_access_index(src))
|
|
|
|
|
+
|
|
|
|
|
+SEC("kprobe/inet_csk_accept")
|
|
|
|
|
+// int BPF_KRETPROBE(inet_csk_accept, struct sock *sk) {
|
|
|
|
|
+int kprobe__inet_csk_accept(struct pt_regs *ctx) {
|
|
|
|
|
+ cw_bpf_debug("socket inet_csk_accept Connection inet_csk_accept entry\n");
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 在 socket 接受时挂钩获取五元组信息
|
|
|
|
|
+SEC("kretprobe/inet_csk_accept")
|
|
|
|
|
+// int BPF_KRETPROBE(inet_csk_accept, struct sock *sk) {
|
|
|
|
|
+int kretprobe__inet_csk_accept(struct pt_regs *ctx) {
|
|
|
|
|
+ struct sock *sk = (struct sock *)PT_REGS_RC(ctx);
|
|
|
|
|
+ __u16 family = 0;
|
|
|
|
|
+ bpf_core_read(&family, sizeof(family), &sk->__sk_common.skc_family);
|
|
|
|
|
+ cw_bpf_debug("socket inet_csk_accept Connection family: family=%d\n", family);
|
|
|
|
|
+ if (family == AF_INET)
|
|
|
|
|
+ {
|
|
|
|
|
+ cw_bpf_debug("socket inet_csk_accept Connection family22: family=%d\n", family);
|
|
|
|
|
+ }
|
|
|
|
|
+ struct ipv4_tuple_t tuple = {};
|
|
|
|
|
+
|
|
|
|
|
+ // 从 __sk_common 获取信息
|
|
|
|
|
+ bpf_probe_read(&tuple.saddr, sizeof(tuple.saddr), &sk->__sk_common.skc_rcv_saddr);
|
|
|
|
|
+ bpf_probe_read(&tuple.daddr, sizeof(tuple.daddr), &sk->__sk_common.skc_daddr);
|
|
|
|
|
+ bpf_probe_read(&tuple.sport, sizeof(tuple.sport), &sk->__sk_common.skc_num);
|
|
|
|
|
+ bpf_probe_read(&tuple.dport, sizeof(tuple.dport), &sk->__sk_common.skc_dport);
|
|
|
|
|
+
|
|
|
|
|
+ tuple.sport = bpf_ntohs(tuple.sport);
|
|
|
|
|
+ tuple.dport = bpf_ntohs(tuple.dport);
|
|
|
|
|
+
|
|
|
|
|
+ __u64 hash;
|
|
|
|
|
+ bpf_probe_read(&hash, sizeof(hash), &sk->__sk_common.skc_hash);
|
|
|
|
|
+
|
|
|
|
|
+ cw_bpf_debug("socket inet_csk_accept Connection accepted: sk=%x, hash: %lld\n", sk, hash);
|
|
|
|
|
+ cw_bpf_debug("socket inet_csk_accept Connection accepted: dport=%d, lport=%d\n", tuple.dport, tuple.sport);
|
|
|
|
|
+ cw_bpf_debug("socket inet_csk_accept Connection accepted: saddr=%lld, daddr=%lld\n", tuple.saddr, tuple.daddr);
|
|
|
|
|
+ cw_bpf_debug("[Go] inet_csk_accept [socket/tracepoint__sys_exit_accept4]getget: rdi_ptr::pid -- \n");
|
|
|
|
|
+ u32_to_ip(tuple.saddr);
|
|
|
|
|
+ u32_to_ip(tuple.daddr);
|
|
|
|
|
+ __u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
|
|
+ cw_bpf_debug("[Go] inet_csk_accept [socket/kprobe__inet_csk_accept]getget: rdi_ptr::pid: %d\n", pid_tgid);
|
|
|
|
|
+ // 将进程 ID 关联到 `struct sock` 指针
|
|
|
|
|
+ // bpf_map_update_elem(&socket_map, &pid_tgid, &sk, BPF_ANY);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+struct sys_exit_accept4_ctx {
|
|
|
|
|
+ __u64 __unused_syscall_header;
|
|
|
|
|
+ __u32 __unused_syscall_nr;
|
|
|
|
|
+ __u64 ret;
|
|
|
|
|
+};
|
|
|
|
|
+struct sys_enter_accept4_ctx {
|
|
|
|
|
+ __u64 __unused_syscall_header;
|
|
|
|
|
+ __u32 __unused_syscall_nr;
|
|
|
|
|
+
|
|
|
|
|
+ __u64 fd;
|
|
|
|
|
+ __u64 *sockaddr;
|
|
|
|
|
+ __u64 addrlen;
|
|
|
|
|
+};
|
|
|
|
|
+// 在系统调用accept返回时挂钩获取文件描述符
|
|
|
|
|
+SEC("tracepoint/syscalls/sys_enter_accept4")
|
|
|
|
|
+int tracepoint__sys_enter_accept4(struct sys_enter_accept4_ctx *ctx) {
|
|
|
|
|
+ __u64 fd = ctx->fd;
|
|
|
|
|
+ __u64 *sockaddr = ctx->sockaddr;
|
|
|
|
|
+ __u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
|
|
+ cw_bpf_debug("[Go] [socket/tracepoint__sys_entry_accept4]getget: rdi_ptr::pid: %d,-- %d\n", pid_tgid, fd);
|
|
|
|
|
+ struct ipv4_tuple_t tuple = {};
|
|
|
|
|
+ // cw_bpf_debug("[Go] [socket/tracepoint__sys_entry_accept4]getget: rdi_ptr::pid: %d\n", *sockaddr);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 在系统调用accept返回时挂钩获取文件描述符
|
|
|
|
|
+SEC("tracepoint/syscalls/sys_exit_accept4")
|
|
|
|
|
+int tracepoint__sys_exit_accept4(struct sys_exit_accept4_ctx *ctx) {
|
|
|
|
|
+ __u64 fd = ctx->ret;
|
|
|
|
|
+ __u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
|
|
+ cw_bpf_debug("[Go] [socket/tracepoint__sys_exit_accept4]getget: rdi_ptr::pid: %d,-- %d\n", pid_tgid, fd);
|
|
|
|
|
+ // bpf_map_update_elem(&fd_by_pid_tgid, &pid_tgid, &fd, BPF_ANY);
|
|
|
|
|
+ // struct sock **skp;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // // 从 map 中获取 `struct sock` 指针
|
|
|
|
|
+ // skp = bpf_map_lookup_elem(&socket_map, &pid_tgid);
|
|
|
|
|
+ // if (skp && fd >= 0) {
|
|
|
|
|
+
|
|
|
|
|
+ // struct sock *sk = *skp;
|
|
|
|
|
+ // __u16 lport = 0, dport = 0;
|
|
|
|
|
+ // bpf_probe_read(&lport, sizeof(lport), &sk->__sk_common.skc_num);
|
|
|
|
|
+ // bpf_probe_read(&dport, sizeof(dport), &sk->__sk_common.skc_dport);
|
|
|
|
|
+ // __u32 saddr, daddr;
|
|
|
|
|
+ // bpf_probe_read(&saddr, sizeof(__u32), &sk->__sk_common.skc_rcv_saddr);
|
|
|
|
|
+ // bpf_probe_read(&daddr, sizeof(__u32), &sk->__sk_common.skc_daddr);
|
|
|
|
|
+ // // sport = lport;
|
|
|
|
|
+ // // dport = ntohs(dport);
|
|
|
|
|
+ // cw_bpf_debug("socket Connection accepted: fd=%d, dport=%d, lport=%d\n", fd, dport, lport);
|
|
|
|
|
+ // cw_bpf_debug("socket Connection accepted: saddr=%lld, daddr=%lld\n", saddr, daddr);
|
|
|
|
|
+ // cw_bpf_debug("[Go] [socket/tracepoint__sys_exit_accept4]getget: rdi_ptr::pid -- \n");
|
|
|
|
|
+ // u32_to_ip(saddr);
|
|
|
|
|
+ // u32_to_ip(daddr);
|
|
|
|
|
+ // // 在此可以访问 `sk` 结构,提取五元组信息进行处理
|
|
|
|
|
+
|
|
|
|
|
+ // // 打印文件描述符和相关信息给用户空间
|
|
|
|
|
+ // bpf_printk("fd: %d", fd);
|
|
|
|
|
+ // }
|
|
|
|
|
+
|
|
|
|
|
+ // // 从地图中移除项目,避免泄漏
|
|
|
|
|
+ // bpf_map_delete_elem(&socket_map, &pid_tgid);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|