diff options
author | 2023-08-08 16:27:18 -0400 | |
---|---|---|
committer | 2023-08-08 16:27:18 -0400 | |
commit | c4962789fc88e349a0c6a6c51af4a7cfc09fcc99 (patch) | |
tree | 83e69a67a17f9962846175e3f5cd0856d5e50de0 /src | |
parent | Merge branch 'master' of ssh://github.com/netblue30/firejail (diff) | |
download | firejail-c4962789f.tar.gz firejail-c4962789f.tar.zst firejail-c4962789f.zip |
nettrace stats
Diffstat (limited to 'src')
-rw-r--r-- | src/fnettrace-dns/main.c | 2 | ||||
-rw-r--r-- | src/fnettrace-sni/main.c | 16 | ||||
-rw-r--r-- | src/fnettrace/event.c | 105 | ||||
-rw-r--r-- | src/fnettrace/fnettrace.h | 28 | ||||
-rw-r--r-- | src/fnettrace/main.c | 244 | ||||
-rw-r--r-- | src/fnettrace/radix.c | 40 | ||||
-rw-r--r-- | src/fnettrace/radix.h | 3 | ||||
-rw-r--r-- | src/fnettrace/static-ip-map.txt | 19 |
8 files changed, 335 insertions, 122 deletions
diff --git a/src/fnettrace-dns/main.c b/src/fnettrace-dns/main.c index 6324a17db..38222fe2e 100644 --- a/src/fnettrace-dns/main.c +++ b/src/fnettrace-dns/main.c | |||
@@ -66,7 +66,7 @@ void print_dns(uint32_t ip_src, unsigned char *pkt) { | |||
66 | 66 | ||
67 | // filter output | 67 | // filter output |
68 | char tmp[sizeof(last)]; | 68 | char tmp[sizeof(last)]; |
69 | snprintf(tmp, sizeof(last), "%02d:%02d:%02d %-15s %s (type %u)%s", | 69 | snprintf(tmp, sizeof(last), "%02d:%02d:%02d %-15s DNS %s (type %u)%s", |
70 | t->tm_hour, t->tm_min, t->tm_sec, ip, pkt + 12 + 1, | 70 | t->tm_hour, t->tm_min, t->tm_sec, ip, pkt + 12 + 1, |
71 | type, (nxdomain)? " NXDOMAIN": ""); | 71 | type, (nxdomain)? " NXDOMAIN": ""); |
72 | if (strcmp(tmp, last)) { | 72 | if (strcmp(tmp, last)) { |
diff --git a/src/fnettrace-sni/main.c b/src/fnettrace-sni/main.c index d4fbf703a..d0a4f115a 100644 --- a/src/fnettrace-sni/main.c +++ b/src/fnettrace-sni/main.c | |||
@@ -32,16 +32,15 @@ static char last[512] = {'\0'}; | |||
32 | static void print_tls(uint32_t ip_dest, unsigned char *pkt, unsigned len) { | 32 | static void print_tls(uint32_t ip_dest, unsigned char *pkt, unsigned len) { |
33 | assert(pkt); | 33 | assert(pkt); |
34 | 34 | ||
35 | // expecting a handshake packet and client hello | ||
36 | if (pkt[0] != 0x16 || pkt[5] != 0x01) | ||
37 | return; | ||
38 | |||
35 | char ip[30]; | 39 | char ip[30]; |
36 | sprintf(ip, "%d.%d.%d.%d", PRINT_IP(ip_dest)); | 40 | sprintf(ip, "%d.%d.%d.%d", PRINT_IP(ip_dest)); |
37 | time_t seconds = time(NULL); | 41 | time_t seconds = time(NULL); |
38 | struct tm *t = localtime(&seconds); | 42 | struct tm *t = localtime(&seconds); |
39 | 43 | ||
40 | // expecting a handshake packet and client hello | ||
41 | if (pkt[0] != 0x16 || pkt[5] != 0x01) | ||
42 | goto errout; | ||
43 | |||
44 | |||
45 | // look for server name indication | 44 | // look for server name indication |
46 | unsigned char *ptr = pkt; | 45 | unsigned char *ptr = pkt; |
47 | unsigned int i = 0; | 46 | unsigned int i = 0; |
@@ -74,7 +73,7 @@ static void print_tls(uint32_t ip_dest, unsigned char *pkt, unsigned len) { | |||
74 | if (name) { | 73 | if (name) { |
75 | // filter output | 74 | // filter output |
76 | char tmp[sizeof(last)]; | 75 | char tmp[sizeof(last)]; |
77 | snprintf(tmp, sizeof(last), "%02d:%02d:%02d %-15s %s", t->tm_hour, t->tm_min, t->tm_sec, ip, name); | 76 | snprintf(tmp, sizeof(last), "%02d:%02d:%02d %-15s SNI %s", t->tm_hour, t->tm_min, t->tm_sec, ip, name); |
78 | if (strcmp(tmp, last)) { | 77 | if (strcmp(tmp, last)) { |
79 | printf("%s\n", tmp); | 78 | printf("%s\n", tmp); |
80 | fflush(0); | 79 | fflush(0); |
@@ -85,11 +84,6 @@ static void print_tls(uint32_t ip_dest, unsigned char *pkt, unsigned len) { | |||
85 | goto nosni; | 84 | goto nosni; |
86 | return; | 85 | return; |
87 | 86 | ||
88 | errout: | ||
89 | printf("%02d:%02d:%02d %-15s Error: invalid TLS packet\n", t->tm_hour, t->tm_min, t->tm_sec, ip); | ||
90 | fflush(0); | ||
91 | return; | ||
92 | |||
93 | nosni: | 87 | nosni: |
94 | printf("%02d:%02d:%02d %-15s no SNI\n", t->tm_hour, t->tm_min, t->tm_sec, ip); | 88 | printf("%02d:%02d:%02d %-15s no SNI\n", t->tm_hour, t->tm_min, t->tm_sec, ip); |
95 | return; | 89 | return; |
diff --git a/src/fnettrace/event.c b/src/fnettrace/event.c new file mode 100644 index 000000000..f4ccf5360 --- /dev/null +++ b/src/fnettrace/event.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2023 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include "fnettrace.h" | ||
21 | |||
22 | typedef struct event_t { | ||
23 | struct event_t *next; | ||
24 | char *record; | ||
25 | } Event; | ||
26 | |||
27 | static Event *event = NULL; | ||
28 | static Event *last_event = NULL; | ||
29 | int ev_cnt = 0; | ||
30 | |||
31 | void ev_clear(void) { | ||
32 | ev_cnt = 0; | ||
33 | Event *ev = event; | ||
34 | while (ev) { | ||
35 | Event *next = ev->next; | ||
36 | free(ev->record); | ||
37 | free(ev); | ||
38 | ev = next; | ||
39 | } | ||
40 | event = NULL; | ||
41 | } | ||
42 | |||
43 | void ev_add(char *record) { | ||
44 | assert(record); | ||
45 | |||
46 | // braking recursivity | ||
47 | if (*record == '\0') | ||
48 | return; | ||
49 | |||
50 | char *ptr = strchr(record, '\n'); | ||
51 | if (ptr) | ||
52 | *ptr = '\0'; | ||
53 | |||
54 | // filter out duplicates | ||
55 | if (event && strcmp(event->record, record) == 0) | ||
56 | return; | ||
57 | |||
58 | Event *ev = malloc(sizeof(Event)); | ||
59 | if (!ev) | ||
60 | errExit("malloc"); | ||
61 | memset(ev, 0, sizeof(Event)); | ||
62 | |||
63 | ev->record = strdup(record); | ||
64 | if (!ev->record) | ||
65 | errExit("strdup"); | ||
66 | |||
67 | if (event == NULL) { | ||
68 | event = ev; | ||
69 | last_event = ev; | ||
70 | } | ||
71 | else { | ||
72 | last_event->next = ev; | ||
73 | last_event = ev; | ||
74 | } | ||
75 | ev_cnt++; | ||
76 | |||
77 | // recursivity | ||
78 | if (ptr) | ||
79 | ev_add(++ptr); | ||
80 | } | ||
81 | |||
82 | void ev_print(FILE *fp) { | ||
83 | assert(fp); | ||
84 | |||
85 | Event *ev = event; | ||
86 | while (ev) { | ||
87 | fprintf(fp, " "); | ||
88 | if (strstr(ev->record, "NXDOMAIN")) { | ||
89 | if (fp == stdout) | ||
90 | ansi_red(ev->record); | ||
91 | else | ||
92 | fprintf(fp, "%s", ev->record); | ||
93 | } | ||
94 | else if (strstr(ev->record, "SSH connection")) { | ||
95 | if (fp == stdout) | ||
96 | ansi_red(ev->record); | ||
97 | else | ||
98 | fprintf(fp, "%s", ev->record); | ||
99 | } | ||
100 | else | ||
101 | fprintf(fp, "%s", ev->record); | ||
102 | fprintf(fp, "\n"); | ||
103 | ev = ev->next; | ||
104 | } | ||
105 | } | ||
diff --git a/src/fnettrace/fnettrace.h b/src/fnettrace/fnettrace.h index b4a8f26c7..9b4973235 100644 --- a/src/fnettrace/fnettrace.h +++ b/src/fnettrace/fnettrace.h | |||
@@ -53,6 +53,27 @@ static inline void ansi_clrscr(void) { | |||
53 | fflush(0); | 53 | fflush(0); |
54 | } | 54 | } |
55 | 55 | ||
56 | static inline void ansi_bold(const char *str) { | ||
57 | char str1[] = {0x1b, '[', '1', 'm', '\0'}; | ||
58 | char str2[] = {0x1b, '[', '0', 'm', '\0'}; | ||
59 | printf("%s%s%s", str1, str, str2); | ||
60 | fflush(0); | ||
61 | } | ||
62 | |||
63 | static inline void ansi_faint(const char *str) { | ||
64 | char str1[] = {0x1b, '[', '2', 'm', '\0'}; | ||
65 | char str2[] = {0x1b, '[', '0', 'm', '\0'}; | ||
66 | printf("%s%s%s", str1, str, str2); | ||
67 | fflush(0); | ||
68 | } | ||
69 | |||
70 | static inline void ansi_red(const char *str) { | ||
71 | char str1[] = {0x1b, '[', '9', '1', 'm', '\0'}; | ||
72 | char str2[] = {0x1b, '[', '0', 'm', '\0'}; | ||
73 | printf("%s%s%s", str1, str, str2); | ||
74 | fflush(0); | ||
75 | } | ||
76 | |||
56 | static inline uint8_t hash(uint32_t ip) { | 77 | static inline uint8_t hash(uint32_t ip) { |
57 | uint8_t *ptr = (uint8_t *) &ip; | 78 | uint8_t *ptr = (uint8_t *) &ip; |
58 | // simple byte xor | 79 | // simple byte xor |
@@ -78,4 +99,11 @@ void terminal_restore(void); | |||
78 | // runprog.c | 99 | // runprog.c |
79 | int runprog(const char *program); | 100 | int runprog(const char *program); |
80 | 101 | ||
102 | // event.c | ||
103 | extern int ev_cnt; | ||
104 | void ev_clear(void); | ||
105 | void ev_add(char *record); | ||
106 | void ev_print(FILE *fp); | ||
107 | |||
108 | |||
81 | #endif | 109 | #endif |
diff --git a/src/fnettrace/main.c b/src/fnettrace/main.c index 3bafd9090..a1e46f307 100644 --- a/src/fnettrace/main.c +++ b/src/fnettrace/main.c | |||
@@ -27,6 +27,12 @@ | |||
27 | 27 | ||
28 | static char *arg_log = NULL; | 28 | static char *arg_log = NULL; |
29 | 29 | ||
30 | // only 0 or negative values; postive values as defiend in RFCsq | ||
31 | #define PROTOCOL_ICMP 0 | ||
32 | #define PROTOCOL_SSH -1 | ||
33 | |||
34 | |||
35 | |||
30 | //***************************************************************** | 36 | //***************************************************************** |
31 | // packet stats | 37 | // packet stats |
32 | //***************************************************************** | 38 | //***************************************************************** |
@@ -42,41 +48,18 @@ uint32_t stats_tor = 0; | |||
42 | uint32_t stats_http = 0; | 48 | uint32_t stats_http = 0; |
43 | uint32_t stats_ssh = 0; | 49 | uint32_t stats_ssh = 0; |
44 | 50 | ||
45 | //***************************************************************** | 51 | static void clear_stats(void) { |
46 | // sni/dns log storage | 52 | stats_pkts = 0; |
47 | //***************************************************************** | 53 | stats_icmp_echo = 0; |
48 | typedef struct lognode_t { | 54 | stats_dns = 0; |
49 | #define LOG_RECORD_LEN 255 | 55 | stats_dns_dot = 0; |
50 | char record[LOG_RECORD_LEN + 1]; | 56 | stats_dns_doh = 0; |
51 | } LogNode; | 57 | stats_dns_doq = 0; |
52 | // circular list of SNI log records | 58 | stats_tls = 0; |
53 | #define SNIMAX 64 | 59 | stats_quic = 0; |
54 | LogNode sni_table[SNIMAX] = {0}; | 60 | stats_tor = 0; |
55 | int sni_index = 0; | 61 | stats_http = 0; |
56 | 62 | stats_ssh = 0; | |
57 | // circular list of SNI log records | ||
58 | #define DNSMAX 64 | ||
59 | LogNode dns_table[SNIMAX] = {0}; | ||
60 | int dns_index = 0; | ||
61 | |||
62 | static void print_sni(void) { | ||
63 | int i; | ||
64 | for (i = sni_index; i < SNIMAX; i++) | ||
65 | if (*sni_table[i].record) | ||
66 | printf(" %s", sni_table[i].record); | ||
67 | for (i = 0; i < sni_index; i++) | ||
68 | if (*sni_table[i].record) | ||
69 | printf(" %s", sni_table[i].record); | ||
70 | } | ||
71 | |||
72 | static void print_dns(void) { | ||
73 | int i; | ||
74 | for (i = dns_index; i < DNSMAX; i++) | ||
75 | if (*dns_table[i].record) | ||
76 | printf(" %s", dns_table[i].record); | ||
77 | for (i = 0; i < dns_index; i++) | ||
78 | if (*dns_table[i].record) | ||
79 | printf(" %s", dns_table[i].record); | ||
80 | } | 63 | } |
81 | 64 | ||
82 | //***************************************************************** | 65 | //***************************************************************** |
@@ -92,7 +75,7 @@ typedef struct hnode_t { | |||
92 | uint32_t bytes; // number of bytes received in the last display interval | 75 | uint32_t bytes; // number of bytes received in the last display interval |
93 | uint32_t pkts; // number of packets received in the last display interval | 76 | uint32_t pkts; // number of packets received in the last display interval |
94 | uint16_t port_src; | 77 | uint16_t port_src; |
95 | uint8_t protocol; | 78 | int protocol; |
96 | 79 | ||
97 | // the firewall is build based on source address, and in the linked list | 80 | // the firewall is build based on source address, and in the linked list |
98 | // we could have elements with the same address but different ports | 81 | // we could have elements with the same address but different ports |
@@ -135,7 +118,7 @@ void hfree(HNode *ptr) { | |||
135 | } | 118 | } |
136 | 119 | ||
137 | // using protocol 0 and port 0 for ICMP | 120 | // using protocol 0 and port 0 for ICMP |
138 | static void hnode_add(uint32_t ip_src, uint8_t protocol, uint16_t port_src, uint32_t bytes) { | 121 | static void hnode_add(uint32_t ip_src, int protocol, uint16_t port_src, uint32_t bytes) { |
139 | uint8_t h = hash(ip_src); | 122 | uint8_t h = hash(ip_src); |
140 | 123 | ||
141 | // find | 124 | // find |
@@ -383,7 +366,9 @@ static void hnode_print(unsigned bw) { | |||
383 | else | 366 | else |
384 | sprintf(stats, "%u KB/s ", bw / (1024 * DISPLAY_INTERVAL)); | 367 | sprintf(stats, "%u KB/s ", bw / (1024 * DISPLAY_INTERVAL)); |
385 | // int len = snprintf(line, LINE_MAX, "%32s geoip %d, IP database %d\n", stats, geoip_calls, radix_nodes); | 368 | // int len = snprintf(line, LINE_MAX, "%32s geoip %d, IP database %d\n", stats, geoip_calls, radix_nodes); |
386 | int len = snprintf(line, LINE_MAX, "%32s address:port (protocol) network\n", stats); | 369 | char faint1[] = {0x1b, '[', '2', 'm', '\0'}; |
370 | char faint2[] = {0x1b, '[', '0', 'm', '\0'}; | ||
371 | int len = snprintf(line, LINE_MAX, "%32s %saddress:port (protocol) network%s\n", stats, faint1, faint2); | ||
387 | adjust_line(line, len, cols); | 372 | adjust_line(line, len, cols); |
388 | printf("%s", line); | 373 | printf("%s", line); |
389 | 374 | ||
@@ -461,10 +446,14 @@ static void hnode_print(unsigned bw) { | |||
461 | protocol = "UDP"; | 446 | protocol = "UDP"; |
462 | else if (ptr->protocol == 0x06) | 447 | else if (ptr->protocol == 0x06) |
463 | protocol = "TCP"; | 448 | protocol = "TCP"; |
449 | else if (ptr->protocol == PROTOCOL_SSH) { | ||
450 | protocol = "SSH"; | ||
451 | stats_ssh += ptr->pkts; | ||
452 | } | ||
464 | 453 | ||
465 | if (protocol == NULL) | 454 | if (protocol == NULL) |
466 | protocol = ""; | 455 | protocol = ""; |
467 | if (ptr->port_src == 0) | 456 | if (ptr->port_src == PROTOCOL_ICMP) |
468 | len = snprintf(line, LINE_MAX, "%10s %s %d.%d.%d.%d (ICMP) %s\n", | 457 | len = snprintf(line, LINE_MAX, "%10s %s %d.%d.%d.%d (ICMP) %s\n", |
469 | bytes, bwline, PRINT_IP(ptr->ip_src), ptr->rnode->name); | 458 | bytes, bwline, PRINT_IP(ptr->ip_src), ptr->rnode->name); |
470 | else | 459 | else |
@@ -490,7 +479,7 @@ static void hnode_print(unsigned bw) { | |||
490 | 479 | ||
491 | ptr = next; | 480 | ptr = next; |
492 | } | 481 | } |
493 | printf("press any key to access stats\n"); | 482 | ansi_faint("(D)isplay, (S)ave, (C)lear, e(X)it\n"); |
494 | 483 | ||
495 | #ifdef DEBUG | 484 | #ifdef DEBUG |
496 | { | 485 | { |
@@ -505,10 +494,34 @@ static void hnode_print(unsigned bw) { | |||
505 | #endif | 494 | #endif |
506 | } | 495 | } |
507 | 496 | ||
497 | static void print_stats(FILE *fp) { | ||
498 | assert(fp); | ||
499 | |||
500 | fprintf(fp, "Stats: %u packets\n", stats_pkts); | ||
501 | fprintf(fp, " encrypted: TLS %u, QUIC %u, Tor %u\n", | ||
502 | stats_tls, stats_quic, stats_tor); | ||
503 | fprintf(fp, " unencrypted: HTTP %u\n", stats_http); | ||
504 | fprintf(fp, " C&C backchannel: SSH %u, PING %u, DNS %u, DoH %u, DoT %u, DoQ %u\n", | ||
505 | stats_ssh, stats_icmp_echo, stats_dns, stats_dns_doh, stats_dns_dot, stats_dns_doq); | ||
506 | |||
507 | fprintf(fp, "\n\nIP map"); | ||
508 | if (fp == stdout) | ||
509 | ansi_faint(" - server-address network (packets)\n"); | ||
510 | else | ||
511 | fprintf(fp, " - server-address network (packets)\n"); | ||
512 | radix_print(fp, 1); | ||
513 | |||
514 | fprintf(fp, "\n\nEvents %d", ev_cnt); | ||
515 | if (fp == stdout) | ||
516 | ansi_faint(" - time address:port data\n"); | ||
517 | else | ||
518 | fprintf(fp, " - time address:port data\n"); | ||
519 | ev_print(fp); | ||
508 | 520 | ||
509 | void print_stats(void) { | ||
510 | } | 521 | } |
511 | 522 | ||
523 | |||
524 | |||
512 | // trace rx traffic coming in | 525 | // trace rx traffic coming in |
513 | static void run_trace(void) { | 526 | static void run_trace(void) { |
514 | // trace only rx ipv4 tcp and upd | 527 | // trace only rx ipv4 tcp and upd |
@@ -523,7 +536,7 @@ static void run_trace(void) { | |||
523 | if (p1 != -1) | 536 | if (p1 != -1) |
524 | printf("loading snitrace..."); | 537 | printf("loading snitrace..."); |
525 | 538 | ||
526 | int p2 = runprog(LIBDIR "/firejail/fnettrace-dns --nolocal"); | 539 | int p2 = runprog(LIBDIR "/firejail/fnettrace-dns"); |
527 | if (p2 != -1) | 540 | if (p2 != -1) |
528 | printf("loading dnstrace..."); | 541 | printf("loading dnstrace..."); |
529 | unsigned last_print_traces = 0; | 542 | unsigned last_print_traces = 0; |
@@ -575,40 +588,67 @@ static void run_trace(void) { | |||
575 | int icmp = 0; | 588 | int icmp = 0; |
576 | 589 | ||
577 | if (FD_ISSET(0, &rfds)) { | 590 | if (FD_ISSET(0, &rfds)) { |
578 | getchar(); | 591 | int c = getchar(); |
579 | printf("\n\nStats: %u packets\n", stats_pkts); | 592 | if (c == 'c' || c == 'C') { |
580 | printf(" encrypted: TLS %u, QUIC %u, SSH %u, Tor %u\n", | 593 | clear_stats(); |
581 | stats_tls, stats_quic, stats_ssh, stats_tor); | 594 | ev_clear(); |
582 | printf(" unencrypted: HTTP %u\n", stats_http); | 595 | radix_clear_data(); |
583 | printf(" C&C backchannel: PING %u, DNS %u, DoH %u, DoT %u, DoQ %u\n", | 596 | continue; |
584 | stats_icmp_echo, stats_dns, stats_dns_doh, stats_dns_dot, stats_dns_doq); | 597 | } |
585 | printf("press any key to continue..."); | 598 | else if (c == 'd' || c == 'D') { |
586 | fflush(0); | 599 | printf("\n\n"); |
587 | 600 | ansi_bold("__________________________________________________________________________\n"); | |
588 | getchar(); | 601 | print_stats(stdout); |
589 | printf("\n\nSNI log - time server-address SNI\n"); | 602 | ansi_bold("__________________________________________________________________________\n"); |
590 | print_sni(); | 603 | ansi_faint("press any key to continue..."); |
591 | printf("press any key to continue..."); | 604 | fflush(0); |
592 | fflush(0); | 605 | |
593 | 606 | getchar(); | |
594 | getchar(); | 607 | continue; |
595 | printf("\n\nDNS log - time server-address domain\n"); | 608 | } |
596 | print_dns(); | 609 | if (c == 's' || c == 'S') { |
597 | printf("press any key to continue..."); | 610 | printf("The file is saved in /tmp directory. Please enter the file name: "); |
598 | fflush(0); | 611 | fflush(0); |
599 | 612 | ||
600 | getchar(); | 613 | char buf[LINE_MAX + 5]; // eave some room to add /tmp/ |
601 | printf("\n\nIP table: %d addresses - server-address network (packets)\n", radix_nodes); | 614 | strcpy(buf, "/tmp/"); |
602 | radix_print(1); | 615 | terminal_restore(); |
603 | printf("press any key to continue..."); | 616 | if (fgets(buf + 5, LINE_MAX, stdin) == NULL) |
604 | fflush(0); | 617 | errExit("fgets"); |
605 | 618 | terminal_set(); | |
606 | getchar(); | 619 | |
620 | // remove '\n' and open the file | ||
621 | char *ptr = strchr(buf, '\n'); | ||
622 | if (!ptr) { // we should have a '\n' | ||
623 | printf("Error: invalid file name\n"); | ||
624 | sleep(5); | ||
625 | continue; | ||
626 | } | ||
627 | *ptr = '\0'; | ||
628 | |||
629 | FILE *fp = fopen(buf, "w"); | ||
630 | if (!fp) { | ||
631 | printf("Error: cannot open file %s\n", buf); | ||
632 | perror("fopen"); | ||
633 | sleep(5); | ||
634 | continue; | ||
635 | } | ||
636 | |||
637 | printf("Saving stats in %s file...\n", buf); | ||
638 | print_stats(fp); | ||
639 | fclose(fp); | ||
640 | int rv = chmod(buf, 0600); | ||
641 | (void) rv; | ||
642 | sleep(1); | ||
643 | continue; | ||
644 | } | ||
645 | else if (c == 'x' || c == 'X') | ||
646 | break; | ||
607 | continue; | 647 | continue; |
608 | } | 648 | } |
609 | else if (FD_ISSET(p1, &rfds)) { | 649 | else if (FD_ISSET(p1, &rfds)) { |
610 | char buf[1024]; | 650 | char buf[LINE_MAX]; |
611 | ssize_t sz = read(p1, buf, 1024 - 1); | 651 | ssize_t sz = read(p1, buf, LINE_MAX - 1); |
612 | if (sz == -1) | 652 | if (sz == -1) |
613 | errExit("error reading snitrace"); | 653 | errExit("error reading snitrace"); |
614 | if (sz == 0) { | 654 | if (sz == 0) { |
@@ -618,19 +658,13 @@ static void run_trace(void) { | |||
618 | if (strncmp(buf, "SNI trace", 9) == 0) | 658 | if (strncmp(buf, "SNI trace", 9) == 0) |
619 | continue; | 659 | continue; |
620 | 660 | ||
621 | if (sz > LOG_RECORD_LEN) | ||
622 | sz = LOG_RECORD_LEN; | ||
623 | buf[sz] = '\0'; | 661 | buf[sz] = '\0'; |
624 | strcpy(sni_table[sni_index].record, buf); | 662 | ev_add(buf); |
625 | if (++sni_index >= SNIMAX) { | ||
626 | sni_index = 0; | ||
627 | *sni_table[sni_index].record = '\0'; | ||
628 | } | ||
629 | continue; | 663 | continue; |
630 | } | 664 | } |
631 | else if (FD_ISSET(p2, &rfds)) { | 665 | else if (FD_ISSET(p2, &rfds)) { |
632 | char buf[1024]; | 666 | char buf[LINE_MAX]; |
633 | ssize_t sz = read(p2, buf, 1024 - 1); | 667 | ssize_t sz = read(p2, buf, LINE_MAX - 1); |
634 | if (sz == -1) | 668 | if (sz == -1) |
635 | errExit("error reading dnstrace"); | 669 | errExit("error reading dnstrace"); |
636 | if (sz == 0) { | 670 | if (sz == 0) { |
@@ -640,16 +674,11 @@ static void run_trace(void) { | |||
640 | if (strncmp(buf, "DNS trace", 9) == 0) | 674 | if (strncmp(buf, "DNS trace", 9) == 0) |
641 | continue; | 675 | continue; |
642 | 676 | ||
643 | if (sz > LOG_RECORD_LEN) | ||
644 | sz = LOG_RECORD_LEN; | ||
645 | buf[sz] = '\0'; | 677 | buf[sz] = '\0'; |
646 | strcpy(dns_table[dns_index].record, buf); | 678 | ev_add(buf); |
647 | if (++dns_index >= DNSMAX) { | ||
648 | dns_index = 0; | ||
649 | *dns_table[dns_index].record = '\0'; | ||
650 | } | ||
651 | continue; | 679 | continue; |
652 | } | 680 | } |
681 | // by default we assume TCP | ||
653 | else if (FD_ISSET(s2, &rfds)) | 682 | else if (FD_ISSET(s2, &rfds)) |
654 | sock = s2; | 683 | sock = s2; |
655 | else if (FD_ISSET(s3, &rfds)) { | 684 | else if (FD_ISSET(s3, &rfds)) { |
@@ -658,7 +687,7 @@ static void run_trace(void) { | |||
658 | } | 687 | } |
659 | 688 | ||
660 | unsigned bytes = recvfrom(sock, buf, MAX_BUF_SIZE, 0, NULL, NULL); | 689 | unsigned bytes = recvfrom(sock, buf, MAX_BUF_SIZE, 0, NULL, NULL); |
661 | if (bytes >= 20) { // size of IP header | 690 | if (bytes >= 20) { // minimum size of IP packet |
662 | #ifdef DEBUG | 691 | #ifdef DEBUG |
663 | { | 692 | { |
664 | uint32_t ip_src; | 693 | uint32_t ip_src; |
@@ -682,12 +711,30 @@ static void run_trace(void) { | |||
682 | uint8_t hlen = (buf[0] & 0x0f) * 4; | 711 | uint8_t hlen = (buf[0] & 0x0f) * 4; |
683 | uint16_t port_src = 0; | 712 | uint16_t port_src = 0; |
684 | if (icmp) | 713 | if (icmp) |
685 | hnode_add(ip_src, 0, 0, bytes + 14); | 714 | hnode_add(ip_src, PROTOCOL_ICMP, 0, bytes + 14); |
686 | else { | 715 | else { // itcp or udp |
687 | memcpy(&port_src, buf + hlen, 2); | 716 | memcpy(&port_src, buf + hlen, 2); |
688 | port_src = ntohs(port_src); | 717 | port_src = ntohs(port_src); |
689 | 718 | int protocol = (int) buf[9]; | |
690 | uint8_t protocol = buf[9]; | 719 | |
720 | // detect ssh on a standard or not so standard port (22) | ||
721 | if (protocol == 6) { // tcp | ||
722 | uint8_t dataoffset = *(buf + hlen + 12); | ||
723 | uint8_t tcphlen = (dataoffset >> 2); | ||
724 | if (memcmp(buf + hlen + tcphlen, "SSH-", 4) == 0) { | ||
725 | time_t seconds = time(NULL); | ||
726 | struct tm *t = localtime(&seconds); | ||
727 | char ip[30]; | ||
728 | sprintf(ip, "%d.%d.%d.%d", PRINT_IP(ip_src)); | ||
729 | char *msg; | ||
730 | if (asprintf(&msg, "%02d:%02d:%02d %-15s SSH connection", | ||
731 | t->tm_hour, t->tm_min, t->tm_sec, ip) == -1) | ||
732 | errExit("asprintf"); | ||
733 | ev_add(msg); | ||
734 | free(msg); | ||
735 | protocol = PROTOCOL_SSH; | ||
736 | } | ||
737 | } | ||
691 | hnode_add(ip_src, protocol, port_src, bytes + 14); | 738 | hnode_add(ip_src, protocol, port_src, bytes + 14); |
692 | } | 739 | } |
693 | 740 | ||
@@ -705,7 +752,10 @@ static void run_trace(void) { | |||
705 | close(s1); | 752 | close(s1); |
706 | close(s2); | 753 | close(s2); |
707 | close(s3); | 754 | close(s3); |
708 | print_stats(); | 755 | if (p1 != -1) |
756 | close(p1); | ||
757 | if (p2 != -1) | ||
758 | close(p2); | ||
709 | } | 759 | } |
710 | 760 | ||
711 | 761 | ||
@@ -765,7 +815,7 @@ int main(int argc, char **argv) { | |||
765 | else if (strcmp(argv[i], "--print-map") == 0) { | 815 | else if (strcmp(argv[i], "--print-map") == 0) { |
766 | char *fname = "static-ip-map.txt"; | 816 | char *fname = "static-ip-map.txt"; |
767 | load_hostnames(fname); | 817 | load_hostnames(fname); |
768 | radix_print(0); | 818 | radix_print(stdout, 0); |
769 | return 0; | 819 | return 0; |
770 | } | 820 | } |
771 | else if (strncmp(argv[i], "--squash-map=", 13) == 0) { | 821 | else if (strncmp(argv[i], "--squash-map=", 13) == 0) { |
@@ -787,7 +837,7 @@ int main(int argc, char **argv) { | |||
787 | printf("# License GPLv2\n"); | 837 | printf("# License GPLv2\n"); |
788 | printf("#\n"); | 838 | printf("#\n"); |
789 | 839 | ||
790 | radix_print(0); | 840 | radix_print(stdout, 0); |
791 | printf("\n#\n#\n# input %d, output %d\n#\n#\n", in, radix_nodes); | 841 | printf("\n#\n#\n# input %d, output %d\n#\n#\n", in, radix_nodes); |
792 | fprintf(stderr, "static ip map: input %d, output %d\n", in, radix_nodes); | 842 | fprintf(stderr, "static ip map: input %d, output %d\n", in, radix_nodes); |
793 | return 0; | 843 | return 0; |
diff --git a/src/fnettrace/radix.c b/src/fnettrace/radix.c index 322ee2643..9dfa725a2 100644 --- a/src/fnettrace/radix.c +++ b/src/fnettrace/radix.c | |||
@@ -151,21 +151,22 @@ RNode *radix_longest_prefix_match(uint32_t ip) { | |||
151 | } | 151 | } |
152 | 152 | ||
153 | static uint32_t sum; | 153 | static uint32_t sum; |
154 | static void print(RNode *ptr, int level, int pkts) { | 154 | static void print(FILE *fp, RNode *ptr, int level, int pkts) { |
155 | assert(fp); | ||
155 | if (!ptr) | 156 | if (!ptr) |
156 | return; | 157 | return; |
157 | if (ptr->name) { | 158 | if (ptr->name) { |
158 | if (pkts) { | 159 | if (pkts) { |
159 | if (ptr->pkts) { | 160 | if (ptr->pkts) { |
160 | printf(" %d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level); | 161 | fprintf(fp, " %d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level); |
161 | printf("%s", ptr->name); | 162 | fprintf(fp, "%s", ptr->name); |
162 | printf(" (%u)\n", ptr->pkts); | 163 | fprintf(fp, " (%u)\n", ptr->pkts); |
163 | } | 164 | } |
164 | } | 165 | } |
165 | else { | 166 | else { |
166 | printf("%d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level); | 167 | fprintf(fp, "%d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level); |
167 | printf("%s", ptr->name); | 168 | fprintf(fp, "%s", ptr->name); |
168 | printf("\n"); | 169 | fprintf(fp, "\n"); |
169 | } | 170 | } |
170 | } | 171 | } |
171 | 172 | ||
@@ -174,21 +175,21 @@ static void print(RNode *ptr, int level, int pkts) { | |||
174 | 175 | ||
175 | level++; | 176 | level++; |
176 | sum <<= 1; | 177 | sum <<= 1; |
177 | print(ptr->zero, level, pkts); | 178 | print(fp, ptr->zero, level, pkts); |
178 | sum++; | 179 | sum++; |
179 | print(ptr->one, level, pkts); | 180 | print(fp, ptr->one, level, pkts); |
180 | sum--; | 181 | sum--; |
181 | sum >>= 1; | 182 | sum >>= 1; |
182 | } | 183 | } |
183 | 184 | ||
184 | void radix_print(int pkts) { | 185 | void radix_print(FILE *fp, int pkts) { |
185 | if (!head) | 186 | if (!head) |
186 | return; | 187 | return; |
187 | sum = 0; | 188 | sum = 0; |
188 | print(head->zero, 1, pkts); | 189 | print(fp, head->zero, 1, pkts); |
189 | assert(sum == 0); | 190 | assert(sum == 0); |
190 | sum = 1; | 191 | sum = 1; |
191 | print(head->one, 1, pkts); | 192 | print(fp, head->one, 1, pkts); |
192 | assert(sum == 1); | 193 | assert(sum == 1); |
193 | } | 194 | } |
194 | 195 | ||
@@ -241,3 +242,18 @@ void radix_squash(void) { | |||
241 | assert(sum == 1); | 242 | assert(sum == 1); |
242 | 243 | ||
243 | } | 244 | } |
245 | |||
246 | static void clear_data(RNode *ptr) { | ||
247 | if (!ptr) | ||
248 | return; | ||
249 | ptr->pkts = 0; | ||
250 | clear_data(ptr->zero); | ||
251 | clear_data(ptr->one); | ||
252 | } | ||
253 | |||
254 | void radix_clear_data(void) { | ||
255 | if (!head) | ||
256 | return; | ||
257 | clear_data(head->zero); | ||
258 | clear_data(head->one); | ||
259 | } | ||
diff --git a/src/fnettrace/radix.h b/src/fnettrace/radix.h index 358524723..686d60ace 100644 --- a/src/fnettrace/radix.h +++ b/src/fnettrace/radix.h | |||
@@ -30,7 +30,8 @@ typedef struct rnode_t { | |||
30 | extern int radix_nodes; | 30 | extern int radix_nodes; |
31 | RNode *radix_longest_prefix_match(uint32_t ip); | 31 | RNode *radix_longest_prefix_match(uint32_t ip); |
32 | RNode*radix_add(uint32_t ip, uint32_t mask, char *name); | 32 | RNode*radix_add(uint32_t ip, uint32_t mask, char *name); |
33 | void radix_print(int pkts); | 33 | void radix_print(FILE *fp, int pkts); |
34 | void radix_squash(void); | 34 | void radix_squash(void); |
35 | void radix_clear_data(void); | ||
35 | 36 | ||
36 | #endif | 37 | #endif |
diff --git a/src/fnettrace/static-ip-map.txt b/src/fnettrace/static-ip-map.txt index eb66df73f..088b5cfea 100644 --- a/src/fnettrace/static-ip-map.txt +++ b/src/fnettrace/static-ip-map.txt | |||
@@ -153,6 +153,7 @@ | |||
153 | 45.113.128.0/22 Twitch | 153 | 45.113.128.0/22 Twitch |
154 | 47.88.0.0/14 Alibaba | 154 | 47.88.0.0/14 Alibaba |
155 | 52.223.192.0/18 Twitch | 155 | 52.223.192.0/18 Twitch |
156 | 63.141.247.168/29 BitChute | ||
156 | 63.245.208.0/23 Mozilla | 157 | 63.245.208.0/23 Mozilla |
157 | 64.63.0.0/18 Twitter | 158 | 64.63.0.0/18 Twitter |
158 | 64.112.13.0/24 Dropbox | 159 | 64.112.13.0/24 Dropbox |
@@ -168,6 +169,7 @@ | |||
168 | 66.218.64.0/19 Yahoo | 169 | 66.218.64.0/19 Yahoo |
169 | 66.220.144.0/20 Facebook | 170 | 66.220.144.0/20 Facebook |
170 | 69.30.200.200/29 BitChute | 171 | 69.30.200.200/29 BitChute |
172 | 69.30.241.48/29 BitChute | ||
171 | 69.53.224.0/19 Netflix | 173 | 69.53.224.0/19 Netflix |
172 | 69.171.224.0/19 Facebook | 174 | 69.171.224.0/19 Facebook |
173 | 69.197.182.184/29 BitChute | 175 | 69.197.182.184/29 BitChute |
@@ -222,7 +224,10 @@ | |||
222 | 173.208.154.8/29 BitChute | 224 | 173.208.154.8/29 BitChute |
223 | 173.208.154.160/29 BitChute | 225 | 173.208.154.160/29 BitChute |
224 | 173.208.185.200/29 BitChute | 226 | 173.208.185.200/29 BitChute |
227 | 173.208.203.248/29 BitChute | ||
228 | 173.208.216.40/29 BitChute | ||
225 | 173.208.219.112/29 BitChute | 229 | 173.208.219.112/29 BitChute |
230 | 173.208.246.160/29 BitChute | ||
226 | 178.154.131.0/24 Yandex | 231 | 178.154.131.0/24 Yandex |
227 | 185.2.220.0/22 Netflix | 232 | 185.2.220.0/22 Netflix |
228 | 185.9.188.0/22 Netflix | 233 | 185.9.188.0/22 Netflix |
@@ -246,6 +251,7 @@ | |||
246 | 192.151.158.136/29 BitChute | 251 | 192.151.158.136/29 BitChute |
247 | 192.173.64.0/18 Netflix | 252 | 192.173.64.0/18 Netflix |
248 | 192.187.97.88/29 BitChute | 253 | 192.187.97.88/29 BitChute |
254 | 192.187.114.16/29 BitChute | ||
249 | 192.187.114.96/29 BitChute | 255 | 192.187.114.96/29 BitChute |
250 | 192.187.123.112/29 BitChute | 256 | 192.187.123.112/29 BitChute |
251 | 192.187.126.0/29 BitChute | 257 | 192.187.126.0/29 BitChute |
@@ -254,13 +260,17 @@ | |||
254 | 198.38.96.0/19 Netflix | 260 | 198.38.96.0/19 Netflix |
255 | 198.45.48.0/20 Netflix | 261 | 198.45.48.0/20 Netflix |
256 | 198.204.226.120/29 BitChute | 262 | 198.204.226.120/29 BitChute |
263 | 198.204.228.48/29 BitChute | ||
264 | 198.204.245.32/29 BitChute | ||
257 | 198.204.245.88/29 BitChute | 265 | 198.204.245.88/29 BitChute |
266 | 198.204.250.208/29 BitChute | ||
258 | 198.252.206.0/24 Stack Exchange | 267 | 198.252.206.0/24 Stack Exchange |
259 | 199.9.248.0/21 Twitch | 268 | 199.9.248.0/21 Twitch |
260 | 199.16.156.0/22 Twitter | 269 | 199.16.156.0/22 Twitter |
261 | 199.59.148.0/22 Twitter | 270 | 199.59.148.0/22 Twitter |
262 | 199.168.96.24/29 BitChute | 271 | 199.168.96.24/29 BitChute |
263 | 204.12.194.176/29 BitChute | 272 | 204.12.194.176/29 BitChute |
273 | 204.12.220.232/29 BitChute | ||
264 | 205.185.194.0/24 Steam | 274 | 205.185.194.0/24 Steam |
265 | 205.196.6.0/24 Steam | 275 | 205.196.6.0/24 Steam |
266 | 207.45.72.0/22 Netflix | 276 | 207.45.72.0/22 Netflix |
@@ -273,6 +283,15 @@ | |||
273 | 208.110.68.56/29 BitChute | 283 | 208.110.68.56/29 BitChute |
274 | 209.140.128.0/18 eBay | 284 | 209.140.128.0/18 eBay |
275 | 285 | ||
286 | # WholeSale Internet | ||
287 | 69.30.192.0/18 WholeSale Internet | ||
288 | 69.197.128.0/18 WholeSale Internet | ||
289 | 173.208.128.0/17 WholeSale Internet | ||
290 | 204.12.192.0/18 WholeSale Internet | ||
291 | 208.67.0.0/21 WholeSale Internet | ||
292 | 208.110.64.0/19 WholeSale Internet | ||
293 | 208.110.91.0/24 WholeSale Internet | ||
294 | |||
276 | # Imperva | 295 | # Imperva |
277 | 199.83.128.0/21 Imperva | 296 | 199.83.128.0/21 Imperva |
278 | 198.143.32.0/19 Imperva | 297 | 198.143.32.0/19 Imperva |