Skip to content

Commit

Permalink
feat: Enrich addr info with remote addr info
Browse files Browse the repository at this point in the history
It is able to get full 5-tuple info when hooking `connect` and `accept`
syscalls with format `saddr:sport-daddr-dport` always.

```bash
$ sudo ./bin/ecapture tls -d
...
2024-12-08T16:44:24Z DBG AddConn success fd=5 pid=113767 tuple=192.168.241.133:37736-172.217.194.113:443
2024-12-10T05:08:04Z DBG AddConn success fd=4 pid=121587 tuple=192.168.241.1:54587-192.168.241.133:8080
...
```

Signed-off-by: Leon Hwang <hffilwlqm@gmail.com>
  • Loading branch information
Asphaltt committed Dec 10, 2024
1 parent 1183b8d commit 019048a
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 87 deletions.
1 change: 0 additions & 1 deletion kern/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@

#define AF_INET 2
#define AF_INET6 10
#define SA_DATA_LEN 14
#define BASH_ERRNO_DEFAULT 128

#define BASH_EVENT_TYPE_READLINE 0
Expand Down
155 changes: 145 additions & 10 deletions kern/openssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@ struct connect_event_t {
u32 pid;
u32 tid;
u32 fd;
char sa_data[SA_DATA_LEN];
u16 sport;
u16 dport;
__be32 saddr;
__be32 daddr;
char comm[TASK_COMM_LEN];
};
} __attribute__((packed)); // NOTE: do not leave padding hole in this struct.

struct active_ssl_buf {
/*
Expand All @@ -59,6 +62,11 @@ struct active_ssl_buf {
const char* buf;
};

struct tcp_fd_info {
u64 file;
int fd;
};

/***********************************************************
* BPF MAPS
***********************************************************/
Expand Down Expand Up @@ -114,6 +122,14 @@ struct {
} ssl_st_fd SEC(".maps");


struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u64);
__type(value, struct tcp_fd_info);
__uint(max_entries, 10240);
} tcp_fd_infos SEC(".maps");


/***********************************************************
* General helper functions
***********************************************************/
Expand Down Expand Up @@ -436,14 +452,67 @@ int probe_ret_SSL_read(struct pt_regs* ctx) {
return 0;
}


static __inline struct tcp_fd_info *find_fd_info(struct pt_regs *regs) {
u64 pid_tgid = bpf_get_current_pid_tgid();

return bpf_map_lookup_elem(&tcp_fd_infos, &pid_tgid);
}

static __inline struct tcp_fd_info *lookup_and_delete_fd_info(struct pt_regs *regs) {
struct tcp_fd_info *fd_info;
u64 pid_tgid;

pid_tgid = bpf_get_current_pid_tgid();
fd_info = bpf_map_lookup_elem(&tcp_fd_infos, &pid_tgid);
if (fd_info) {
bpf_map_delete_elem(&tcp_fd_infos, &pid_tgid);
}
return fd_info;
}

static __inline struct sock *tcp_sock_from_file(u64 ptr) {
struct socket *socket;
struct file *file;
struct sock *sk;

file = (struct file *)ptr;
bpf_probe_read_kernel(&socket, sizeof(socket), &file->private_data);
bpf_probe_read_kernel(&sk, sizeof(sk), &socket->sk);
return sk;
}

// libc : int __connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
// kernel : int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
SEC("kprobe/sys_connect")
int probe_connect(struct pt_regs* ctx) {
u64 pid_tgid = bpf_get_current_pid_tgid();
struct tcp_fd_info fd_info = {};

fd_info.fd = PT_REGS_PARM1(ctx);
bpf_map_update_elem(&tcp_fd_infos, &pid_tgid, &fd_info, BPF_ANY);
return 0;
}

SEC("kprobe/__sys_connect_file")
int probe_connect_file(struct pt_regs* ctx) {
struct tcp_fd_info *fd_info;

fd_info = find_fd_info(ctx);
if (fd_info) {
fd_info->file = (u64)(void *) PT_REGS_PARM1(ctx);
}
return 0;
}

