diff --git a/Server/Dockerfile b/Server/Dockerfile deleted file mode 100644 index a5efce8..0000000 --- a/Server/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM ubuntu:latest - -RUN apt-get update -y && apt-get install -y nmap diff --git a/exec.sh b/exec.sh index d3705e0..69653c9 100755 --- a/exec.sh +++ b/exec.sh @@ -1,5 +1,5 @@ #!/usr/bin/sh clang-11 -g -O2 -target bpf -c tp_tcp.c -o tp_tcp.o && \ -gcc load_bpf.c -o load_bpf -lbpf && \ -sudo ./load_bpf +gcc ic.c load_bpf.c -o load_bpf -lbpf && \ +sudo ./load_bpf 192.168.1.68 f32d493484526abc _HK7-cwCZuOiaBIFi17J3riUeQ8OeR6oOp9o3QZMNpehdJMTkleR4B7-CczXSzwhx656GMZi3m6h15h59burbg== tcp_metrics diff --git a/ic.c b/ic.c index 860f465..b2a476e 100644 --- a/ic.c +++ b/ic.c @@ -41,6 +41,8 @@ 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 influx_token[128+1]; +char influx_orgID[64+1]; char *output; /* all the stats must fit in this buffer */ long output_size = 0; @@ -117,6 +119,14 @@ void ic_influx_database(char *host, long port, char *db) /* note: converts influ } } +void ic_influx_token(char *token){ + DEBUG fprintf(stderr, "ic_influx_token(token=%s))\n", token); + strncpy(influx_token, token, 128); +} +void ic_influx_orgID(char *orgID){ + DEBUG fprintf(stderr, "ic_influx_orgID(ordID=%s))\n", orgID); + strncpy(influx_orgID, orgID, 64); +} void ic_influx_userpw(char *user, char *pw) { DEBUG fprintf(stderr,"ic_influx_userpw(username=%s,pssword=%s))\n",user,pw); @@ -278,9 +288,8 @@ void ic_push() 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); + sprintf(buffer, "POST /api/v2/write?bucket=%s&orgID=%s HTTP/1.1\r\nHost: %s:%ld\r\nContent-Length: %ld\r\nAuthorization: Token %s\r\n\r\n", + influx_database, influx_orgID, influx_hostname, influx_port, output_char, influx_token); 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); @@ -323,3 +332,30 @@ void ic_push() output[0] = 0; output_char = 0; } +int ic_read(const char *ipsrc, const char *ipdst){ + int value; + int ret; + char buffer[1024 * 8]; + char request[1024]; + char result[1024]; + int len = 0; + + sprintf(request, "from(bucket: \"tcp_metrics\")|> range(start: -1m)|> filter(fn: (r) => r[\"_measurement\"] == \"tcp_reset\")|> filter(fn: (r) => r[\"host\"] == \"%s\")|> filter(fn: (r) => r[\"_field\"] == \"%s\")|> last()", ipsrc, ipdst); + len = strlen(request); + + if (create_socket() == 1) { + sprintf(buffer, "POST /api/v2/query?bucket=%s&orgID=%s HTTP/1.1\r\nHost: %s:%ld\r\nContent-Type: application/vnd.flux\r\nAccept: application/csv\r\nContent-Length: %d\r\nAuthorization: Token %s\r\n\r\n%s", + influx_database, influx_orgID, influx_hostname, influx_port, len, influx_token, request); + DEBUG fprintf(stderr, "buffer size=%ld\nbuffer=<%s>\n", strlen(buffer), buffer); + printf("%s\n", buffer); + if ((ret = write(sockfd, buffer, strlen(buffer))) != strlen(buffer)) { + fprintf(stderr, "warning: \"write post to sockfd failed.\" errno=%d\n", errno); + } + if ((ret = read(sockfd, result, sizeof(result))) > 0) { + printf("%s\n", result); + } + close(sockfd); + sockfd = 0; + } + return value; +} diff --git a/ic.h b/ic.h index 1bc9411..9f6ef86 100644 --- a/ic.h +++ b/ic.h @@ -5,6 +5,8 @@ */ void ic_influx_database(char *host, long port, char *db); void ic_influx_userpw(char *user, char *pw); + void ic_influx_orgID(char *orgID); + void ic_influx_token(char *token); void ic_tags(char *tags); void ic_measure(char *section); @@ -18,5 +20,6 @@ void ic_string(char *name, char *value); void ic_push(); + int ic_read(const char *, const char *); void ic_debug(int level); diff --git a/ic_v1.c b/ic_v1.c new file mode 100644 index 0000000..860f465 --- /dev/null +++ b/ic_v1.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/influxdb.pcap b/influxdb.pcap new file mode 100644 index 0000000..1aecd92 Binary files /dev/null and b/influxdb.pcap differ diff --git a/influxdb.py b/influxdb.py deleted file mode 100644 index 4ba02fe..0000000 --- a/influxdb.py +++ /dev/null @@ -1,24 +0,0 @@ -import influxdb_client -from influxdb_client import InfluxDBClient, Point, WritePrecision -from influxdb_client.client.write_api import SYNCHRONOUS -import os - -#token = os.environ.get("dQV0BbJvy7W9Bool6FGh1ryb_uXBNqZB8BlJqb8yC4yNB8RTDSooT5hixoqMf8cBeXUXTRUdmkwlxnkI9PCsBA==") -token = os.environ.get("sySU58aCfMdTGtBTttduzSS_x_4CBI1twpicYw4Idq9abZWGsAXdbvww2wWmwmLDTtrALAx4Q0wZK9PUIr4ejg==") -org = "gbucchino" -url = "http://192.168.1.68:8086" - -write_client = influxdb_client.InfluxDBClient(url=url, token=token, org=org) - -bucket="tcp" - -write_api = write_client.write_api(write_options=SYNCHRONOUS) - -for value in range(5): - point = ( - Point("measurement1") - .tag("tagname1", "tagvalue1") - .field("field1", value) - ) - write_api.write(bucket=bucket, org="gbucchino", record=point) - time.sleep(1) # separate points by 1 second diff --git a/load_bpf.c b/load_bpf.c index 3fc3453..02770b5 100644 --- a/load_bpf.c +++ b/load_bpf.c @@ -7,12 +7,23 @@ #include "common.h" #include #include +#include "ic.h" + +#define BUF_SIZE 300 +#define BUCKET_SIZE 16 // Bucket size for InfluxDB +#define INFLUXDB_SIZE 64 // Host and ordID size for InfluxDB +#define TOKEN_SIZE 128 // Token size for InfluxDB +#define CNT_ARGS 5 // Number of args + static void clean_obj(struct bpf_object *obj){ printf("Cleaning\n"); bpf_object__close(obj); -} -int main(void){ +} +static void usage(char *app){ + printf("Usage: %s \n", app); +} +int main(int argc, char *argv[]){ const char *fileObj = "tp_tcp.o"; struct bpf_object *obj; struct bpf_program *program; @@ -26,6 +37,26 @@ int main(void){ int keys = 0; int indexPackets = 0; int index = 0; + char buf[BUF_SIZE]; + char host[INFLUXDB_SIZE]; + char orgID[INFLUXDB_SIZE]; + char token[TOKEN_SIZE]; + char bucket[BUCKET_SIZE]; + + if (argc < CNT_ARGS){ + usage(argv[0]); + return -1; + } + + strncpy(host, argv[1], INFLUXDB_SIZE); + strncpy(orgID, argv[2], INFLUXDB_SIZE); + strncpy(token, argv[3], TOKEN_SIZE); + strncpy(bucket, argv[4], BUCKET_SIZE); + + // Connect to InfluxDB + ic_influx_database(host, 8086, bucket); + ic_influx_orgID(orgID); + ic_influx_token(token); obj = bpf_object__open_file(fileObj, NULL); if (!obj){ @@ -93,12 +124,8 @@ int main(void){ __s16 f = AF_INET; err = bpf_map_update_elem(map_fd_filter_family, &keys, &f, BPF_ANY); - printf("Waiting for new packets\n"); while(1){ - // Get the index - // and we compare with the local variable - // If it's different, we get the new variable err = bpf_map_lookup_elem(map_fd_index, &keys, &indexPackets); // We have a new packet @@ -110,15 +137,29 @@ int main(void){ struct in_addr *src = (struct in_addr*)&s_reset.saddr; struct in_addr *dest = (struct in_addr*)&s_reset.daddr; char *s = inet_ntoa(*src); + char *d; char tmp[35]; + int lastValue; memcpy(tmp, s, 35); - char *d = inet_ntoa(*dest); + d = inet_ntoa(*dest); printf("Sport: %d; dport: %d %d %d %s - %s\n", s_reset.sport, s_reset.dport, s_reset.family, s_reset.proto, tmp, d); + // Get the last value from InfluxDB + lastValue = ic_read(s, d); + + // Send data to InfluxDB + snprintf(buf, BUF_SIZE, "host=%s", s); + ic_tags(buf); + + ic_measure("tcp_reset"); + ic_long(d, 1); + ic_measureend(); + ic_push(); + + memset(buf, 0, BUF_SIZE); } memset(&s_reset, 0, sizeof(struct reset)); - //sleep(1); } } diff --git a/main b/main deleted file mode 100755 index 1653d84..0000000 Binary files a/main and /dev/null differ diff --git a/main.c b/main.c deleted file mode 100644 index 8821e46..0000000 --- a/main.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include "ic.h" - -int main(int argc, char *argv[], char *argp[]){ - char buf[300]; - char host[64]; - char account[64]; - char pwd[64]; - - if (argc < 3){ - printf("Usage: ./main "); - return 0; - } - - memcpy(host, argv[1], 64); - memcpy(account, argv[2], 64); - memcpy(pwd, argv[3], 64); - printf("Host: %s\n", host); - printf("Account: %s\n", account); - printf("Pwd: %s\n", pwd); - - ic_influx_database(host, 8086, "tcp"); - ic_influx_userpw(account, pwd); - ic_debug(2); - - snprintf(buf, 300, "host=%s", host); - ic_tags(buf); - - ic_measure("tcp_reset"); - - ic_string("ipsrc", "192.168.1.1"); - - ic_measureend(); - ic_push(); - - return 0; -} diff --git a/prometheus.py b/prometheus.py deleted file mode 100644 index c5e6eee..0000000 --- a/prometheus.py +++ /dev/null @@ -1,30 +0,0 @@ -from prometheus_client import start_http_server, Summary, Counter -import random -import time - -# Create a metric to track time spent and requests made. -#REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing request', 'foo') -#REQUEST_TIME = Summary('request_processing_seconds', 'foo') - - -# Decorate function with metric. -#@REQUEST_TIME.time() -#def process_request(t): -# """A dummy function that takes some time.""" -# time.sleep(t) - -c = Counter("tcp_reset_stats", "TCP RST stats") -def tcp_rst_stats(): - c.inc() - -if __name__ == '__main__': - # Start up the server to expose the metrics. - start_http_server(8000) - # Generate some requests. - while True: - # process_request(random.random()) - - # Count - print("Inc") - tcp_rst_stats() - time.sleep(30) diff --git a/tests/main b/tests/main new file mode 100755 index 0000000..c579cf5 Binary files /dev/null and b/tests/main differ diff --git a/tests/main.c b/tests/main.c new file mode 100644 index 0000000..5a9b353 --- /dev/null +++ b/tests/main.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include "ic.h" + +int main(int argc, char *argv[], char *argp[]){ + char buf[300]; + char host[64]; + char orgID[64]; + char token[128]; + int stats = 0; + + if (argc < 3){ + printf("Usage: ./main "); + return 0; + } + printf("%s %s %s\n", argv[1], argv[2], argv[3]); + memcpy(host, argv[1], 64); + memcpy(orgID, argv[2], 64); + memcpy(token, argv[3], 128); + printf("Host: %s\n", host); + printf("orgID: %s\n", orgID); + printf("Token: %s\n", token); + + ic_influx_database(host, 8086, "tcp_metrics"); + ic_influx_orgID(orgID); + ic_influx_token(token); + ic_debug(2); + + while(1){ + snprintf(buf, 300, "host=%s", host); + ic_tags(buf); + + ic_measure("tcp_reset"); + + stats += 1; + + ic_measureend(); + ic_push(); + sleep(30); + } + + return 0; +} diff --git a/main.py b/tests/main.py similarity index 100% rename from main.py rename to tests/main.py diff --git a/tests/read.sh b/tests/read.sh new file mode 100755 index 0000000..2eb9b4a --- /dev/null +++ b/tests/read.sh @@ -0,0 +1,13 @@ +#!/usr/bin/bash + +curl -i -X POST "http://192.168.1.68:8086/api/v2/query?bucket=tcp_metrics&orgID=f32d493484526abc" \ + --header "Authorization: Token $1" \ + --header "Accept: application/csv" \ + --header "Content-Type: application/vnd.flux" \ + --data 'from(bucket: "tcp_metrics")|> range(start: -1m)|> filter(fn: (r) => r["_measurement"] == "tcp_reset")|> filter(fn: (r) => r["host"] == "127.0.0.1")|> filter(fn: (r) => r["_field"] == "127.0.0.1")|> last()' +# --data 'from(bucket: "tcp_metrics") +# |> range(start: -5m) +# |> filter(fn: (r) => r["_measurement"] == "tcp_reset") +# |> filter(fn: (r) => r["host"] == "127.0.0.1") +# |> filter(fn: (r) => r["_field"] == "127.0.0.1") +# |> yield(name: "mean")' diff --git a/write.sh b/tests/write.sh similarity index 100% rename from write.sh rename to tests/write.sh diff --git a/tp_tcp_py.c b/tp_tcp_py.c deleted file mode 100644 index bcc1143..0000000 --- a/tp_tcp_py.c +++ /dev/null @@ -1,149 +0,0 @@ -#define BPF_NO_GLOBAL_DATA -//#define __TARGET_ARCH_x86 -#include "vmlinux.h" -#include -#include -#include -#include -#include "common.h" - -char LICENSE[] SEC("license") = "Dual BSD/GPL"; - - -struct ctx_receive_reset { - __u16 common_type; // unsigned short - __u8 common_flags; // unsigned char - __u8 common_count; // unsigned char - __s32 pid; // int - - 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 ctx_send_reset { - __u16 common_type; // unsigned short - __u8 common_flags; // unsigned char - __u8 common_count; // unsigned char - __s32 pid; // int - - const void *skbaddr; - const void *skaddr; - __s32 state; // int - __u16 sport; - __u16 dport; - __u8 saddr[4]; - __u8 daddr[4]; - __u8 saddr_v6[16]; - __u8 daddr_v6[16]; -}; - -struct { - __uint(type, BPF_MAP_TYPE_ARRAY); - __uint(max_entries, 4096); - __type(key, 1); - __type(value, __s32); -} tcp_stats_index SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_ARRAY); - __uint(max_entries, 4096); - __type(key, 4); - __type(value, struct reset); -} tcp_reset_stats SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_ARRAY); - __uint(max_entries, 1); - __type(key, __s32); - __type(value, __u16); -} filter_family SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_ARRAY); - __uint(max_entries, 1); - __type(key, __s32); - __type(value, __u16); -} filter_sport SEC(".maps"); - -// sudo tcpdump -i any 'tcp[13] & 4 != 0' -n -> filter TCP reset flags - -/* - * This project do not trace any sniffing ports, because, the tracepoint tcp:tcp_send_reset - * works only for an establish socket, but, if you have a lot of TCP RST, you can have - * an issue with your system - */ - -/* - * 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") -//SEC("tracepoint/tcp/tcp_send_reset") -int tcp_retransmit(struct ctx_send_reset *ctx){ - struct reset s_reset = {}; - int *index; - int keys = 0; - struct sock *sk; - __u16 family; - __s16 *f_family; - __u16 proto; - int err; - - memset(&s_reset, 0, sizeof(struct reset)); - - // Get filter - sk = (struct sock*)ctx->skaddr; - f_family = bpf_map_lookup_elem(&filter_family, &keys); - if (!f_family) - return 0; - - index = bpf_map_lookup_elem(&tcp_stats_index, &keys); - if (!index) - return 0; - - - // Get the family of the socket - bpf_probe_read_kernel(&family, sizeof(family), &sk->__sk_common.skc_family); - if (family != *f_family) - return 0; - - // Get and update the index in the map - *index += 1; - - // Proto type: here it's 6 (TCP) - bpf_probe_read_kernel(&proto, sizeof(proto), &sk->sk_protocol); - - memcpy(s_reset.saddr, ctx->saddr, 4); - memcpy(s_reset.daddr, ctx->daddr, 4); - - //bpf_probe_read_kernel(&s_reset.saddr, 4, &ctx->saddr); - //bpf_probe_read_kernel(&s_reset.daddr, 4, &ctx->daddr); - - s_reset.sport = ctx->sport; - s_reset.dport = ctx->dport; - s_reset.family = family; - s_reset.proto = proto; - - bpf_printk("BPF detected TCP send reset %d %d", s_reset.sport, s_reset.dport); - bpf_map_update_elem(&tcp_reset_stats, &keys, &s_reset, BPF_ANY); - return 0; -}