From d4fbe5fdace238809e2069c9938d47e6f90f2126 Mon Sep 17 00:00:00 2001 From: gbucchino Date: Wed, 3 Jul 2024 16:22:36 +0200 Subject: [PATCH] First commit --- README.md | 39 + common.h | 11 + ic.c | 325 + ic.h | 22 + load_bpf | Bin 0 -> 16680 bytes load_bpf.c | 75 + main | Bin 0 -> 25056 bytes main.c | 12 + tp_tcp.c | 86 + tp_tcp.o | Bin 0 -> 9360 bytes vmlinux.h | 143501 ++++++++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 144071 insertions(+) create mode 100644 README.md create mode 100644 common.h create mode 100644 ic.c create mode 100644 ic.h create mode 100755 load_bpf create mode 100644 load_bpf.c create mode 100755 main create mode 100644 main.c create mode 100644 tp_tcp.c create mode 100644 tp_tcp.o create mode 100644 vmlinux.h diff --git a/README.md b/README.md new file mode 100644 index 0000000..d001835 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# Introduction +This project collect some metrics for TCP. For doing that, I use eBPF. + +## Requirements +For executing and loading the eBPF program and to send data to InfluxDB, you need to install some packages: + +``` +``` + +## Compile eBPF program +First, you need to dump the vmlinux header file, which contains all definitions codes of your Linux kernel: + +``` +sudo bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h +``` + +After that, you can compile the eBPF code: + +``` +$ clang-11 -g -O2 -target bpf -c tp_tcp.c -o tp_tcp.o +``` + +Now, I made a C script which can load the eBPF program and attach it: + +``` +$ gcc load_bpf.c -o load_bpf -lbpf +``` + +And you can execute it, but, you need to have the root privileges: + +``` +$ sudo ./load_bpf +``` + + +## InfluxDB +I use this [project](https://github.com/nigelargriffiths/InfluxDB-C-client) for sending data to InfluxDB. + +The documentation of that project is [here](https://www.influxdata.com/blog/influxdb-c-client-library-for-capturing-statistics/) diff --git a/common.h b/common.h new file mode 100644 index 0000000..4a963a0 --- /dev/null +++ b/common.h @@ -0,0 +1,11 @@ +#ifndef H_COMMON +#define H_COMMON + +struct reset { + __u8 saddr[4]; + __u8 daddr[4]; + __u16 sport; + __u16 dport; +}; + +#endif diff --git a/ic.c b/ic.c new file mode 100644 index 0000000..860f465 --- /dev/null +++ b/ic.c @@ -0,0 +1,325 @@ +/* + * Influx C (ic) client for data capture + * Developer: Nigel Griffiths. + * (C) Copyright 2021 Nigel Griffiths + + This program is free software: you can redistribute it and/or modify + it under the terms of the gnu general public license as published by + the free software foundation, either version 3 of the license, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but without any warranty; without even the implied warranty of + merchantability or fitness for a particular purpose. see the + gnu general public license for more details. + + You should have received a copy of the gnu general public license + along with this program. if not, see . + + Compile: cc ic.c -g -O3 -o ic + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG if(debug) +#define MEGABYTE ( 1024 * 1024 ) /* USed as the default buffer sizes */ + +int debug = 0; /* 0=off, 1=on basic, 2=trace like output */ + +char influx_hostname[1024 + 1] = { 0 };/* details of the influxdb server or telegraf */ +char influx_ip[16 + 1] = { 0 }; +long influx_port = 0; + +char influx_database[256+1]; /* the influxdb database */ +char influx_username[64+1]; /* optional for influxdb access */ +char influx_password[64+1]; /* optional for influxdb access */ + +char *output; /* all the stats must fit in this buffer */ +long output_size = 0; +long output_char = 0; + +char *influx_tags; /* saved tags for every influxdb line protocol mesurement */ + +int subended = 0; /* stop ic_subend and ic_measureend both enig the measure */ +int first_sub = 0; /* need to remove the ic_measure measure before adding ic_sub measure */ +char saved_section[64]; +char saved_sub[64]; + +int sockfd; /* file desciptor for socket connection */ + +void error(char *buf) +{ + fprintf(stderr, "error: \"%s\" errno=%d meaning=\"%s\"\n", buf, errno, strerror(errno)); + close(sockfd); + sleep(2); /* this can help the socket close cleanly at the remote end */ + exit(1); +} + +void ic_debug(int level) +{ + debug = level; +} + +/* ic_tags() argument is the measurement tags for influddb */ +/* example: "host=vm1234" note:the comma & hostname of the virtual machine sending the data */ +/* complex: "host=lpar42,serialnum=987654,arch=power9" note:the comma separated list */ +void ic_tags(char *t) +{ + DEBUG fprintf(stderr,"ic_tags(%s)\n",t); + if( influx_tags == (char *) 0) { + if( (influx_tags = (char *)malloc(MEGABYTE)) == (char *)-1) + error("failed to malloc() tags buffer"); + } + + strncpy(influx_tags,t,256); +} + +void ic_influx_database(char *host, long port, char *db) /* note: converts influxdb hostname to ip address */ +{ + struct hostent *he; + char errorbuf[1024 +1 ]; + + influx_port = port; + strncpy(influx_database,db,256); + + if(host[0] <= '0' && host[0] <='9') { + DEBUG fprintf(stderr,"ic_influx(ipaddr=%s,port=%ld,database=%s))\n",host,port,db); + strncpy(influx_ip,host,16); + } else { + DEBUG fprintf(stderr,"ic_influx_by_hostname(host=%s,port=%ld,database=%s))\n",host,port,db); + strncpy(influx_hostname,host,1024); + if (isalpha(host[0])) { + + he = gethostbyname(host); + if (he == NULL) { + sprintf(errorbuf, "influx host=%s to ip address convertion failed gethostbyname(), bailing out\n", host); + error(errorbuf); + } + /* this could return multiple ip addresses but we assume its the first one */ + if (he->h_addr_list[0] != NULL) { + strcpy(influx_ip, inet_ntoa(*(struct in_addr *) (he->h_addr_list[0]))); + DEBUG fprintf(stderr,"ic_influx_by_hostname hostname=%s converted to ip address %s))\n",host,influx_ip); + } else { + sprintf(errorbuf, "influx host=%s to ip address convertion failed (empty list), bailing out\n", host); + error(errorbuf); + } + } else { + strcpy( influx_ip, host); /* perhaps the hostname is actually an ip address */ + } + } +} + +void ic_influx_userpw(char *user, char *pw) +{ + DEBUG fprintf(stderr,"ic_influx_userpw(username=%s,pssword=%s))\n",user,pw); + strncpy(influx_username,user,64); + strncpy(influx_password,pw,64); +} + +int create_socket() /* returns 1 for error and 0 for ok */ +{ + int i; + static char buffer[4096]; + static struct sockaddr_in serv_addr; + + if(debug) DEBUG fprintf(stderr, "socket: trying to connect to \"%s\":%ld\n", influx_ip, influx_port); + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + error("socket() call failed"); + return 0; + } + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(influx_ip); + serv_addr.sin_port = htons(influx_port); + + /* connect tot he socket offered by the web server */ + if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { + DEBUG fprintf(stderr, " connect() call failed errno=%d", errno); + return 0; + } + return 1; +} + +void ic_check(long adding) /* Check the buffer space */ +{ + if(output == (char *)0) { /* First time create the buffer * + if( (output = (char *)malloc(MEGABYTE)) == (char *)-1) + error("failed to malloc() output buffer"); + } + if(output_char + (2*adding) > output_size) /* When near the end of the output buffer, extend it*/ + if( (output = (char *)realloc(output, output_size + MEGABYTE)) == (char *)-1) + error("failed to realloc() output buffer"); + } +} + +void remove_ending_comma_if_any() +{ + if (output[output_char - 1] == ',') { + output[output_char - 1] = 0; /* remove the char */ + output_char--; + } +} + +void ic_measure(char *section) +{ + ic_check( strlen(section) + strlen(influx_tags) + 3); + + output_char += sprintf(&output[output_char], "%s,%s ", section, influx_tags); + strcpy(saved_section, section); + first_sub = 1; + subended = 0; + DEBUG fprintf(stderr, "ic_measure(\"%s\") count=%ld\n", section, output_char); +} + +void ic_measureend() +{ + ic_check( 4 ); + remove_ending_comma_if_any(); + if (!subended) { + output_char += sprintf(&output[output_char], " \n"); + } + subended = 0; + DEBUG fprintf(stderr, "ic_measureend()\n"); +} + +/* Note this added a further tag to the measurement of the "resource_name" */ +/* measurement might be "disks" */ +/* sub might be "sda1", "sdb1", etc */ +void ic_sub(char *resource) +{ + int i; + + ic_check( strlen(saved_section) + strlen(influx_tags) +strlen(saved_sub) + strlen(resource) + 9); + + /* remove previously added section */ + if (first_sub) { + for (i = output_char - 1; i > 0; i--) { + if (output[i] == '\n') { + output[i + 1] = 0; + output_char = i + 1; + break; + } + } + } + first_sub = 0; + + /* remove the trailing s */ + strcpy(saved_sub, saved_section); + if (saved_sub[strlen(saved_sub) - 1] == 's') { + saved_sub[strlen(saved_sub) - 1] = 0; + } + output_char += sprintf(&output[output_char], "%s,%s,%s_name=%s ", saved_section, influx_tags, saved_sub, resource); + subended = 0; + DEBUG fprintf(stderr, "ic_sub(\"%s\") count=%ld\n", resource, output_char); +} + +void ic_subend() +{ + ic_check( 4 ); + remove_ending_comma_if_any(); + output_char += sprintf(&output[output_char], " \n"); + subended = 1; + DEBUG fprintf(stderr, "ic_subend()\n"); +} + +void ic_long(char *name, long long value) +{ + ic_check( strlen(name) + 16 + 4 ); + output_char += sprintf(&output[output_char], "%s=%lldi,", name, value); + DEBUG fprintf(stderr, "ic_long(\"%s\",%lld) count=%ld\n", name, value, output_char); +} + +void ic_double(char *name, double value) +{ + ic_check( strlen(name) + 16 + 4 ); + if (isnan(value) || isinf(value)) { /* not-a-number or infinity */ + DEBUG fprintf(stderr, "ic_double(%s,%.1f) - nan error\n", name, value); + } else { + output_char += sprintf(&output[output_char], "%s=%.3f,", name, value); + DEBUG fprintf(stderr, "ic_double(\"%s\",%.1f) count=%ld\n", name, value, output_char); + } +} + +void ic_string(char *name, char *value) +{ + int i; + int len; + + ic_check( strlen(name) + strlen(value) + 4 ); + len = strlen(value); + for (i = 0; i < len; i++) /* replace problem characters and with a space */ + if (value[i] == '\n' || iscntrl(value[i])) + value[i] = ' '; + output_char += sprintf(&output[output_char], "%s=\"%s\",", name, value); + DEBUG fprintf(stderr, "ic_string(\"%s\",\"%s\") count=%ld\n", name, value, output_char); +} + +void ic_push() +{ + char header[1024]; + char result[1024]; + char buffer[1024 * 8]; + int ret; + int i; + int total; + int sent; + int code; + + if (output_char == 0) /* nothing to send so skip this operation */ + return; + if (influx_port) { + DEBUG fprintf(stderr, "ic_push() size=%ld\n", output_char); + if (create_socket() == 1) { + + sprintf(buffer, "POST /write?db=%s&u=%s&p=%s HTTP/1.1\r\nHost: %s:%ld\r\nContent-Length: %ld\r\n\r\n", + influx_database, influx_username, influx_password, influx_hostname, influx_port, output_char); + DEBUG fprintf(stderr, "buffer size=%ld\nbuffer=<%s>\n", strlen(buffer), buffer); + if ((ret = write(sockfd, buffer, strlen(buffer))) != strlen(buffer)) { + fprintf(stderr, "warning: \"write post to sockfd failed.\" errno=%d\n", errno); + } + total = output_char; + sent = 0; + if (debug == 2) + fprintf(stderr, "output size=%d output=\n<%s>\n", total, output); + while (sent < total) { + ret = write(sockfd, &output[sent], total - sent); + DEBUG fprintf(stderr, "written=%d bytes sent=%d total=%d\n", ret, sent, total); + if (ret < 0) { + fprintf(stderr, "warning: \"write body to sockfd failed.\" errno=%d\n", errno); + break; + } + sent = sent + ret; + } + for (i = 0; i < 1024; i++) /* empty the buffer */ + result[i] = 0; + if ((ret = read(sockfd, result, sizeof(result))) > 0) { + result[ret] = 0; + DEBUG fprintf(stderr, "received bytes=%d data=<%s>\n", ret, result); + sscanf(result, "HTTP/1.1 %d", &code); + for (i = 13; i < 1024; i++) + if (result[i] == '\r') + result[i] = 0; + if (debug == 2) + fprintf(stderr, "http-code=%d text=%s [204=Success]\n", code, &result[13]); + if (code != 204) + fprintf(stderr, "code %d -->%s<--\n", code, result); + } + close(sockfd); + sockfd = 0; + DEBUG fprintf(stderr, "ic_push complete\n"); + } else { + DEBUG fprintf(stderr, "socket create failed\n"); + } + } else error("influx port is not set, bailing out"); + + output[0] = 0; + output_char = 0; +} diff --git a/ic.h b/ic.h new file mode 100644 index 0000000..1bc9411 --- /dev/null +++ b/ic.h @@ -0,0 +1,22 @@ +/* + * Influx C (ic) client for data capture header file + * Developer: Nigel Griffiths. + * (C) Copyright 2021 Nigel Griffiths + */ + void ic_influx_database(char *host, long port, char *db); + void ic_influx_userpw(char *user, char *pw); + void ic_tags(char *tags); + + void ic_measure(char *section); + void ic_measureend(); + + void ic_sub(char *sub_name); + void ic_subend(); + + void ic_long(char *name, long long value); + void ic_double(char *name, double value); + void ic_string(char *name, char *value); + + void ic_push(); + void ic_debug(int level); + diff --git a/load_bpf b/load_bpf new file mode 100755 index 0000000000000000000000000000000000000000..05156a03a67b3df481266a4d5e14639b897b0c8a GIT binary patch literal 16680 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 Y9wEnNT{=xYDpIty$<|orG4QbBU)E9{{{R30 literal 0 HcmV?d00001 diff --git a/load_bpf.c b/load_bpf.c new file mode 100644 index 0000000..98d7385 --- /dev/null +++ b/load_bpf.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include "common.h" + +static void clean_obj(struct bpf_object *obj){ + printf("Cleaning\n"); + bpf_object__close(obj); +} +int main(void){ + const char *fileObj = "tp_tcp.o"; + struct bpf_object *obj; + struct bpf_program *program; + struct bpf_map *map; + struct reset s_reset; + int err; + int map_fd; + long long stats; + int keys = 0; + + obj = bpf_object__open_file(fileObj, NULL); + if (!obj){ + printf("Failed to open %s\n", fileObj); + return -1; + } + //LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_MMAPABLE); + map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int), sizeof(struct reset), 4096, BPF_ANY); + printf("Create map: %d\n", map_fd); + + err = bpf_object__load(obj); + printf("Object loaded: %d\n", err); + if (err){ + printf("Failed to load object\n"); + return -1; + } + + program = bpf_object__find_program_by_name(obj, "tcp_retransmit"); + if (!program){ + printf("Failed to find the program\n"); + return -1; + } + + map = bpf_object__find_map_by_name(obj, "tcp_reset_stats"); + if (!map){ + printf("Failed to get the map\n"); + clean_obj(obj); + return -1; + } + + map_fd = bpf_object__find_map_fd_by_name(obj, "tcp_reset_stats"); + printf("Map fd: %d\n", map_fd); + + struct bpf_link *link = bpf_program__attach(program); + if (!link){ + printf("Failed to attach the program\n"); + return -1; + } + + while(1){ + int e = bpf_map_lookup_elem(map_fd, &keys, &s_reset); + if (e == 0){ + //printf("%lld\n", stats); + struct in_addr *src = (struct in_addr*)&s_reset.saddr; + struct in_addr *dest = (struct in_addr*)&s_reset.daddr; + //struct in_addr src = s_reset.saddr; + printf("Sport: %d; dport: %d %s %s\n", s_reset.sport, s_reset.dport, inet_ntoa(*src), inet_ntoa(*dest)); + } + + } + + return 0; +} diff --git a/main b/main new file mode 100755 index 0000000000000000000000000000000000000000..dae00eb455294343cceaad6b9b43a33cf7589a6c GIT binary patch literal 25056 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 literal 0 HcmV?d00001 diff --git a/main.c b/main.c new file mode 100644 index 0000000..ef1f3a0 --- /dev/null +++ b/main.c @@ -0,0 +1,12 @@ +#define BPF_NO_GLOBAL_DATA +#include +#include +#include +#include +#include + +int main(int argc, char *argv[], char *argp[]){ + printf("Hello world\n"); + execve("/usr/bin/ls", argv, argp); + return 0; +} diff --git a/tp_tcp.c b/tp_tcp.c new file mode 100644 index 0000000..9126c54 --- /dev/null +++ b/tp_tcp.c @@ -0,0 +1,86 @@ +#define BPF_NO_GLOBAL_DATA +//#define __TARGET_ARCH_x86 +#include "vmlinux.h" +#include +#include +#include +#include "common.h" + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + + +struct ctx_reset { + __u16 common_type; + __u8 common_flags; + __u8 common_count; + __s32 pid; + + const void *skaddr; + __u16 sport; + __u16 dport; + __u16 family; + __u8 saddr[4]; + __u8 daddr[4]; + __u8 saddr_v6[16]; + __u8 daddr_v6[16]; + __u64 sock_cookie; +}; + +struct { +// __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 4096); + __type(key, int); + __type(value, sizeof(struct reset)); +} tcp_reset_stats SEC(".maps"); + +// sudo tcpdump -i any 'tcp[13] & 4 != 0' -n -> filter TCP reset flags + +/* + * Identify all tracepoint available + * - cat /sys/kernel/tracing/available_events + * Enable an event: + * - echo 'tcp_receive_reset' >> /sys/kernel/tracing/set_event -> important to add the '>>' + * Docs: https://docs.kernel.org/trace/events.html + * https://events.linuxfoundation.org/wp-content/uploads/2022/10/elena-zannoni-tracing-tutorial-LF-2021.pdf + * https://docs.kernel.org/trace/tracepoints.html + * Why we need to detect RST: + * When we scan the port, the scanner send an SYN flag and if the port is block, we receive a RST flag: + * listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes +10:48:28.531295 lo In IP localhost.43961 > localhost.tproxy: Flags [S], seq 2197047013, win 1024, options [mss 1460], length 0 +10:48:28.531306 lo In IP localhost.tproxy > localhost.43961: Flags [R.], seq 0, ack 2197047014, win 0, length 0 + * But we can also block all receive RST: iptables -I INPUT -p tcp --dport -j REJECT --reject-with tcp-reset + */ + +//SEC("tp/tcp_retransmit_synack") +SEC("tracepoint/tcp/tcp_receive_reset") +//int tcp_retransmit(struct sock *sk){ +int tcp_retransmit(struct ctx_reset *ctx){ + long long *stats; + struct reset *s_reset; + int keys = 0; + __u16 sport = 0; + __u16 dport = 0; + + s_reset = bpf_map_lookup_elem(&tcp_reset_stats, &keys); + if (!s_reset) + return 0; + + //*stats += 1; + sport = ctx->sport; + dport = ctx->dport; + s_reset->saddr[0] = ctx->saddr[0]; + s_reset->saddr[1] = ctx->saddr[1]; + s_reset->saddr[2] = ctx->saddr[2]; + s_reset->saddr[3] = ctx->saddr[3]; + /*s_reset->daddr[0] = ctx->daddr[0]; + s_reset->daddr[1] = ctx->daddr[1]; + s_reset->daddr[2] = ctx->daddr[2]; + s_reset->daddr[3] = ctx->daddr[3];*/ + s_reset->sport = sport; + s_reset->dport = dport; + + //bpf_printk("BPF detected TCP received reset %d - %d %d\n", *stats, dport, sport); + bpf_printk("BPF detected TCP received reset %d %d\n", dport, sport); + return 0; +} diff --git a/tp_tcp.o b/tp_tcp.o new file mode 100644 index 0000000000000000000000000000000000000000..ad2c7b000f5624417cecac42ecaab86d32b5c4de GIT binary patch literal 9360 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