mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-06-23 14:58:44 +00:00
Improve Go TLS address availability (#1207)
Fetch source and destination addresses with bpf from tcp kprobes, similar to how it is done for openssl lib. Chunk contains both source address and destination address. FD is no longer used to obtain addresses.
This commit is contained in:
parent
5525214d0a
commit
692c500b0f
@ -16,34 +16,16 @@ static __always_inline int add_address_to_chunk(struct pt_regs *ctx, struct tls_
|
||||
__u32 pid = id >> 32;
|
||||
__u64 key = (__u64) pid << 32 | fd;
|
||||
|
||||
struct fd_info *fdinfo = bpf_map_lookup_elem(&file_descriptor_to_ipv4, &key);
|
||||
conn_flags *flags = bpf_map_lookup_elem(&connection_context, &key);
|
||||
|
||||
if (fdinfo == NULL) {
|
||||
// Happens when we don't catch the connect / accept (if the connection is created before tapping is started)
|
||||
if (flags == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int err;
|
||||
chunk->flags |= (*flags & FLAGS_IS_CLIENT_BIT);
|
||||
|
||||
switch (info->address_info.mode) {
|
||||
case ADDRESS_INFO_MODE_UNDEFINED:
|
||||
chunk->address_info.mode = ADDRESS_INFO_MODE_SINGLE;
|
||||
err = bpf_probe_read(&chunk->address_info.sport, sizeof(chunk->address_info.sport), &fdinfo->ipv4_addr[2]);
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_READING_FD_ADDRESS, id, err, 0l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = bpf_probe_read(&chunk->address_info.saddr, sizeof(chunk->address_info.saddr), &fdinfo->ipv4_addr[4]);
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_READING_FD_ADDRESS, id, err, 0l);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bpf_probe_read(&chunk->address_info, sizeof(chunk->address_info), &info->address_info);
|
||||
}
|
||||
|
||||
chunk->flags |= (fdinfo->flags & FLAGS_IS_CLIENT_BIT);
|
||||
bpf_probe_read(&chunk->address_info, sizeof(chunk->address_info), &info->address_info);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ Copyright (C) UP9 Inc.
|
||||
#define IPV4_ADDR_LEN (16)
|
||||
|
||||
struct accept_info {
|
||||
__u64* sockaddr;
|
||||
__u32* addrlen;
|
||||
};
|
||||
|
||||
@ -39,7 +38,6 @@ void sys_enter_accept4(struct sys_enter_accept4_ctx *ctx) {
|
||||
|
||||
struct accept_info info = {};
|
||||
|
||||
info.sockaddr = ctx->sockaddr;
|
||||
info.addrlen = ctx->addrlen;
|
||||
|
||||
long err = bpf_map_update_elem(&accept_syscall_context, &id, &info, BPF_ANY);
|
||||
@ -94,26 +92,21 @@ void sys_exit_accept4(struct sys_exit_accept4_ctx *ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct fd_info fdinfo = {
|
||||
.flags = 0
|
||||
};
|
||||
|
||||
bpf_probe_read(fdinfo.ipv4_addr, sizeof(fdinfo.ipv4_addr), info.sockaddr);
|
||||
conn_flags flags = 0;
|
||||
|
||||
__u32 pid = id >> 32;
|
||||
__u32 fd = (__u32) ctx->ret;
|
||||
|
||||
__u64 key = (__u64) pid << 32 | fd;
|
||||
err = bpf_map_update_elem(&file_descriptor_to_ipv4, &key, &fdinfo, BPF_ANY);
|
||||
err = bpf_map_update_elem(&connection_context, &key, &flags, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_PUTTING_FD_MAPPING, id, err, ORIGIN_SYS_EXIT_ACCEPT4_CODE);
|
||||
log_error(ctx, LOG_ERROR_PUTTING_CONNECTION_CONTEXT, id, err, ORIGIN_SYS_EXIT_ACCEPT4_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
struct connect_info {
|
||||
__u64 fd;
|
||||
__u64* sockaddr;
|
||||
__u32 addrlen;
|
||||
};
|
||||
|
||||
@ -138,7 +131,6 @@ void sys_enter_connect(struct sys_enter_connect_ctx *ctx) {
|
||||
|
||||
struct connect_info info = {};
|
||||
|
||||
info.sockaddr = ctx->sockaddr;
|
||||
info.addrlen = ctx->addrlen;
|
||||
info.fd = ctx->fd;
|
||||
|
||||
@ -193,19 +185,15 @@ void sys_exit_connect(struct sys_exit_connect_ctx *ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct fd_info fdinfo = {
|
||||
.flags = FLAGS_IS_CLIENT_BIT
|
||||
};
|
||||
|
||||
bpf_probe_read(fdinfo.ipv4_addr, sizeof(fdinfo.ipv4_addr), info.sockaddr);
|
||||
conn_flags flags = FLAGS_IS_CLIENT_BIT;
|
||||
|
||||
__u32 pid = id >> 32;
|
||||
__u32 fd = (__u32) info.fd;
|
||||
|
||||
__u64 key = (__u64) pid << 32 | fd;
|
||||
err = bpf_map_update_elem(&file_descriptor_to_ipv4, &key, &fdinfo, BPF_ANY);
|
||||
err = bpf_map_update_elem(&connection_context, &key, &flags, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_PUTTING_FD_MAPPING, id, err, ORIGIN_SYS_EXIT_CONNECT_CODE);
|
||||
log_error(ctx, LOG_ERROR_PUTTING_CONNECTION_CONTEXT, id, err, ORIGIN_SYS_EXIT_CONNECT_CODE);
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,9 @@ Copyright (C) UP9 Inc.
|
||||
#include "include/log.h"
|
||||
#include "include/logger_messages.h"
|
||||
#include "include/pids.h"
|
||||
#include "include/common.h"
|
||||
|
||||
struct sys_enter_read_ctx {
|
||||
struct sys_enter_read_write_ctx {
|
||||
__u64 __unused_syscall_header;
|
||||
__u32 __unused_syscall_nr;
|
||||
|
||||
@ -20,8 +21,46 @@ struct sys_enter_read_ctx {
|
||||
__u64 count;
|
||||
};
|
||||
|
||||
struct sys_exit_read_write_ctx {
|
||||
__u64 __unused_syscall_header;
|
||||
__u32 __unused_syscall_nr;
|
||||
|
||||
__u64 ret;
|
||||
};
|
||||
|
||||
|
||||
static __always_inline void fd_tracepoints_handle_openssl(struct sys_enter_read_write_ctx *ctx, __u64 id, struct ssl_info *infoPtr, struct bpf_map_def *map_fd, __u64 origin_code) {
|
||||
struct ssl_info info;
|
||||
long err = bpf_probe_read(&info, sizeof(struct ssl_info), infoPtr);
|
||||
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_READING_SSL_CONTEXT, id, err, origin_code);
|
||||
return;
|
||||
}
|
||||
|
||||
info.fd = ctx->fd;
|
||||
|
||||
err = bpf_map_update_elem(map_fd, &id, &info, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_PUTTING_FILE_DESCRIPTOR, id, err, origin_code);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline void fd_tracepoints_handle_go(struct sys_enter_read_write_ctx *ctx, __u64 id, struct bpf_map_def *map_fd, __u64 origin_code) {
|
||||
__u32 fd = ctx->fd;
|
||||
|
||||
long err = bpf_map_update_elem(map_fd, &id, &fd, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_PUTTING_FILE_DESCRIPTOR, id, err, origin_code);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SEC("tracepoint/syscalls/sys_enter_read")
|
||||
void sys_enter_read(struct sys_enter_read_ctx *ctx) {
|
||||
void sys_enter_read(struct sys_enter_read_write_ctx *ctx) {
|
||||
__u64 id = bpf_get_current_pid_tgid();
|
||||
|
||||
if (!should_tap(id >> 32)) {
|
||||
@ -30,38 +69,15 @@ void sys_enter_read(struct sys_enter_read_ctx *ctx) {
|
||||
|
||||
struct ssl_info *infoPtr = bpf_map_lookup_elem(&openssl_read_context, &id);
|
||||
|
||||
if (infoPtr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ssl_info info;
|
||||
long err = bpf_probe_read(&info, sizeof(struct ssl_info), infoPtr);
|
||||
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_READING_SSL_CONTEXT, id, err, ORIGIN_SYS_ENTER_READ_CODE);
|
||||
return;
|
||||
}
|
||||
|
||||
info.fd = ctx->fd;
|
||||
|
||||
err = bpf_map_update_elem(&openssl_read_context, &id, &info, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_PUTTING_FILE_DESCRIPTOR, id, err, ORIGIN_SYS_ENTER_READ_CODE);
|
||||
if (infoPtr != NULL) {
|
||||
fd_tracepoints_handle_openssl(ctx, id, infoPtr, &openssl_read_context, ORIGIN_SYS_ENTER_READ_CODE);
|
||||
}
|
||||
|
||||
fd_tracepoints_handle_go(ctx, id, &go_kernel_read_context, ORIGIN_SYS_ENTER_READ_CODE);
|
||||
}
|
||||
|
||||
struct sys_enter_write_ctx {
|
||||
__u64 __unused_syscall_header;
|
||||
__u32 __unused_syscall_nr;
|
||||
|
||||
__u64 fd;
|
||||
__u64* buf;
|
||||
__u64 count;
|
||||
};
|
||||
|
||||
SEC("tracepoint/syscalls/sys_enter_write")
|
||||
void sys_enter_write(struct sys_enter_write_ctx *ctx) {
|
||||
void sys_enter_write(struct sys_enter_read_write_ctx *ctx) {
|
||||
__u64 id = bpf_get_current_pid_tgid();
|
||||
|
||||
if (!should_tap(id >> 32)) {
|
||||
@ -70,23 +86,25 @@ void sys_enter_write(struct sys_enter_write_ctx *ctx) {
|
||||
|
||||
struct ssl_info *infoPtr = bpf_map_lookup_elem(&openssl_write_context, &id);
|
||||
|
||||
if (infoPtr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ssl_info info;
|
||||
long err = bpf_probe_read(&info, sizeof(struct ssl_info), infoPtr);
|
||||
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_READING_SSL_CONTEXT, id, err, ORIGIN_SYS_ENTER_WRITE_CODE);
|
||||
return;
|
||||
}
|
||||
|
||||
info.fd = ctx->fd;
|
||||
|
||||
err = bpf_map_update_elem(&openssl_write_context, &id, &info, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_PUTTING_FILE_DESCRIPTOR, id, err, ORIGIN_SYS_ENTER_WRITE_CODE);
|
||||
if (infoPtr != NULL) {
|
||||
fd_tracepoints_handle_openssl(ctx, id, infoPtr, &openssl_write_context, ORIGIN_SYS_ENTER_WRITE_CODE);
|
||||
}
|
||||
|
||||
fd_tracepoints_handle_go(ctx, id, &go_kernel_write_context, ORIGIN_SYS_ENTER_WRITE_CODE);
|
||||
}
|
||||
|
||||
SEC("tracepoint/syscalls/sys_exit_read")
|
||||
void sys_exit_read(struct sys_exit_read_write_ctx *ctx) {
|
||||
__u64 id = bpf_get_current_pid_tgid();
|
||||
// Delete from go map. The value is not used after exiting this syscall.
|
||||
// Keep value in openssl map.
|
||||
bpf_map_delete_elem(&go_kernel_read_context, &id);
|
||||
}
|
||||
|
||||
SEC("tracepoint/syscalls/sys_exit_write")
|
||||
void sys_exit_write(struct sys_exit_read_write_ctx *ctx) {
|
||||
__u64 id = bpf_get_current_pid_tgid();
|
||||
// Delete from go map. The value is not used after exiting this syscall.
|
||||
// Keep value in openssl map.
|
||||
bpf_map_delete_elem(&go_kernel_write_context, &id);
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ static __always_inline void go_crypto_tls_uprobe(struct pt_regs *ctx, struct bpf
|
||||
return;
|
||||
}
|
||||
|
||||
static __always_inline void go_crypto_tls_ex_uprobe(struct pt_regs *ctx, struct bpf_map_def* go_context, __u32 flags, enum ABI abi) {
|
||||
static __always_inline void go_crypto_tls_ex_uprobe(struct pt_regs *ctx, struct bpf_map_def* go_context, struct bpf_map_def* go_user_kernel_context, __u32 flags, enum ABI abi) {
|
||||
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
||||
__u64 pid = pid_tgid >> 32;
|
||||
if (!should_tap(pid)) {
|
||||
@ -285,6 +285,21 @@ static __always_inline void go_crypto_tls_ex_uprobe(struct pt_regs *ctx, struct
|
||||
}
|
||||
}
|
||||
|
||||
__u64 key = (__u64) pid << 32 | info_ptr->fd;
|
||||
struct address_info *address_info = bpf_map_lookup_elem(go_user_kernel_context, &key);
|
||||
// Ideally we would delete the entry from the map after reading it,
|
||||
// but sometimes the uprobe is called twice in a row without the tcp kprobes in between to fill in
|
||||
// the entry again. Keeping it in the map and rely on LRU logic.
|
||||
if (address_info == NULL) {
|
||||
log_error(ctx, LOG_ERROR_GETTING_GO_USER_KERNEL_CONTEXT, pid_tgid, info_ptr->fd, err);
|
||||
return;
|
||||
}
|
||||
|
||||
info.address_info.daddr = address_info->daddr;
|
||||
info.address_info.dport = address_info->dport;
|
||||
info.address_info.saddr = address_info->saddr;
|
||||
info.address_info.sport = address_info->sport;
|
||||
|
||||
output_ssl_chunk(ctx, &info, info.buffer_len, pid_tgid, flags);
|
||||
|
||||
return;
|
||||
@ -298,7 +313,7 @@ int BPF_KPROBE(go_crypto_tls_abi0_write) {
|
||||
|
||||
SEC("uprobe/go_crypto_tls_abi0_write_ex")
|
||||
int BPF_KPROBE(go_crypto_tls_abi0_write_ex) {
|
||||
go_crypto_tls_ex_uprobe(ctx, &go_write_context, 0, ABI0);
|
||||
go_crypto_tls_ex_uprobe(ctx, &go_write_context, &go_user_kernel_write_context, 0, ABI0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -310,7 +325,7 @@ int BPF_KPROBE(go_crypto_tls_abi0_read) {
|
||||
|
||||
SEC("uprobe/go_crypto_tls_abi0_read_ex")
|
||||
int BPF_KPROBE(go_crypto_tls_abi0_read_ex) {
|
||||
go_crypto_tls_ex_uprobe(ctx, &go_read_context, FLAGS_IS_READ_BIT, ABI0);
|
||||
go_crypto_tls_ex_uprobe(ctx, &go_read_context, &go_user_kernel_read_context, FLAGS_IS_READ_BIT, ABI0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -322,7 +337,7 @@ int BPF_KPROBE(go_crypto_tls_abi_internal_write) {
|
||||
|
||||
SEC("uprobe/go_crypto_tls_abi_internal_write_ex")
|
||||
int BPF_KPROBE(go_crypto_tls_abi_internal_write_ex) {
|
||||
go_crypto_tls_ex_uprobe(ctx, &go_write_context, 0, ABIInternal);
|
||||
go_crypto_tls_ex_uprobe(ctx, &go_write_context, &go_user_kernel_write_context, 0, ABIInternal);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -334,6 +349,6 @@ int BPF_KPROBE(go_crypto_tls_abi_internal_read) {
|
||||
|
||||
SEC("uprobe/go_crypto_tls_abi_internal_read_ex")
|
||||
int BPF_KPROBE(go_crypto_tls_abi_internal_read_ex) {
|
||||
go_crypto_tls_ex_uprobe(ctx, &go_read_context, FLAGS_IS_READ_BIT, ABIInternal);
|
||||
go_crypto_tls_ex_uprobe(ctx, &go_read_context, &go_user_kernel_read_context, FLAGS_IS_READ_BIT, ABIInternal);
|
||||
return 1;
|
||||
}
|
||||
|
@ -10,27 +10,28 @@ Copyright (C) UP9 Inc.
|
||||
// Must be synced with bpf_logger_messages.go
|
||||
//
|
||||
#define LOG_ERROR_READING_BYTES_COUNT (0)
|
||||
#define LOG_ERROR_READING_FD_ADDRESS (1)
|
||||
#define LOG_ERROR_READING_FROM_SSL_BUFFER (2)
|
||||
#define LOG_ERROR_BUFFER_TOO_BIG (3)
|
||||
#define LOG_ERROR_ALLOCATING_CHUNK (4)
|
||||
#define LOG_ERROR_READING_SSL_CONTEXT (5)
|
||||
#define LOG_ERROR_PUTTING_SSL_CONTEXT (6)
|
||||
#define LOG_ERROR_GETTING_SSL_CONTEXT (7)
|
||||
#define LOG_ERROR_MISSING_FILE_DESCRIPTOR (8)
|
||||
#define LOG_ERROR_PUTTING_FILE_DESCRIPTOR (9)
|
||||
#define LOG_ERROR_PUTTING_ACCEPT_INFO (10)
|
||||
#define LOG_ERROR_GETTING_ACCEPT_INFO (11)
|
||||
#define LOG_ERROR_READING_ACCEPT_INFO (12)
|
||||
#define LOG_ERROR_PUTTING_FD_MAPPING (13)
|
||||
#define LOG_ERROR_PUTTING_CONNECT_INFO (14)
|
||||
#define LOG_ERROR_GETTING_CONNECT_INFO (15)
|
||||
#define LOG_ERROR_READING_CONNECT_INFO (16)
|
||||
#define LOG_ERROR_READING_SOCKET_FAMILY (17)
|
||||
#define LOG_ERROR_READING_SOCKET_DADDR (18)
|
||||
#define LOG_ERROR_READING_SOCKET_SADDR (19)
|
||||
#define LOG_ERROR_READING_SOCKET_DPORT (20)
|
||||
#define LOG_ERROR_READING_SOCKET_SPORT (21)
|
||||
#define LOG_ERROR_READING_FROM_SSL_BUFFER (1)
|
||||
#define LOG_ERROR_BUFFER_TOO_BIG (2)
|
||||
#define LOG_ERROR_ALLOCATING_CHUNK (3)
|
||||
#define LOG_ERROR_READING_SSL_CONTEXT (4)
|
||||
#define LOG_ERROR_PUTTING_SSL_CONTEXT (5)
|
||||
#define LOG_ERROR_GETTING_SSL_CONTEXT (6)
|
||||
#define LOG_ERROR_MISSING_FILE_DESCRIPTOR (7)
|
||||
#define LOG_ERROR_PUTTING_FILE_DESCRIPTOR (8)
|
||||
#define LOG_ERROR_PUTTING_ACCEPT_INFO (9)
|
||||
#define LOG_ERROR_GETTING_ACCEPT_INFO (10)
|
||||
#define LOG_ERROR_READING_ACCEPT_INFO (11)
|
||||
#define LOG_ERROR_PUTTING_CONNECTION_CONTEXT (12)
|
||||
#define LOG_ERROR_PUTTING_CONNECT_INFO (13)
|
||||
#define LOG_ERROR_GETTING_CONNECT_INFO (14)
|
||||
#define LOG_ERROR_READING_CONNECT_INFO (15)
|
||||
#define LOG_ERROR_READING_SOCKET_FAMILY (16)
|
||||
#define LOG_ERROR_READING_SOCKET_DADDR (17)
|
||||
#define LOG_ERROR_READING_SOCKET_SADDR (18)
|
||||
#define LOG_ERROR_READING_SOCKET_DPORT (19)
|
||||
#define LOG_ERROR_READING_SOCKET_SPORT (20)
|
||||
#define LOG_ERROR_PUTTING_GO_USER_KERNEL_CONTEXT (21)
|
||||
#define LOG_ERROR_GETTING_GO_USER_KERNEL_CONTEXT (22)
|
||||
|
||||
// Sometimes we have the same error, happening from different locations.
|
||||
// in order to be able to distinct between them in the log, we add an
|
||||
|
@ -25,14 +25,7 @@ Copyright (C) UP9 Inc.
|
||||
// Be careful when editing, alignment and padding should be exactly the same in go/c.
|
||||
//
|
||||
|
||||
typedef enum {
|
||||
ADDRESS_INFO_MODE_UNDEFINED,
|
||||
ADDRESS_INFO_MODE_SINGLE,
|
||||
ADDRESS_INFO_MODE_PAIR,
|
||||
} address_info_mode;
|
||||
|
||||
struct address_info {
|
||||
address_info_mode mode;
|
||||
__be32 saddr;
|
||||
__be32 daddr;
|
||||
__be16 sport;
|
||||
@ -64,10 +57,7 @@ struct ssl_info {
|
||||
size_t *count_ptr;
|
||||
};
|
||||
|
||||
struct fd_info {
|
||||
__u8 ipv4_addr[16]; // struct sockaddr (linux-src/include/linux/socket.h)
|
||||
__u8 flags;
|
||||
};
|
||||
typedef __u8 conn_flags;
|
||||
|
||||
struct goid_offsets {
|
||||
__u64 g_addr_offset;
|
||||
@ -105,7 +95,7 @@ struct {
|
||||
|
||||
// Generic
|
||||
BPF_HASH(pids_map, __u32, __u32);
|
||||
BPF_LRU_HASH(file_descriptor_to_ipv4, __u64, struct fd_info);
|
||||
BPF_LRU_HASH(connection_context, __u64, conn_flags);
|
||||
BPF_PERF_OUTPUT(chunks_buffer);
|
||||
BPF_PERF_OUTPUT(log_buffer);
|
||||
|
||||
@ -117,5 +107,9 @@ BPF_LRU_HASH(openssl_read_context, __u64, struct ssl_info);
|
||||
BPF_HASH(goid_offsets_map, __u32, struct goid_offsets);
|
||||
BPF_LRU_HASH(go_write_context, __u64, struct ssl_info);
|
||||
BPF_LRU_HASH(go_read_context, __u64, struct ssl_info);
|
||||
BPF_LRU_HASH(go_kernel_write_context, __u64, __u32);
|
||||
BPF_LRU_HASH(go_kernel_read_context, __u64, __u32);
|
||||
BPF_LRU_HASH(go_user_kernel_write_context, __u64, struct address_info);
|
||||
BPF_LRU_HASH(go_user_kernel_read_context, __u64, struct address_info);
|
||||
|
||||
#endif /* __MAPS__ */
|
||||
|
@ -5,32 +5,19 @@
|
||||
#include "include/pids.h"
|
||||
#include "include/common.h"
|
||||
|
||||
static __always_inline void tcp_kprobe(struct pt_regs *ctx, struct bpf_map_def *map_fd, _Bool is_send) {
|
||||
|
||||
static __always_inline int tcp_kprobes_get_address_pair_from_ctx(struct pt_regs *ctx, __u64 id, struct address_info *address_info_ptr) {
|
||||
long err;
|
||||
|
||||
__u64 id = bpf_get_current_pid_tgid();
|
||||
__u32 pid = id >> 32;
|
||||
|
||||
if (!should_tap(id >> 32)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ssl_info *info_ptr = bpf_map_lookup_elem(map_fd, &id);
|
||||
// Happens when the connection is not tls
|
||||
if (info_ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct sock *sk = (struct sock *) PT_REGS_PARM1(ctx);
|
||||
|
||||
short unsigned int family;
|
||||
err = bpf_probe_read(&family, sizeof(family), (void *)&sk->__sk_common.skc_family);
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_READING_SOCKET_FAMILY, id, err, 0l);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
if (family != AF_INET) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// daddr, saddr and dport are in network byte order (big endian)
|
||||
@ -43,37 +30,89 @@ static __always_inline void tcp_kprobe(struct pt_regs *ctx, struct bpf_map_def *
|
||||
err = bpf_probe_read(&saddr, sizeof(saddr), (void *)&sk->__sk_common.skc_rcv_saddr);
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_READING_SOCKET_SADDR, id, err, 0l);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
err = bpf_probe_read(&daddr, sizeof(daddr), (void *)&sk->__sk_common.skc_daddr);
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_READING_SOCKET_DADDR, id, err, 0l);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
err = bpf_probe_read(&dport, sizeof(dport), (void *)&sk->__sk_common.skc_dport);
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_READING_SOCKET_DPORT, id, err, 0l);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
err = bpf_probe_read(&sport, sizeof(sport), (void *)&sk->__sk_common.skc_num);
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_READING_SOCKET_SPORT, id, err, 0l);
|
||||
return -1;
|
||||
}
|
||||
|
||||
address_info_ptr->daddr = daddr;
|
||||
address_info_ptr->saddr = saddr;
|
||||
address_info_ptr->dport = dport;
|
||||
address_info_ptr->sport = bpf_htons(sport);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline void tcp_kprobes_forward_go(struct pt_regs *ctx, __u64 id, __u32 fd, struct address_info address_info, struct bpf_map_def *map_fd_go_user_kernel) {
|
||||
__u32 pid = id >> 32;
|
||||
__u64 key = (__u64) pid << 32 | fd;
|
||||
|
||||
long err = bpf_map_update_elem(map_fd_go_user_kernel, &key, &address_info, BPF_ANY);
|
||||
if (err != 0) {
|
||||
log_error(ctx, LOG_ERROR_PUTTING_GO_USER_KERNEL_CONTEXT, id, fd, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void __always_inline tcp_kprobes_forward_openssl(struct ssl_info *info_ptr, struct address_info address_info) {
|
||||
info_ptr->address_info.daddr = address_info.daddr;
|
||||
info_ptr->address_info.saddr = address_info.saddr;
|
||||
info_ptr->address_info.dport = address_info.dport;
|
||||
info_ptr->address_info.sport = address_info.sport;
|
||||
}
|
||||
|
||||
static __always_inline void tcp_kprobe(struct pt_regs *ctx, struct bpf_map_def *map_fd_openssl, struct bpf_map_def *map_fd_go_kernel, struct bpf_map_def *map_fd_go_user_kernel) {
|
||||
long err;
|
||||
|
||||
__u64 id = bpf_get_current_pid_tgid();
|
||||
|
||||
if (!should_tap(id >> 32)) {
|
||||
return;
|
||||
}
|
||||
|
||||
info_ptr->address_info.mode = ADDRESS_INFO_MODE_PAIR;
|
||||
info_ptr->address_info.daddr = daddr;
|
||||
info_ptr->address_info.saddr = saddr;
|
||||
info_ptr->address_info.dport = dport;
|
||||
info_ptr->address_info.sport = bpf_htons(sport);
|
||||
struct address_info address_info;
|
||||
if (0 != tcp_kprobes_get_address_pair_from_ctx(ctx, id, &address_info)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ssl_info *info_ptr = bpf_map_lookup_elem(map_fd_openssl, &id);
|
||||
__u32 *fd_ptr;
|
||||
if (info_ptr == NULL) {
|
||||
fd_ptr = bpf_map_lookup_elem(map_fd_go_kernel, &id);
|
||||
// Connection is used by a Go program
|
||||
if (fd_ptr == NULL) {
|
||||
// Connection was not created by a Go program or by openssl lib
|
||||
return;
|
||||
}
|
||||
tcp_kprobes_forward_go(ctx, id, *fd_ptr, address_info, map_fd_go_user_kernel);
|
||||
} else {
|
||||
// Connection is used by openssl lib
|
||||
tcp_kprobes_forward_openssl(info_ptr, address_info);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SEC("kprobe/tcp_sendmsg")
|
||||
void BPF_KPROBE(tcp_sendmsg) {
|
||||
tcp_kprobe(ctx, &openssl_write_context, true);
|
||||
__u64 id = bpf_get_current_pid_tgid();
|
||||
tcp_kprobe(ctx, &openssl_write_context, &go_kernel_write_context, &go_user_kernel_write_context);
|
||||
}
|
||||
|
||||
SEC("kprobe/tcp_recvmsg")
|
||||
void BPF_KPROBE(tcp_recvmsg) {
|
||||
tcp_kprobe(ctx, &openssl_read_context, false);
|
||||
__u64 id = bpf_get_current_pid_tgid();
|
||||
tcp_kprobe(ctx, &openssl_read_context, &go_kernel_read_context, &go_user_kernel_read_context);
|
||||
}
|
||||
|
@ -4,25 +4,26 @@ package tlstapper
|
||||
//
|
||||
var bpfLogMessages = []string{
|
||||
/*0000*/ "[%d] Unable to read bytes count from _ex methods [err: %d]",
|
||||
/*0001*/ "[%d] Unable to read ipv4 address [err: %d]",
|
||||
/*0002*/ "[%d] Unable to read ssl buffer [err: %d]",
|
||||
/*0003*/ "[%d] Buffer is too big [size: %d]",
|
||||
/*0004*/ "[%d] Unable to allocate chunk in bpf heap",
|
||||
/*0005*/ "[%d] Unable to read ssl context [err: %d] [origin: %d]",
|
||||
/*0006*/ "[%d] Unable to put ssl context [err: %d]",
|
||||
/*0007*/ "[%d] Unable to get ssl context",
|
||||
/*0008*/ "[%d] File descriptor is missing for tls chunk",
|
||||
/*0009*/ "[%d] Unable to put file descriptor [err: %d] [origin: %d]",
|
||||
/*0010*/ "[%d] Unable to put accept info [err: %d]",
|
||||
/*0011*/ "[%d] Unable to get accept info",
|
||||
/*0012*/ "[%d] Unable to read accept info [err: %d]",
|
||||
/*0013*/ "[%d] Unable to put file descriptor to address mapping [err: %d] [origin: %d]",
|
||||
/*0014*/ "[%d] Unable to put connect info [err: %d]",
|
||||
/*0015*/ "[%d] Unable to get connect info",
|
||||
/*0016*/ "[%d] Unable to read connect info [err: %d]",
|
||||
/*0017*/ "[%d] Unable to read socket family [err: %d]",
|
||||
/*0018*/ "[%d] Unable to read socket daddr [err: %d]",
|
||||
/*0019*/ "[%d] Unable to read socket saddr [err: %d]",
|
||||
/*0001*/ "[%d] Unable to read ssl buffer [err: %d] [origin: %d]",
|
||||
/*0002*/ "[%d] Buffer is too big [size: %d]",
|
||||
/*0003*/ "[%d] Unable to allocate chunk in bpf heap",
|
||||
/*0004*/ "[%d] Unable to read ssl context [err: %d] [origin: %d]",
|
||||
/*0005*/ "[%d] Unable to put ssl context [err: %d]",
|
||||
/*0006*/ "[%d] Unable to get ssl context",
|
||||
/*0007*/ "[%d] File descriptor is missing for tls chunk",
|
||||
/*0008*/ "[%d] Unable to put file descriptor [err: %d] [origin: %d]",
|
||||
/*0009*/ "[%d] Unable to put accept info [err: %d]",
|
||||
/*0010*/ "[%d] Unable to get accept info",
|
||||
/*0011*/ "[%d] Unable to read accept info [err: %d]",
|
||||
/*0012*/ "[%d] Unable to put connection info to connection context [err: %d] [origin: %d]",
|
||||
/*0013*/ "[%d] Unable to put connect info [err: %d]",
|
||||
/*0014*/ "[%d] Unable to get connect info",
|
||||
/*0015*/ "[%d] Unable to read connect info [err: %d]",
|
||||
/*0016*/ "[%d] Unable to read socket family [err: %d]",
|
||||
/*0017*/ "[%d] Unable to read socket daddr [err: %d]",
|
||||
/*0018*/ "[%d] Unable to read socket saddr [err: %d]",
|
||||
/*0019*/ "[%d] Unable to read socket dport [err: %d]",
|
||||
/*0021*/ "[%d] Unable to read socket sport [err: %d]",
|
||||
/*0020*/ "[%d] Unable to read socket sport [err: %d]",
|
||||
/*0021*/ "[%d] Unable to put go user-kernel context [fd: %d] [err: %d]",
|
||||
/*0022*/ "[%d] Unable to get go user-kernel context [fd: %d]]",
|
||||
}
|
||||
|
@ -4,17 +4,17 @@ import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"unsafe"
|
||||
|
||||
"github.com/up9inc/mizu/tap/api"
|
||||
)
|
||||
|
||||
const FlagsIsClientBit uint32 = 1 << 0
|
||||
const FlagsIsReadBit uint32 = 1 << 1
|
||||
const (
|
||||
addressInfoModeUndefined = iota
|
||||
addressInfoModeSingle
|
||||
addressInfoModePair
|
||||
)
|
||||
|
||||
type addressPair struct {
|
||||
srcIp net.IP
|
||||
srcPort uint16
|
||||
dstIp net.IP
|
||||
dstPort uint16
|
||||
}
|
||||
|
||||
func (c *tlsTapperTlsChunk) getSrcAddress() (net.IP, uint16) {
|
||||
ip := intToIP(c.AddressInfo.Saddr)
|
||||
@ -54,36 +54,18 @@ func (c *tlsTapperTlsChunk) isRequest() bool {
|
||||
return (c.isClient() && c.isWrite()) || (c.isServer() && c.isRead())
|
||||
}
|
||||
|
||||
func (c *tlsTapperTlsChunk) getAddressPair() (addressPair, bool) {
|
||||
func (c *tlsTapperTlsChunk) getAddressPair() addressPair {
|
||||
var (
|
||||
srcIp, dstIp net.IP
|
||||
srcPort, dstPort uint16
|
||||
full bool
|
||||
)
|
||||
|
||||
switch c.AddressInfo.Mode {
|
||||
case addressInfoModeSingle:
|
||||
if c.isRequest() {
|
||||
srcIp, srcPort = api.UnknownIp, api.UnknownPort
|
||||
dstIp, dstPort = c.getSrcAddress()
|
||||
} else {
|
||||
srcIp, srcPort = c.getSrcAddress()
|
||||
dstIp, dstPort = api.UnknownIp, api.UnknownPort
|
||||
}
|
||||
full = false
|
||||
case addressInfoModePair:
|
||||
if c.isRequest() {
|
||||
srcIp, srcPort = c.getSrcAddress()
|
||||
dstIp, dstPort = c.getDstAddress()
|
||||
} else {
|
||||
srcIp, srcPort = c.getDstAddress()
|
||||
dstIp, dstPort = c.getSrcAddress()
|
||||
}
|
||||
full = true
|
||||
case addressInfoModeUndefined:
|
||||
srcIp, srcPort = api.UnknownIp, api.UnknownPort
|
||||
dstIp, dstPort = api.UnknownIp, api.UnknownPort
|
||||
full = false
|
||||
if c.isRequest() {
|
||||
srcIp, srcPort = c.getSrcAddress()
|
||||
dstIp, dstPort = c.getDstAddress()
|
||||
} else {
|
||||
srcIp, srcPort = c.getDstAddress()
|
||||
dstIp, dstPort = c.getSrcAddress()
|
||||
}
|
||||
|
||||
return addressPair{
|
||||
@ -91,7 +73,7 @@ func (c *tlsTapperTlsChunk) getAddressPair() (addressPair, bool) {
|
||||
srcPort: srcPort,
|
||||
dstIp: dstIp,
|
||||
dstPort: dstPort,
|
||||
}, full
|
||||
}
|
||||
}
|
||||
|
||||
// intToIP converts IPv4 number to net.IP
|
||||
|
@ -1,122 +0,0 @@
|
||||
package tlstapper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
)
|
||||
|
||||
var socketInodeRegex = regexp.MustCompile(`socket:\[(\d+)\]`)
|
||||
|
||||
const (
|
||||
SRC_ADDRESS_FILED_INDEX = 1
|
||||
DST_ADDRESS_FILED_INDEX = 2
|
||||
INODE_FILED_INDEX = 9
|
||||
)
|
||||
|
||||
type addressPair struct {
|
||||
srcIp net.IP
|
||||
srcPort uint16
|
||||
dstIp net.IP
|
||||
dstPort uint16
|
||||
}
|
||||
|
||||
// This file helps to extract Ip and Port out of a Socket file descriptor.
|
||||
//
|
||||
// The equivalent bash commands are:
|
||||
//
|
||||
// > ls -l /proc/<pid>/fd/<fd>
|
||||
// Output something like "socket:[1234]" for sockets - 1234 is the inode of the socket
|
||||
// > cat /proc/<pid>/net/tcp | grep <inode>
|
||||
// Output a line per ipv4 socket, the 9th field is the inode of the socket
|
||||
// The 1st and 2nd fields are the source and dest ip and ports in a Hex format
|
||||
// 0100007F:50 is 127.0.0.1:80
|
||||
|
||||
func getAddressBySockfd(procfs string, pid uint32, fd uint32) (addressPair, error) {
|
||||
inode, err := getSocketInode(procfs, pid, fd)
|
||||
|
||||
if err != nil {
|
||||
return addressPair{}, err
|
||||
}
|
||||
|
||||
tcppath := fmt.Sprintf("%s/%d/net/tcp", procfs, pid)
|
||||
tcp, err := ioutil.ReadFile(tcppath)
|
||||
|
||||
if err != nil {
|
||||
return addressPair{}, errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(string(tcp), "\n") {
|
||||
parts := strings.Fields(line)
|
||||
|
||||
if len(parts) < 10 {
|
||||
continue
|
||||
}
|
||||
|
||||
if inode == parts[INODE_FILED_INDEX] {
|
||||
srcIp, srcPort, srcErr := parseHexAddress(parts[SRC_ADDRESS_FILED_INDEX])
|
||||
|
||||
if srcErr != nil {
|
||||
return addressPair{}, srcErr
|
||||
}
|
||||
|
||||
dstIp, dstPort, dstErr := parseHexAddress(parts[DST_ADDRESS_FILED_INDEX])
|
||||
|
||||
if dstErr != nil {
|
||||
return addressPair{}, dstErr
|
||||
}
|
||||
|
||||
return addressPair{
|
||||
srcIp: srcIp,
|
||||
srcPort: srcPort,
|
||||
dstIp: dstIp,
|
||||
dstPort: dstPort,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return addressPair{}, errors.Errorf("address not found [pid: %d] [sockfd: %d] [inode: %s]", pid, fd, inode)
|
||||
}
|
||||
|
||||
func getSocketInode(procfs string, pid uint32, fd uint32) (string, error) {
|
||||
fdlinkPath := fmt.Sprintf("%s/%d/fd/%d", procfs, pid, fd)
|
||||
fdlink, err := os.Readlink(fdlinkPath)
|
||||
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
tokens := socketInodeRegex.FindStringSubmatch(fdlink)
|
||||
|
||||
if tokens == nil || len(tokens) < 1 {
|
||||
return "", errors.Errorf("socket inode not found [pid: %d] [sockfd: %d] [link: %s]", pid, fd, fdlink)
|
||||
}
|
||||
|
||||
return tokens[1], nil
|
||||
}
|
||||
|
||||
// Format looks like 0100007F:50 for 127.0.0.1:80
|
||||
//
|
||||
func parseHexAddress(addr string) (net.IP, uint16, error) {
|
||||
addrParts := strings.Split(addr, ":")
|
||||
|
||||
port, err := strconv.ParseUint(addrParts[1], 16, 16)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
ip, err := strconv.ParseUint(addrParts[0], 16, 32)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
return net.IP{uint8(ip), uint8(ip >> 8), uint8(ip >> 16), uint8(ip >> 24)}, uint16(port), nil
|
||||
}
|
@ -14,8 +14,6 @@ type sslHooks struct {
|
||||
sslWriteExRetProbe link.Link
|
||||
sslReadExProbe link.Link
|
||||
sslReadExRetProbe link.Link
|
||||
tcpSendmsg link.Link
|
||||
tcpRecvmsg link.Link
|
||||
}
|
||||
|
||||
func (s *sslHooks) installUprobes(bpfObjects *tlsTapperObjects, sslLibraryPath string) error {
|
||||
@ -105,16 +103,6 @@ func (s *sslHooks) installSslHooks(bpfObjects *tlsTapperObjects, sslLibrary *lin
|
||||
}
|
||||
}
|
||||
|
||||
s.tcpSendmsg, err = link.Kprobe("tcp_sendmsg", bpfObjects.TcpSendmsg, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
s.tcpRecvmsg, err = link.Kprobe("tcp_recvmsg", bpfObjects.TcpRecvmsg, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -161,17 +149,5 @@ func (s *sslHooks) close() []error {
|
||||
}
|
||||
}
|
||||
|
||||
if s.tcpSendmsg != nil {
|
||||
if err := s.tcpSendmsg.Close(); err != nil {
|
||||
returnValue = append(returnValue, err)
|
||||
}
|
||||
}
|
||||
|
||||
if s.tcpRecvmsg != nil {
|
||||
if err := s.tcpRecvmsg.Close(); err != nil {
|
||||
returnValue = append(returnValue, err)
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
type syscallHooks struct {
|
||||
sysEnterRead link.Link
|
||||
sysEnterWrite link.Link
|
||||
sysExitRead link.Link
|
||||
sysExitWrite link.Link
|
||||
sysEnterAccept4 link.Link
|
||||
sysExitAccept4 link.Link
|
||||
sysEnterConnect link.Link
|
||||
@ -29,6 +31,18 @@ func (s *syscallHooks) installSyscallHooks(bpfObjects *tlsTapperObjects) error {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
s.sysExitRead, err = link.Tracepoint("syscalls", "sys_exit_read", bpfObjects.SysExitRead, nil)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
s.sysExitWrite, err = link.Tracepoint("syscalls", "sys_exit_write", bpfObjects.SysExitWrite, nil)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
s.sysEnterAccept4, err = link.Tracepoint("syscalls", "sys_enter_accept4", bpfObjects.SysEnterAccept4, nil)
|
||||
|
||||
if err != nil {
|
||||
@ -67,6 +81,14 @@ func (s *syscallHooks) close() []error {
|
||||
returnValue = append(returnValue, err)
|
||||
}
|
||||
|
||||
if err := s.sysExitRead.Close(); err != nil {
|
||||
returnValue = append(returnValue, err)
|
||||
}
|
||||
|
||||
if err := s.sysExitWrite.Close(); err != nil {
|
||||
returnValue = append(returnValue, err)
|
||||
}
|
||||
|
||||
if err := s.sysEnterAccept4.Close(); err != nil {
|
||||
returnValue = append(returnValue, err)
|
||||
}
|
||||
|
45
tap/tlstapper/tcp_kprobe_hooks.go
Normal file
45
tap/tlstapper/tcp_kprobe_hooks.go
Normal file
@ -0,0 +1,45 @@
|
||||
package tlstapper
|
||||
|
||||
import (
|
||||
"github.com/cilium/ebpf/link"
|
||||
"github.com/go-errors/errors"
|
||||
)
|
||||
|
||||
type tcpKprobeHooks struct {
|
||||
tcpSendmsg link.Link
|
||||
tcpRecvmsg link.Link
|
||||
}
|
||||
|
||||
func (s *tcpKprobeHooks) installTcpKprobeHooks(bpfObjects *tlsTapperObjects) error {
|
||||
var err error
|
||||
|
||||
s.tcpSendmsg, err = link.Kprobe("tcp_sendmsg", bpfObjects.TcpSendmsg, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
s.tcpRecvmsg, err = link.Kprobe("tcp_recvmsg", bpfObjects.TcpRecvmsg, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *tcpKprobeHooks) close() []error {
|
||||
returnValue := make([]error, 0)
|
||||
|
||||
if s.tcpSendmsg != nil {
|
||||
if err := s.tcpSendmsg.Close(); err != nil {
|
||||
returnValue = append(returnValue, err)
|
||||
}
|
||||
}
|
||||
|
||||
if s.tcpRecvmsg != nil {
|
||||
if err := s.tcpRecvmsg.Close(); err != nil {
|
||||
returnValue = append(returnValue, err)
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue
|
||||
}
|
@ -134,10 +134,7 @@ func (p *tlsPoller) pollChunksPerfBuffer(chunks chan<- *tlsTapperTlsChunk) {
|
||||
|
||||
func (p *tlsPoller) handleTlsChunk(chunk *tlsTapperTlsChunk, extension *api.Extension, emitter api.Emitter,
|
||||
options *api.TrafficFilteringOptions, streamsMap api.TcpStreamMap) error {
|
||||
address, err := p.getAddressPair(chunk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
address := chunk.getAddressPair()
|
||||
|
||||
key := buildTlsKey(address)
|
||||
reader, exists := p.readers[key]
|
||||
@ -156,22 +153,6 @@ func (p *tlsPoller) handleTlsChunk(chunk *tlsTapperTlsChunk, extension *api.Exte
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *tlsPoller) getAddressPair(chunk *tlsTapperTlsChunk) (addressPair, error) {
|
||||
addrPairFromChunk, full := chunk.getAddressPair()
|
||||
if full {
|
||||
return addrPairFromChunk, nil
|
||||
}
|
||||
|
||||
addrPairFromSockfd, err := p.getSockfdAddressPair(chunk)
|
||||
if err == nil {
|
||||
return addrPairFromSockfd, nil
|
||||
} else {
|
||||
logger.Log.Error("failed to get address from sock fd:", err)
|
||||
}
|
||||
|
||||
return addrPairFromChunk, err
|
||||
}
|
||||
|
||||
func (p *tlsPoller) startNewTlsReader(chunk *tlsTapperTlsChunk, address *addressPair, key string,
|
||||
emitter api.Emitter, extension *api.Extension, options *api.TrafficFilteringOptions,
|
||||
streamsMap api.TcpStreamMap) *tlsReader {
|
||||
@ -227,41 +208,6 @@ func (p *tlsPoller) closeReader(key string, r *tlsReader) {
|
||||
p.closedReaders <- key
|
||||
}
|
||||
|
||||
func (p *tlsPoller) getSockfdAddressPair(chunk *tlsTapperTlsChunk) (addressPair, error) {
|
||||
address, err := getAddressBySockfd(p.procfs, chunk.Pid, chunk.Fd)
|
||||
fdCacheKey := fmt.Sprintf("%d:%d", chunk.Pid, chunk.Fd)
|
||||
|
||||
if err == nil {
|
||||
if !chunk.isRequest() {
|
||||
switchedAddress := addressPair{
|
||||
srcIp: address.dstIp,
|
||||
srcPort: address.dstPort,
|
||||
dstIp: address.srcIp,
|
||||
dstPort: address.srcPort,
|
||||
}
|
||||
p.fdCache.Add(fdCacheKey, switchedAddress)
|
||||
return switchedAddress, nil
|
||||
} else {
|
||||
p.fdCache.Add(fdCacheKey, address)
|
||||
return address, nil
|
||||
}
|
||||
}
|
||||
|
||||
fromCacheIfc, ok := p.fdCache.Get(fdCacheKey)
|
||||
|
||||
if !ok {
|
||||
return addressPair{}, err
|
||||
}
|
||||
|
||||
fromCache, ok := fromCacheIfc.(addressPair)
|
||||
|
||||
if !ok {
|
||||
return address, errors.Errorf("Unable to cast %T to addressPair", fromCacheIfc)
|
||||
}
|
||||
|
||||
return fromCache, nil
|
||||
}
|
||||
|
||||
func buildTlsKey(address addressPair) string {
|
||||
return fmt.Sprintf("%s:%d>%s:%d", address.srcIp, address.srcPort, address.dstIp, address.dstPort)
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ const GlobalTapPid = 0
|
||||
type TlsTapper struct {
|
||||
bpfObjects tlsTapperObjects
|
||||
syscallHooks syscallHooks
|
||||
tcpKprobeHooks tcpKprobeHooks
|
||||
sslHooksStructs []sslHooks
|
||||
goHooksStructs []goHooks
|
||||
poller *tlsPoller
|
||||
@ -63,6 +64,11 @@ func (t *TlsTapper) Init(chunksBufferSize int, logBufferSize int, procfs string,
|
||||
return err
|
||||
}
|
||||
|
||||
t.tcpKprobeHooks = tcpKprobeHooks{}
|
||||
if err := t.tcpKprobeHooks.installTcpKprobeHooks(&t.bpfObjects); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.sslHooksStructs = make([]sslHooks, 0)
|
||||
|
||||
t.bpfLogger = newBpfLogger()
|
||||
@ -152,6 +158,8 @@ func (t *TlsTapper) Close() []error {
|
||||
|
||||
returnValue = append(returnValue, t.syscallHooks.close()...)
|
||||
|
||||
returnValue = append(returnValue, t.tcpKprobeHooks.close()...)
|
||||
|
||||
for _, sslHooks := range t.sslHooksStructs {
|
||||
returnValue = append(returnValue, sslHooks.close()...)
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ type tlsTapper46TlsChunk struct {
|
||||
Fd uint32
|
||||
Flags uint32
|
||||
AddressInfo struct {
|
||||
Mode int32
|
||||
Saddr uint32
|
||||
Daddr uint32
|
||||
Sport uint16
|
||||
@ -99,6 +98,8 @@ type tlsTapper46ProgramSpecs struct {
|
||||
SysEnterWrite *ebpf.ProgramSpec `ebpf:"sys_enter_write"`
|
||||
SysExitAccept4 *ebpf.ProgramSpec `ebpf:"sys_exit_accept4"`
|
||||
SysExitConnect *ebpf.ProgramSpec `ebpf:"sys_exit_connect"`
|
||||
SysExitRead *ebpf.ProgramSpec `ebpf:"sys_exit_read"`
|
||||
SysExitWrite *ebpf.ProgramSpec `ebpf:"sys_exit_write"`
|
||||
TcpRecvmsg *ebpf.ProgramSpec `ebpf:"tcp_recvmsg"`
|
||||
TcpSendmsg *ebpf.ProgramSpec `ebpf:"tcp_sendmsg"`
|
||||
}
|
||||
@ -107,18 +108,22 @@ type tlsTapper46ProgramSpecs struct {
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type tlsTapper46MapSpecs struct {
|
||||
AcceptSyscallContext *ebpf.MapSpec `ebpf:"accept_syscall_context"`
|
||||
ChunksBuffer *ebpf.MapSpec `ebpf:"chunks_buffer"`
|
||||
ConnectSyscallInfo *ebpf.MapSpec `ebpf:"connect_syscall_info"`
|
||||
FileDescriptorToIpv4 *ebpf.MapSpec `ebpf:"file_descriptor_to_ipv4"`
|
||||
GoReadContext *ebpf.MapSpec `ebpf:"go_read_context"`
|
||||
GoWriteContext *ebpf.MapSpec `ebpf:"go_write_context"`
|
||||
GoidOffsetsMap *ebpf.MapSpec `ebpf:"goid_offsets_map"`
|
||||
Heap *ebpf.MapSpec `ebpf:"heap"`
|
||||
LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"`
|
||||
OpensslReadContext *ebpf.MapSpec `ebpf:"openssl_read_context"`
|
||||
OpensslWriteContext *ebpf.MapSpec `ebpf:"openssl_write_context"`
|
||||
PidsMap *ebpf.MapSpec `ebpf:"pids_map"`
|
||||
AcceptSyscallContext *ebpf.MapSpec `ebpf:"accept_syscall_context"`
|
||||
ChunksBuffer *ebpf.MapSpec `ebpf:"chunks_buffer"`
|
||||
ConnectSyscallInfo *ebpf.MapSpec `ebpf:"connect_syscall_info"`
|
||||
ConnectionContext *ebpf.MapSpec `ebpf:"connection_context"`
|
||||
GoKernelReadContext *ebpf.MapSpec `ebpf:"go_kernel_read_context"`
|
||||
GoKernelWriteContext *ebpf.MapSpec `ebpf:"go_kernel_write_context"`
|
||||
GoReadContext *ebpf.MapSpec `ebpf:"go_read_context"`
|
||||
GoUserKernelReadContext *ebpf.MapSpec `ebpf:"go_user_kernel_read_context"`
|
||||
GoUserKernelWriteContext *ebpf.MapSpec `ebpf:"go_user_kernel_write_context"`
|
||||
GoWriteContext *ebpf.MapSpec `ebpf:"go_write_context"`
|
||||
GoidOffsetsMap *ebpf.MapSpec `ebpf:"goid_offsets_map"`
|
||||
Heap *ebpf.MapSpec `ebpf:"heap"`
|
||||
LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"`
|
||||
OpensslReadContext *ebpf.MapSpec `ebpf:"openssl_read_context"`
|
||||
OpensslWriteContext *ebpf.MapSpec `ebpf:"openssl_write_context"`
|
||||
PidsMap *ebpf.MapSpec `ebpf:"pids_map"`
|
||||
}
|
||||
|
||||
// tlsTapper46Objects contains all objects after they have been loaded into the kernel.
|
||||
@ -140,18 +145,22 @@ func (o *tlsTapper46Objects) Close() error {
|
||||
//
|
||||
// It can be passed to loadTlsTapper46Objects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type tlsTapper46Maps struct {
|
||||
AcceptSyscallContext *ebpf.Map `ebpf:"accept_syscall_context"`
|
||||
ChunksBuffer *ebpf.Map `ebpf:"chunks_buffer"`
|
||||
ConnectSyscallInfo *ebpf.Map `ebpf:"connect_syscall_info"`
|
||||
FileDescriptorToIpv4 *ebpf.Map `ebpf:"file_descriptor_to_ipv4"`
|
||||
GoReadContext *ebpf.Map `ebpf:"go_read_context"`
|
||||
GoWriteContext *ebpf.Map `ebpf:"go_write_context"`
|
||||
GoidOffsetsMap *ebpf.Map `ebpf:"goid_offsets_map"`
|
||||
Heap *ebpf.Map `ebpf:"heap"`
|
||||
LogBuffer *ebpf.Map `ebpf:"log_buffer"`
|
||||
OpensslReadContext *ebpf.Map `ebpf:"openssl_read_context"`
|
||||
OpensslWriteContext *ebpf.Map `ebpf:"openssl_write_context"`
|
||||
PidsMap *ebpf.Map `ebpf:"pids_map"`
|
||||
AcceptSyscallContext *ebpf.Map `ebpf:"accept_syscall_context"`
|
||||
ChunksBuffer *ebpf.Map `ebpf:"chunks_buffer"`
|
||||
ConnectSyscallInfo *ebpf.Map `ebpf:"connect_syscall_info"`
|
||||
ConnectionContext *ebpf.Map `ebpf:"connection_context"`
|
||||
GoKernelReadContext *ebpf.Map `ebpf:"go_kernel_read_context"`
|
||||
GoKernelWriteContext *ebpf.Map `ebpf:"go_kernel_write_context"`
|
||||
GoReadContext *ebpf.Map `ebpf:"go_read_context"`
|
||||
GoUserKernelReadContext *ebpf.Map `ebpf:"go_user_kernel_read_context"`
|
||||
GoUserKernelWriteContext *ebpf.Map `ebpf:"go_user_kernel_write_context"`
|
||||
GoWriteContext *ebpf.Map `ebpf:"go_write_context"`
|
||||
GoidOffsetsMap *ebpf.Map `ebpf:"goid_offsets_map"`
|
||||
Heap *ebpf.Map `ebpf:"heap"`
|
||||
LogBuffer *ebpf.Map `ebpf:"log_buffer"`
|
||||
OpensslReadContext *ebpf.Map `ebpf:"openssl_read_context"`
|
||||
OpensslWriteContext *ebpf.Map `ebpf:"openssl_write_context"`
|
||||
PidsMap *ebpf.Map `ebpf:"pids_map"`
|
||||
}
|
||||
|
||||
func (m *tlsTapper46Maps) Close() error {
|
||||
@ -159,8 +168,12 @@ func (m *tlsTapper46Maps) Close() error {
|
||||
m.AcceptSyscallContext,
|
||||
m.ChunksBuffer,
|
||||
m.ConnectSyscallInfo,
|
||||
m.FileDescriptorToIpv4,
|
||||
m.ConnectionContext,
|
||||
m.GoKernelReadContext,
|
||||
m.GoKernelWriteContext,
|
||||
m.GoReadContext,
|
||||
m.GoUserKernelReadContext,
|
||||
m.GoUserKernelWriteContext,
|
||||
m.GoWriteContext,
|
||||
m.GoidOffsetsMap,
|
||||
m.Heap,
|
||||
@ -197,6 +210,8 @@ type tlsTapper46Programs struct {
|
||||
SysEnterWrite *ebpf.Program `ebpf:"sys_enter_write"`
|
||||
SysExitAccept4 *ebpf.Program `ebpf:"sys_exit_accept4"`
|
||||
SysExitConnect *ebpf.Program `ebpf:"sys_exit_connect"`
|
||||
SysExitRead *ebpf.Program `ebpf:"sys_exit_read"`
|
||||
SysExitWrite *ebpf.Program `ebpf:"sys_exit_write"`
|
||||
TcpRecvmsg *ebpf.Program `ebpf:"tcp_recvmsg"`
|
||||
TcpSendmsg *ebpf.Program `ebpf:"tcp_sendmsg"`
|
||||
}
|
||||
@ -225,6 +240,8 @@ func (p *tlsTapper46Programs) Close() error {
|
||||
p.SysEnterWrite,
|
||||
p.SysExitAccept4,
|
||||
p.SysExitConnect,
|
||||
p.SysExitRead,
|
||||
p.SysExitWrite,
|
||||
p.TcpRecvmsg,
|
||||
p.TcpSendmsg,
|
||||
)
|
||||
|
@ -27,7 +27,6 @@ type tlsTapperTlsChunk struct {
|
||||
Fd uint32
|
||||
Flags uint32
|
||||
AddressInfo struct {
|
||||
Mode int32
|
||||
Saddr uint32
|
||||
Daddr uint32
|
||||
Sport uint16
|
||||
@ -99,6 +98,8 @@ type tlsTapperProgramSpecs struct {
|
||||
SysEnterWrite *ebpf.ProgramSpec `ebpf:"sys_enter_write"`
|
||||
SysExitAccept4 *ebpf.ProgramSpec `ebpf:"sys_exit_accept4"`
|
||||
SysExitConnect *ebpf.ProgramSpec `ebpf:"sys_exit_connect"`
|
||||
SysExitRead *ebpf.ProgramSpec `ebpf:"sys_exit_read"`
|
||||
SysExitWrite *ebpf.ProgramSpec `ebpf:"sys_exit_write"`
|
||||
TcpRecvmsg *ebpf.ProgramSpec `ebpf:"tcp_recvmsg"`
|
||||
TcpSendmsg *ebpf.ProgramSpec `ebpf:"tcp_sendmsg"`
|
||||
}
|
||||
@ -107,18 +108,22 @@ type tlsTapperProgramSpecs struct {
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type tlsTapperMapSpecs struct {
|
||||
AcceptSyscallContext *ebpf.MapSpec `ebpf:"accept_syscall_context"`
|
||||
ChunksBuffer *ebpf.MapSpec `ebpf:"chunks_buffer"`
|
||||
ConnectSyscallInfo *ebpf.MapSpec `ebpf:"connect_syscall_info"`
|
||||
FileDescriptorToIpv4 *ebpf.MapSpec `ebpf:"file_descriptor_to_ipv4"`
|
||||
GoReadContext *ebpf.MapSpec `ebpf:"go_read_context"`
|
||||
GoWriteContext *ebpf.MapSpec `ebpf:"go_write_context"`
|
||||
GoidOffsetsMap *ebpf.MapSpec `ebpf:"goid_offsets_map"`
|
||||
Heap *ebpf.MapSpec `ebpf:"heap"`
|
||||
LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"`
|
||||
OpensslReadContext *ebpf.MapSpec `ebpf:"openssl_read_context"`
|
||||
OpensslWriteContext *ebpf.MapSpec `ebpf:"openssl_write_context"`
|
||||
PidsMap *ebpf.MapSpec `ebpf:"pids_map"`
|
||||
AcceptSyscallContext *ebpf.MapSpec `ebpf:"accept_syscall_context"`
|
||||
ChunksBuffer *ebpf.MapSpec `ebpf:"chunks_buffer"`
|
||||
ConnectSyscallInfo *ebpf.MapSpec `ebpf:"connect_syscall_info"`
|
||||
ConnectionContext *ebpf.MapSpec `ebpf:"connection_context"`
|
||||
GoKernelReadContext *ebpf.MapSpec `ebpf:"go_kernel_read_context"`
|
||||
GoKernelWriteContext *ebpf.MapSpec `ebpf:"go_kernel_write_context"`
|
||||
GoReadContext *ebpf.MapSpec `ebpf:"go_read_context"`
|
||||
GoUserKernelReadContext *ebpf.MapSpec `ebpf:"go_user_kernel_read_context"`
|
||||
GoUserKernelWriteContext *ebpf.MapSpec `ebpf:"go_user_kernel_write_context"`
|
||||
GoWriteContext *ebpf.MapSpec `ebpf:"go_write_context"`
|
||||
GoidOffsetsMap *ebpf.MapSpec `ebpf:"goid_offsets_map"`
|
||||
Heap *ebpf.MapSpec `ebpf:"heap"`
|
||||
LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"`
|
||||
OpensslReadContext *ebpf.MapSpec `ebpf:"openssl_read_context"`
|
||||
OpensslWriteContext *ebpf.MapSpec `ebpf:"openssl_write_context"`
|
||||
PidsMap *ebpf.MapSpec `ebpf:"pids_map"`
|
||||
}
|
||||
|
||||
// tlsTapperObjects contains all objects after they have been loaded into the kernel.
|
||||
@ -140,18 +145,22 @@ func (o *tlsTapperObjects) Close() error {
|
||||
//
|
||||
// It can be passed to loadTlsTapperObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type tlsTapperMaps struct {
|
||||
AcceptSyscallContext *ebpf.Map `ebpf:"accept_syscall_context"`
|
||||
ChunksBuffer *ebpf.Map `ebpf:"chunks_buffer"`
|
||||
ConnectSyscallInfo *ebpf.Map `ebpf:"connect_syscall_info"`
|
||||
FileDescriptorToIpv4 *ebpf.Map `ebpf:"file_descriptor_to_ipv4"`
|
||||
GoReadContext *ebpf.Map `ebpf:"go_read_context"`
|
||||
GoWriteContext *ebpf.Map `ebpf:"go_write_context"`
|
||||
GoidOffsetsMap *ebpf.Map `ebpf:"goid_offsets_map"`
|
||||
Heap *ebpf.Map `ebpf:"heap"`
|
||||
LogBuffer *ebpf.Map `ebpf:"log_buffer"`
|
||||
OpensslReadContext *ebpf.Map `ebpf:"openssl_read_context"`
|
||||
OpensslWriteContext *ebpf.Map `ebpf:"openssl_write_context"`
|
||||
PidsMap *ebpf.Map `ebpf:"pids_map"`
|
||||
AcceptSyscallContext *ebpf.Map `ebpf:"accept_syscall_context"`
|
||||
ChunksBuffer *ebpf.Map `ebpf:"chunks_buffer"`
|
||||
ConnectSyscallInfo *ebpf.Map `ebpf:"connect_syscall_info"`
|
||||
ConnectionContext *ebpf.Map `ebpf:"connection_context"`
|
||||
GoKernelReadContext *ebpf.Map `ebpf:"go_kernel_read_context"`
|
||||
GoKernelWriteContext *ebpf.Map `ebpf:"go_kernel_write_context"`
|
||||
GoReadContext *ebpf.Map `ebpf:"go_read_context"`
|
||||
GoUserKernelReadContext *ebpf.Map `ebpf:"go_user_kernel_read_context"`
|
||||
GoUserKernelWriteContext *ebpf.Map `ebpf:"go_user_kernel_write_context"`
|
||||
GoWriteContext *ebpf.Map `ebpf:"go_write_context"`
|
||||
GoidOffsetsMap *ebpf.Map `ebpf:"goid_offsets_map"`
|
||||
Heap *ebpf.Map `ebpf:"heap"`
|
||||
LogBuffer *ebpf.Map `ebpf:"log_buffer"`
|
||||
OpensslReadContext *ebpf.Map `ebpf:"openssl_read_context"`
|
||||
OpensslWriteContext *ebpf.Map `ebpf:"openssl_write_context"`
|
||||
PidsMap *ebpf.Map `ebpf:"pids_map"`
|
||||
}
|
||||
|
||||
func (m *tlsTapperMaps) Close() error {
|
||||
@ -159,8 +168,12 @@ func (m *tlsTapperMaps) Close() error {
|
||||
m.AcceptSyscallContext,
|
||||
m.ChunksBuffer,
|
||||
m.ConnectSyscallInfo,
|
||||
m.FileDescriptorToIpv4,
|
||||
m.ConnectionContext,
|
||||
m.GoKernelReadContext,
|
||||
m.GoKernelWriteContext,
|
||||
m.GoReadContext,
|
||||
m.GoUserKernelReadContext,
|
||||
m.GoUserKernelWriteContext,
|
||||
m.GoWriteContext,
|
||||
m.GoidOffsetsMap,
|
||||
m.Heap,
|
||||
@ -197,6 +210,8 @@ type tlsTapperPrograms struct {
|
||||
SysEnterWrite *ebpf.Program `ebpf:"sys_enter_write"`
|
||||
SysExitAccept4 *ebpf.Program `ebpf:"sys_exit_accept4"`
|
||||
SysExitConnect *ebpf.Program `ebpf:"sys_exit_connect"`
|
||||
SysExitRead *ebpf.Program `ebpf:"sys_exit_read"`
|
||||
SysExitWrite *ebpf.Program `ebpf:"sys_exit_write"`
|
||||
TcpRecvmsg *ebpf.Program `ebpf:"tcp_recvmsg"`
|
||||
TcpSendmsg *ebpf.Program `ebpf:"tcp_sendmsg"`
|
||||
}
|
||||
@ -225,6 +240,8 @@ func (p *tlsTapperPrograms) Close() error {
|
||||
p.SysEnterWrite,
|
||||
p.SysExitAccept4,
|
||||
p.SysExitConnect,
|
||||
p.SysExitRead,
|
||||
p.SysExitWrite,
|
||||
p.TcpRecvmsg,
|
||||
p.TcpSendmsg,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user