From 55b986d253fcae830d4a5daeaee6b1a784bebef0 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Sun, 9 Jan 2022 22:20:35 -0500 Subject: nettrace --- src/fnettrace/fnettrace.h | 1 + src/fnettrace/hostnames | 17 ++++++- src/fnettrace/hostnames.c | 10 +++++ src/fnettrace/main.c | 112 +++++++++++++++++++++++++++++++++------------- src/fnettrace/radix.c | 20 +++++---- src/fnettrace/radix.h | 1 + 6 files changed, 121 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/fnettrace/fnettrace.h b/src/fnettrace/fnettrace.h index c2f76f3a6..50c538a71 100644 --- a/src/fnettrace/fnettrace.h +++ b/src/fnettrace/fnettrace.h @@ -59,6 +59,7 @@ static inline uint8_t hash(uint32_t ip) { void logprintf(char* fmt, ...); // hostnames.c +extern int geoip_calls; void load_hostnames(const char *fname); char* retrieve_hostname(uint32_t ip); void build_list(const char *fname); diff --git a/src/fnettrace/hostnames b/src/fnettrace/hostnames index b10d9a13d..6b7a19689 100644 --- a/src/fnettrace/hostnames +++ b/src/fnettrace/hostnames @@ -66,7 +66,7 @@ 9.9.9.0/24 Quad9 DNS 45.90.28.0/22 NextDNS 149.112.112.0/24 Quad9 DNS -149.112.120.0/21 CIRA DNS Canada +149.112.120.0/21 CIRA DNS Csnada 176.103.128.0/19 Adguard DNS 185.228.168.0/24 Cleanbrowsing DNS 193.0.0.0/21 whois.ripe.net Netherlands @@ -160,6 +160,21 @@ 108.46.0.0/16 MCI 192.229.128.0/17 MCI +# Microsoft +40.76.0.0/14 Microsoft +40.96.0.0/12 Microsoft +40.112.0.0/13 Microsoft +40.124.0.0/16 Microsoft +40.74.0.0/15 Microsoft +40.80.0.0/12 Microsoft +40.120.0.0/14 Microsoft +40.125.0.0/17 Microsoft +52.145.0.0/16 Microsoft +52.148.0.0/14 Microsoft +52.152.0.0/13 Microsoft +52.146.0.0/15 Microsoft +52.160.0.0/11 Microsoft + # Yahoo 63.250.192.0/19 Yahoo 66.196.64.0/18 Yahoo diff --git a/src/fnettrace/hostnames.c b/src/fnettrace/hostnames.c index e1ad45f81..733d13853 100644 --- a/src/fnettrace/hostnames.c +++ b/src/fnettrace/hostnames.c @@ -21,8 +21,14 @@ #include "radix.h" #define MAXBUF 1024 +int geoip_calls = 0; +static int geoip_not_found = 0; char *retrieve_hostname(uint32_t ip) { + if (geoip_not_found) + return NULL; + geoip_calls++; + char *rv = NULL; char *cmd; if (asprintf(&cmd, "/usr/bin/geoiplookup %d.%d.%d.%d", PRINT_IP(ip)) == -1) @@ -47,6 +53,10 @@ char *retrieve_hostname(uint32_t ip) { fclose(fp); return rv; } + else + geoip_not_found = 1; + + free(cmd); return NULL; } diff --git a/src/fnettrace/main.c b/src/fnettrace/main.c index 804a9cd80..40025590e 100644 --- a/src/fnettrace/main.c +++ b/src/fnettrace/main.c @@ -46,8 +46,6 @@ HNode *htable[HMAX] = {NULL}; // display linked list HNode *dlist = NULL; -static unsigned bwmax = 0; // max bytes received in a display interval - static void hnode_add(uint32_t ip_src, uint32_t ip_dst, uint8_t protocol, uint16_t port_src, uint32_t bytes) { uint8_t h = hash(ip_src); @@ -151,7 +149,7 @@ static char *print_bw(unsigned units) { units = DISPLAY_BW_UNITS ; if (bw_line[units] == NULL) { - char *ptr = malloc(DISPLAY_BW_UNITS + 1); + char *ptr = malloc(DISPLAY_BW_UNITS + 2); if (!ptr) errExit("malloc"); bw_line[units] = ptr; @@ -159,12 +157,44 @@ static char *print_bw(unsigned units) { unsigned i; for (i = 0; i < DISPLAY_BW_UNITS; i++, ptr++) sprintf(ptr, "%s", (i < units)? "*": " "); + sprintf(ptr, "%s", " "); } return bw_line[units]; } -static void hnode_print(void) { +#define LINE_MAX 200 +static inline void adjust_line(char *str, int len, int cols) { + if (len > LINE_MAX) // functions such as snprintf truncate the string, and return the length of the untruncated string + len = LINE_MAX; + if (cols > 4 && len > cols) { + str[cols] = '\0'; + str[cols- 1] = '\n'; + } +} + +#define BWMAX_CNT 8 +static unsigned adjust_bandwidth(unsigned bw) { + static unsigned array[BWMAX_CNT] = {0}; + static int instance = 0; + + array[instance] = bw; + int i; + unsigned sum = 0; + unsigned max = 0; + for ( i = 0; i < BWMAX_CNT; i++) { + sum += array[i]; + max = (max > array[i])? max: array[i]; + } + sum /= BWMAX_CNT; + + if (++instance >= BWMAX_CNT) + instance = 0; + + return (max < (sum / 2))? sum: max; +} + +static void hnode_print(unsigned bw) { assert(!arg_netfilter); ansi_clrscr(); @@ -178,38 +208,47 @@ static void hnode_print(void) { // get terminal size struct winsize sz; - int col = 80; + int cols = 80; if (isatty(STDIN_FILENO)) { if (!ioctl(0, TIOCGWINSZ, &sz)) - col = sz.ws_col; + cols = sz.ws_col; } -#define LINE_MAX 200 + if (cols > LINE_MAX) + cols = LINE_MAX; char line[LINE_MAX + 1]; - if (col > LINE_MAX) - col = LINE_MAX; + + // print stats line + bw = adjust_bandwidth(bw); + char stats[31]; + if (bw > (1024 * 1024 * DISPLAY_INTERVAL)) + sprintf(stats, "%d MB/s ", bw / (1024 * 1024 * DISPLAY_INTERVAL)); + else + sprintf(stats, "%d KB/s ", bw / (1024 * DISPLAY_INTERVAL)); + int len = snprintf(line, LINE_MAX, "%32s geoip %d, IP database %d\n", stats, geoip_calls, radix_nodes); + adjust_line(line, len, cols); + printf("%s", line); HNode *ptr = dlist; HNode *prev = NULL; + int row = 0; while (ptr) { HNode *next = ptr->dnext; if (--ptr->ttl > 0) { char bytes[11]; if (ptr->bytes > (DISPLAY_INTERVAL * 1024 * 1024 * 2)) // > 2 MB/second - sprintf(bytes, "%u MB/s", + snprintf(bytes, 11, "%u MB/s", (unsigned) (ptr->bytes / (DISPLAY_INTERVAL * 1024* 1024))); else if (ptr->bytes > (DISPLAY_INTERVAL * 1024 * 2)) // > 2 KB/second - sprintf(bytes, "%u KB/s", + snprintf(bytes, 11, "%u KB/s", (unsigned) (ptr->bytes / (DISPLAY_INTERVAL * 1024))); else - sprintf(bytes, "%u B/s", (unsigned) (ptr->bytes / DISPLAY_INTERVAL)); + snprintf(bytes, 11, "%u B/s", (unsigned) (ptr->bytes / DISPLAY_INTERVAL)); char *hostname = ptr->hostname; if (!hostname) hostname = radix_find_last(ptr->ip_src); - if (!hostname) hostname = retrieve_hostname(ptr->ip_src); - if (!hostname) hostname = " "; else { @@ -218,16 +257,30 @@ static void hnode_print(void) { errExit("strdup"); } - unsigned bwunit = bwmax / DISPLAY_BW_UNITS; - unsigned units = ptr->bytes / bwunit; - char *bwline = print_bw(units); + unsigned bwunit = bw / DISPLAY_BW_UNITS; + char *bwline; + if (bwunit == 0) + bwline = print_bw(0); + else + bwline = print_bw(ptr->bytes / bwunit); + + char *protocol = ""; + if (ptr->port_src == 80) + protocol = "(HTTP)"; + else if (ptr->port_src == 853) + protocol = "(DoT)"; + else if (ptr->protocol == 0x11) + protocol = "(UDP)"; +/* + else (ptr->port_src == 443) + protocol = "SSL"; + else if (ptr->port_src == 53) + protocol = "DNS"; +*/ - sprintf(line, "%10s %s %d.%d.%d.%d:%u %s\n", bytes, bwline, PRINT_IP(ptr->ip_src), ptr->port_src, hostname); - int len = strlen(line); - if (col > 4 && len > col) { - line[col] = '\0'; - line[col - 1] = '\n'; - } + len = snprintf(line, LINE_MAX, "%10s %s %d.%d.%d.%d:%u%s %s\n", + bytes, bwline, PRINT_IP(ptr->ip_src), ptr->port_src, protocol, hostname); + adjust_line(line, len, cols); printf("%s", line); if (ptr->bytes) @@ -246,6 +299,7 @@ static void hnode_print(void) { ptr = next; } + } static void run_trace(void) { @@ -262,18 +316,16 @@ static void run_trace(void) { unsigned last_print_traces = 0; unsigned last_print_remaining = 0; unsigned char buf[MAX_BUF_SIZE]; - unsigned bwcurrent = 0; + unsigned bw = 0; // bandwidth calculations while (1) { unsigned end = time(NULL); if (arg_netfilter && end - start >= NETLOCK_INTERVAL) break; if (end % DISPLAY_INTERVAL == 1 && last_print_traces != end) { // first print after 1 second - if (bwcurrent > bwmax) - bwmax = bwcurrent; if (!arg_netfilter) - hnode_print(); + hnode_print(bw); last_print_traces = end; - bwcurrent = 0; + bw = 0; } if (arg_netfilter && last_print_remaining != end) { logprintf("."); @@ -300,7 +352,7 @@ static void run_trace(void) { unsigned bytes = recvfrom(sock, buf, MAX_BUF_SIZE, 0, NULL, NULL); if (bytes >= 20) { // size of IP header - bwcurrent += bytes + 14; // assume a 14 byte Ethernet layer + bw += bytes + 14; // assume a 14 byte Ethernet layer // filter out loopback traffic if (buf[12] != 127) { uint32_t ip_src; @@ -486,8 +538,8 @@ static void usage(void) { printf("Options:\n"); printf(" --build=filename - compact list of addresses\n"); printf(" --help, -? - this help screen\n"); + printf(" --log=filename - netlocker logfile\n"); printf(" --netfilter - build the firewall rules and commit them.\n"); - printf(" --log=filename - logfile\n"); printf("\n"); } diff --git a/src/fnettrace/radix.c b/src/fnettrace/radix.c index a1f44dd31..d68aaf85c 100644 --- a/src/fnettrace/radix.c +++ b/src/fnettrace/radix.c @@ -26,6 +26,7 @@ #include "fnettrace.h" RNode *head = 0; +int radix_nodes = 0; static inline RNode *addOne(RNode *ptr, uint32_t ip, uint32_t mask, char *name) { assert(ptr); @@ -34,6 +35,7 @@ static inline RNode *addOne(RNode *ptr, uint32_t ip, uint32_t mask, char *name) RNode *node = malloc(sizeof(RNode)); if (!node) errExit("malloc"); + radix_nodes++; memset(node, 0, sizeof(RNode)); node->ip = ip; node->mask = mask; @@ -42,7 +44,7 @@ static inline RNode *addOne(RNode *ptr, uint32_t ip, uint32_t mask, char *name) if (!node->name) errExit("strdup"); } - + ptr->one = node; return node; } @@ -62,7 +64,7 @@ static inline RNode *addZero(RNode *ptr, uint32_t ip, uint32_t mask, char *name) if (!node->name) errExit("strdup"); } - + ptr->zero = node; return node; } @@ -146,13 +148,13 @@ char *radix_find_last(uint32_t ip) { if (ptr->name) rv = ptr; } - + return (rv)? rv->name: NULL; } static void radix_print_node(RNode *ptr, int level) { assert(ptr); - + int i; for (i = 0; i < level; i++) printf(" "); @@ -173,7 +175,7 @@ void radix_print(void) { printf("radix tree is empty\n"); return; } - + printf("radix IPv4 tree\n"); radix_print_node(head, 0); } @@ -187,14 +189,14 @@ static inline int mask2cidr(uint32_t mask) { if (mask & m) cnt++; } - + return cnt; } static void radix_build_list_node(RNode *ptr) { assert(ptr); - - + + if (ptr->name) { printf("%d.%d.%d.%d/%d %s\n", PRINT_IP(ptr->ip), mask2cidr(ptr->mask), ptr->name); return; @@ -213,6 +215,6 @@ void radix_build_list(void) { return; } - radix_build_list_node(head); + radix_build_list_node(head); } diff --git a/src/fnettrace/radix.h b/src/fnettrace/radix.h index b77c24216..ed7ae0cb7 100644 --- a/src/fnettrace/radix.h +++ b/src/fnettrace/radix.h @@ -28,6 +28,7 @@ typedef struct rnode_t { char *name; } RNode; +extern int radix_nodes; char *radix_find_first(uint32_t ip); char *radix_find_last(uint32_t ip); void radix_add(uint32_t ip, uint32_t mask, char *name); -- cgit v1.2.3-54-g00ecf