static __inline int kretprobe_connect(struct pt_regs *ctx, int fd, struct sock *sk, const bool active) {
u64 current_pid_tgid = bpf_get_current_pid_tgid();
u32 pid = current_pid_tgid >> 32;
u64 current_uid_gid = bpf_get_current_uid_gid();
u32 uid = current_uid_gid;
u16 address_family = 0;
u64 addrs;
u32 ports;

#ifndef KERNEL_LESS_5_2
// if target_ppid is 0 then we target all pids
Expand All @@ -455,16 +524,15 @@ int probe_connect(struct pt_regs* ctx) {
}
#endif

u32 fd = (u32)PT_REGS_PARM1(ctx);
struct sockaddr* saddr = (struct sockaddr*)PT_REGS_PARM2(ctx);
if (!saddr) {
bpf_probe_read_kernel(&address_family, sizeof(address_family), &sk->__sk_common.skc_family);
if (address_family != AF_INET) {
return 0;
}
sa_family_t address_family = 0;
bpf_probe_read_user(&address_family, sizeof(address_family),
&saddr->sa_family);

if (address_family != AF_INET) {
// if the connection hasn't been established yet, the ports or addrs are 0.
bpf_probe_read_kernel(&addrs, sizeof(addrs), &sk->__sk_common.skc_addrpair);
bpf_probe_read_kernel(&ports, sizeof(ports), &sk->__sk_common.skc_portpair);
if (ports == 0 || addrs == 0) {
return 0;
}

Expand All @@ -476,14 +544,81 @@ int probe_connect(struct pt_regs* ctx) {
conn.pid = pid;
conn.tid = current_pid_tgid;
conn.fd = fd;
bpf_probe_read_user(&conn.sa_data, SA_DATA_LEN, &saddr->sa_data);
if (active) {
conn.dport = bpf_ntohs((u16)ports);
conn.sport = ports >> 16;
conn.daddr = (__be32)addrs;
conn.saddr = (__be32)(addrs >> 32);
} else {
conn.sport = bpf_ntohs((u16)ports);
conn.dport = ports >> 16;
conn.saddr = (__be32)addrs;
conn.daddr = (__be32)(addrs >> 32);
}
bpf_get_current_comm(&conn.comm, sizeof(conn.comm));

bpf_perf_event_output(ctx, &connect_events, BPF_F_CURRENT_CPU, &conn,
sizeof(struct connect_event_t));
return 0;
}

SEC("kretprobe/sys_connect")
int retprobe_connect(struct pt_regs* ctx) {
struct tcp_fd_info *fd_info;
struct sock *sk;

fd_info = lookup_and_delete_fd_info(ctx);
if (fd_info) {
sk = tcp_sock_from_file(fd_info->file);
if (sk) {
return kretprobe_connect(ctx, fd_info->fd, sk, true);
}
}
return 0;
}

#ifndef IS_ERR_VALUE
#define MAX_ERRNO 4095
#define IS_ERR_VALUE(x) ((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO)
#endif

SEC("kretprobe/do_accept")
int retprobe_do_accept(struct pt_regs* ctx) {
struct tcp_fd_info *fd_info;
struct file *file;

file = (struct file *)PT_REGS_RC(ctx);
if (IS_ERR_VALUE(file)) {
return 0;
}

fd_info = find_fd_info(ctx);
if (fd_info) {
fd_info->file = (u64)file;
}
return 0;
}

SEC("kretprobe/__sys_accept4")
int retprobe_accept4(struct pt_regs* ctx) {
struct tcp_fd_info *fd_info;
struct sock *sk;
int fd;

fd = PT_REGS_RC(ctx);
if (fd < 0) {
return 0;
}

fd_info = lookup_and_delete_fd_info(ctx);
if (fd_info) {
sk = tcp_sock_from_file(fd_info->file);
if (sk) {
return kretprobe_connect(ctx, fd, sk, false);
}
}
return 0;
}


// int SSL_set_fd(SSL *s, int fd)
Expand Down
3 changes: 1 addition & 2 deletions pkg/event_processor/base_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"bytes"
"encoding/binary"
"fmt"

"github.com/gojue/ecapture/user/event"
)

Expand All @@ -35,8 +36,6 @@ const ChunkSizeHalf = ChunkSize / 2

const MaxDataSize = 1024 * 4

//const SaDataLen = 14

const (
Ssl2Version = 0x0002
Ssl3Version = 0x0300
Expand Down
Loading

0 comments on commit 019048a

Please sign in to comment.