Skip to content

Commit

Permalink
feat: associate corresponding process information with each network p…
Browse files Browse the repository at this point in the history
…acket.
  • Loading branch information
cfc4n committed Jul 1, 2023
1 parent d812e67 commit d5a7681
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 93 deletions.
1 change: 1 addition & 0 deletions kern/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#endif

#define TASK_COMM_LEN 16
#define PATH_MAX_LEN 256
#define MAX_DATA_SIZE_OPENSSL 1024 * 4
#define MAX_DATA_SIZE_MYSQL 256
#define MAX_DATA_SIZE_POSTGRES 256
Expand Down
1 change: 1 addition & 0 deletions kern/ecapture.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include <uapi/linux/ptrace.h>
#include <linux/bpf.h>
#include <linux/socket.h>
#include <net/sock.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
Expand Down
175 changes: 93 additions & 82 deletions kern/tc.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,19 @@

#define TC_PACKET_MIN_SIZE 36
#define SOCKET_ALLOW 1
#define READ_KERN(ptr) \
({ \
typeof(ptr) _val; \
__builtin_memset((void *)&_val, 0, sizeof(_val)); \
bpf_core_read((void *)&_val, sizeof(_val), &ptr); \
_val; \
})

struct skb_data_event_t {
uint64_t ts;
u32 pid;
char comm[TASK_COMM_LEN];
// u8 cmdline[PATH_MAX_LEN];
u32 len;
u32 ifindex;
};
Expand All @@ -26,15 +35,16 @@ struct net_id_t {
u32 protocol;
u32 src_port;
u32 src_ip4;
// u32 dst_port;
// u32 dst_ip4;
u32 dst_port;
u32 dst_ip4;
// u32 src_ip6[4];
// u32 dst_ip6[4];
};

struct net_ctx_t {
u32 pid;
char comm[TASK_COMM_LEN];
// u8 cmdline[PATH_MAX_LEN];
};

////////////////////// ebpf maps //////////////////////
Expand All @@ -58,17 +68,20 @@ struct {
__uint(max_entries, 10240);
} network_map SEC(".maps");

/*
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, u16); // key即为TCP连接的 本地port
__type(value, u32); // pid
__uint(max_entries, 10240);
} pid_port SEC(".maps");
*/

////////////////////// General helper functions //////////////////////
static __inline struct skb_data_event_t *make_skb_data_event() {

static __always_inline void get_proc_cmdline(struct task_struct *task, char *cmdline, int size)
{
struct mm_struct *mm = READ_KERN(task->mm);
long unsigned int args_start = READ_KERN(mm->arg_start);
long unsigned int args_end = READ_KERN(mm->arg_end);
int len = (args_end - args_start);
if (len >= size)
len = size - 1;
bpf_probe_read(cmdline, len & (size - 1), (const void *)args_start);
}

static __always_inline struct skb_data_event_t *make_skb_data_event() {
u32 kZero = 0;
struct skb_data_event_t *event =
bpf_map_lookup_elem(&skb_data_buffer_heap, &kZero);
Expand Down Expand Up @@ -98,17 +111,20 @@ static __always_inline bool skb_revalidate_data(struct __sk_buff *skb,
}

///////////////////// ebpf functions //////////////////////
int capture_packets(struct __sk_buff *skb, bool is_ingress) {
static __always_inline int capture_packets(struct __sk_buff *skb, bool is_ingress) {
// packet data
unsigned char *data_start = (void *)(long)skb->data;
unsigned char *data_end = (void *)(long)skb->data_end;
if (data_start + sizeof(struct ethhdr) > data_end) {
return TC_ACT_OK;
}

u32 data_len = (u32)skb->len;
uint32_t l4_hdr_off;

// Ethernet headers
struct ethhdr *eth = (struct ethhdr *)data_start;
// IP headers
struct iphdr *iph = (struct iphdr *)(data_start + sizeof(struct ethhdr));


// Simple length check
if ((data_start + sizeof(struct ethhdr) + sizeof(struct iphdr)) >
Expand All @@ -126,14 +142,22 @@ int capture_packets(struct __sk_buff *skb, bool is_ingress) {
return TC_ACT_OK;
}

// IP headers
struct iphdr *iph = (struct iphdr *)(data_start + sizeof(struct ethhdr));
// filter out non-TCP packets
if (iph->protocol != IPPROTO_TCP) {
return TC_ACT_OK;
}
struct net_id_t conn_id = {0};
conn_id.protocol = iph->protocol;
conn_id.src_ip4 = iph->saddr;
conn_id.dst_ip4 = iph->daddr;

if (!skb_revalidate_data(skb, &data_start, &data_end,
l4_hdr_off + sizeof(struct tcphdr))) {
return TC_ACT_OK;
}
// debug_bpf_printk("!!!capture_packets src_ip4 : %d, dst_ip4 port :%d\n", conn_id.src_ip4, conn_id.dst_ip4);
struct tcphdr *tcp = (struct tcphdr *)(data_start + l4_hdr_off);

#ifndef KERNEL_LESS_5_2
Expand All @@ -142,28 +166,38 @@ int capture_packets(struct __sk_buff *skb, bool is_ingress) {
return TC_ACT_OK;
}
#endif
debug_bpf_printk("capture_packets port : %d, dest port :%d\n", bpf_ntohs(tcp->source), bpf_ntohs(tcp->dest));
/*
// get the skb data event
struct net_id_t conn_id = {0};
conn_id.protocol = iph->protocol;
conn_id.src_ip4 = iph->saddr;
conn_id.src_port = tcp->source;


conn_id.src_port = bpf_ntohs(tcp->source);
conn_id.dst_port = bpf_ntohs(tcp->dest);
// debug_bpf_printk("!!!capture_packets port : %d, dest port :%d\n", conn_id.src_port, conn_id.dst_port);

struct net_ctx_t *net_ctx = bpf_map_lookup_elem(&network_map, &conn_id);
if (net_ctx == NULL) {
// exchange src and dst
conn_id.src_ip4 = iph->daddr;
conn_id.src_port = tcp->dest;
u32 tmp_ip = conn_id.src_ip4;
conn_id.src_ip4 = conn_id.dst_ip4;
conn_id.dst_ip4 = tmp_ip;
u32 tmp_port = conn_id.src_port;
conn_id.src_port = conn_id.dst_port;
conn_id.dst_port = tmp_port;
net_ctx = bpf_map_lookup_elem(&network_map, &conn_id);
}
*/

// new packet event
struct skb_data_event_t event = {0};
// if (net_ctx != NULL) {
// event.pid = net_ctx->pid;
// bpf_probe_read(&event.comm, sizeof(event.comm), net_ctx->comm);
// struct skb_data_event_t *event = make_skb_data_event();
// if (event == NULL) {
// return TC_ACT_OK;
// }
if (net_ctx != NULL) {
event.pid = net_ctx->pid;
__builtin_memcpy(event.comm, net_ctx->comm, TASK_COMM_LEN);
// __builtin_memcpy(event.cmdline, net_ctx->cmdline, PATH_MAX_LEN);
debug_bpf_printk("capture packet process found, pid: %d, comm :%s\n", event.pid, event.comm);
} else {
debug_bpf_printk("capture packet process not found, src_port:%d, dst_port:%d\n", conn_id.src_port, conn_id.dst_port);
}
event.ts = bpf_ktime_get_ns();
event.len = skb->len;
event.ifindex = skb->ifindex;
Expand Down Expand Up @@ -198,70 +232,47 @@ int ingress_cls_func(struct __sk_buff *skb) {
return capture_packets(skb, true);
};

/*
struct bpf_sock_addr {
__u32 user_family;
__u32 user_ip4;
__u32 user_ip6[4];
__u32 user_port;
__u32 family;
__u32 type;
__u32 protocol;
__u32 msg_src_ip4;
__u32 msg_src_ip6[4];
*/
static __always_inline int get_process(struct bpf_sock_addr *ctx) {
SEC("kprobe/tcp_sendmsg")
int tcp_sendmsg(struct pt_regs *ctx){
u32 pid = bpf_get_current_pid_tgid() >> 32;
// 仅对指定PID的进程发起的connect事件进行捕获
#ifndef KERNEL_LESS_5_2
if (target_pid != 0 && target_pid != pid) {
return SOCKET_ALLOW;
}
if (target_pid != 0 && target_pid != pid) {
return 0;
}
#endif
if (ctx->protocol != IPPROTO_TCP) {
return SOCKET_ALLOW;
struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx);
if (sk == NULL) {
return 0;
}
u32 port = bpf_ntohs(ctx->user_port);
if (port == 0) {
return SOCKET_ALLOW;
}
if (ctx->family != AF_INET ) {
debug_bpf_printk("[eCapture] unsupported family %d\n", ctx->family);
return SOCKET_ALLOW;

u16 family, lport, dport;
u32 src_ip4, dst_ip4;
bpf_probe_read(&family, sizeof(family), &sk->__sk_common.skc_family);

if (family != AF_INET) {
return 0;
}
bpf_probe_read(&lport, sizeof(lport), &sk->__sk_common.skc_num);
bpf_probe_read(&dport, sizeof(dport), &sk->__sk_common.skc_dport);
bpf_probe_read(&src_ip4, sizeof(src_ip4), &sk->__sk_common.skc_rcv_saddr);
bpf_probe_read(&dst_ip4, sizeof(dst_ip4), &sk->__sk_common.skc_daddr);

// 从 ctx->sk中获取五元组
struct net_id_t conn_id = {0};
// conn_id.src_ip4 = bpf_ntohs(ctx->msg_src_ip4);
bpf_probe_read(&conn_id.src_ip4, sizeof(conn_id.src_ip4), &ctx->msg_src_ip4);
conn_id.protocol = ctx->sk->protocol;
conn_id.src_port = bpf_ntohs(ctx->sk->src_port);
conn_id.protocol = IPPROTO_TCP;
conn_id.src_port = lport;
conn_id.src_ip4 = src_ip4;
conn_id.dst_port = bpf_ntohs(dport);
conn_id.dst_ip4 = dst_ip4;

struct net_ctx_t net_ctx;
net_ctx.pid = pid;
bpf_get_current_comm(&net_ctx.comm, sizeof(net_ctx.comm));
debug_bpf_printk("[!!!!!] conn_id user_ip4:%d, msg_src_ip4:%d, protocol:%d\n", bpf_ntohl(ctx->user_ip4), bpf_ntohl(conn_id.src_ip4), conn_id.protocol);
debug_bpf_printk("[!!!!!] wrote network_map map: user_port %d ==> pid:%d, comm:%s\n", port, pid, net_ctx.comm);
//
// struct task_struct *task = (struct task_struct *)bpf_get_current_task();
// get_proc_cmdline(task, net_ctx.cmdline, sizeof(net_ctx.cmdline));
//
debug_bpf_printk("tcp_sendmsg pid : %d, comm :%s\n", net_ctx.pid, net_ctx.comm);
bpf_map_update_elem(&network_map, &conn_id, &net_ctx, BPF_ANY);
return SOCKET_ALLOW;
}


// tracee used kprobe/security_socket_bind.
SEC("cgroup/connect4")
int cg_connect4(struct bpf_sock_addr *ctx) {
if (ctx->user_family != AF_INET || ctx->family != AF_INET) {
return SOCKET_ALLOW;
}
return get_process(ctx);
}

/*
SEC("cgroup/connect6")
int cg_connect6(struct bpf_sock_addr *ctx) {
if (ctx->user_family != AF_INET || ctx->family != AF_INET) {
return SOCKET_ALLOW;
}
return get_process(ctx);
}
*/
return 0;
}
7 changes: 7 additions & 0 deletions user/event/event_openssl_tc.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ import (

const (
TaskCommLen = 16
CmdlineLen = 256
)

type TcSkbEvent struct {
eventType EventType
Ts uint64 `json:"ts"`
Pid uint32 `json:"pid"`
Comm [TaskCommLen]byte `json:"Comm"`
Cmdline [CmdlineLen]byte `json:"Cmdline"`
Len uint32 `json:"len"`
Ifindex uint32 `json:"ifindex"`
payload []byte
Expand All @@ -45,6 +47,11 @@ func (te *TcSkbEvent) Decode(payload []byte) (err error) {
if err = binary.Read(buf, binary.LittleEndian, &te.Comm); err != nil {
return
}
//if err = binary.Read(buf, binary.LittleEndian, &te.Cmdline); err != nil {
// return
//}
//TODO
te.Cmdline[0] = 91 //ascii 91
if err = binary.Read(buf, binary.LittleEndian, &te.Len); err != nil {
return
}
Expand Down
1 change: 0 additions & 1 deletion user/module/probe_openssl.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,6 @@ func (m *MOpenSSLProbe) Dispatcher(eventStruct event.IEventStruct) {
case *event.MasterSecretBSSLEvent:
m.saveMasterSecretBSSL(eventStruct.(*event.MasterSecretBSSLEvent))
case *event.TcSkbEvent:
m.logger.Printf("pid:%d, comm:%s\n", eventStruct.(*event.TcSkbEvent).Pid, eventStruct.(*event.TcSkbEvent).Comm)
err := m.dumpTcSkb(eventStruct.(*event.TcSkbEvent))
if err != nil {
m.logger.Printf("%s\t save packet error %s .\n", m.Name(), err.Error())
Expand Down
6 changes: 3 additions & 3 deletions user/module/probe_openssl_tc.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ func (m *MOpenSSLProbe) setupManagersTC() error {
},
//
{
EbpfFuncName: "cg_connect4",
Section: "cgroup/connect4",
CGroupPath: m.cgroupPath,
EbpfFuncName: "tcp_sendmsg",
Section: "kprobe/tcp_sendmsg",
AttachToFuncName: "tcp_sendmsg",
},
},

Expand Down
Loading

0 comments on commit d5a7681

Please sign in to comment.