aboutsummaryrefslogtreecommitdiffstats
path: root/src/fnettrace
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@protonmail.com>2023-07-26 08:59:18 -0400
committerLibravatar netblue30 <netblue30@protonmail.com>2023-07-26 08:59:18 -0400
commit1d69791e80cbe583aae3a0f4230d07f721b2932d (patch)
treeb829f0648f604ab74971238de509a3074521ffaf /src/fnettrace
parentsplit nettrace executable ^Cto netrace and netlock (diff)
downloadfirejail-1d69791e80cbe583aae3a0f4230d07f721b2932d.tar.gz
firejail-1d69791e80cbe583aae3a0f4230d07f721b2932d.tar.zst
firejail-1d69791e80cbe583aae3a0f4230d07f721b2932d.zip
netlock/nettrace cleanup
Diffstat (limited to 'src/fnettrace')
-rw-r--r--src/fnettrace/main.c226
-rw-r--r--src/fnettrace/static-ip-map.txt4
-rw-r--r--src/fnettrace/tail.c63
3 files changed, 19 insertions, 274 deletions
diff --git a/src/fnettrace/main.c b/src/fnettrace/main.c
index 22da429af..3bafd9090 100644
--- a/src/fnettrace/main.c
+++ b/src/fnettrace/main.c
@@ -25,8 +25,6 @@
25#include <signal.h> 25#include <signal.h>
26#define MAX_BUF_SIZE (64 * 1024) 26#define MAX_BUF_SIZE (64 * 1024)
27 27
28static int arg_netfilter = 0;
29static int arg_tail = 0;
30static char *arg_log = NULL; 28static char *arg_log = NULL;
31 29
32//***************************************************************** 30//*****************************************************************
@@ -42,6 +40,7 @@ uint32_t stats_tls = 0;
42uint32_t stats_quic = 0; 40uint32_t stats_quic = 0;
43uint32_t stats_tor = 0; 41uint32_t stats_tor = 0;
44uint32_t stats_http = 0; 42uint32_t stats_http = 0;
43uint32_t stats_ssh = 0;
45 44
46//***************************************************************** 45//*****************************************************************
47// sni/dns log storage 46// sni/dns log storage
@@ -191,9 +190,6 @@ static void hnode_add(uint32_t ip_src, uint8_t protocol, uint16_t port_src, uint
191 if (!hnew->rnode) 190 if (!hnew->rnode)
192 hnew->rnode = radix_add(hnew->ip_src, 0xffffffff, NULL); 191 hnew->rnode = radix_add(hnew->ip_src, 0xffffffff, NULL);
193 hnew->rnode->pkts++; 192 hnew->rnode->pkts++;
194
195 if (arg_netfilter)
196 logprintf(" %d.%d.%d.%d ", PRINT_IP(hnew->ip_src));
197} 193}
198 194
199static void hnode_free(HNode *elem) { 195static void hnode_free(HNode *elem) {
@@ -357,7 +353,6 @@ static inline const char *common_port(uint16_t port) {
357 353
358 354
359static void hnode_print(unsigned bw) { 355static void hnode_print(unsigned bw) {
360 assert(!arg_netfilter);
361 bw = (bw < 1024 * DISPLAY_INTERVAL) ? 1024 * DISPLAY_INTERVAL : bw; 356 bw = (bw < 1024 * DISPLAY_INTERVAL) ? 1024 * DISPLAY_INTERVAL : bw;
362#ifdef DEBUG 357#ifdef DEBUG
363 printf("*********************\n"); 358 printf("*********************\n");
@@ -459,6 +454,8 @@ static void hnode_print(unsigned bw) {
459 stats_http += ptr->pkts; 454 stats_http += ptr->pkts;
460 else if (strcmp(protocol, "Tor") == 0) 455 else if (strcmp(protocol, "Tor") == 0)
461 stats_tor += ptr->pkts; 456 stats_tor += ptr->pkts;
457 else if (strcmp(protocol, "SSH") == 0)
458 stats_ssh += ptr->pkts;
462 } 459 }
463 else if (ptr->protocol == 0x11) 460 else if (ptr->protocol == 0x11)
464 protocol = "UDP"; 461 protocol = "UDP";
@@ -514,9 +511,6 @@ void print_stats(void) {
514 511
515// trace rx traffic coming in 512// trace rx traffic coming in
516static void run_trace(void) { 513static void run_trace(void) {
517 if (arg_netfilter)
518 logprintf("accumulating traffic for %d seconds\n", NETLOCK_INTERVAL);
519
520 // trace only rx ipv4 tcp and upd 514 // trace only rx ipv4 tcp and upd
521 int s1 = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); 515 int s1 = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
522 int s2 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); 516 int s2 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
@@ -525,44 +519,28 @@ static void run_trace(void) {
525 errExit("socket"); 519 errExit("socket");
526 520
527 521
528 int p1 = -1; 522 int p1 = runprog(LIBDIR "/firejail/fnettrace-sni");
529 if (!arg_netfilter)
530 p1 = runprog(LIBDIR "/firejail/fnettrace-sni");
531 if (p1 != -1) 523 if (p1 != -1)
532 printf("loading snitrace..."); 524 printf("loading snitrace...");
533 525
534 int p2 = -1; 526 int p2 = runprog(LIBDIR "/firejail/fnettrace-dns --nolocal");
535 if (!arg_netfilter)
536 p2 = runprog(LIBDIR "/firejail/fnettrace-dns --nolocal");
537 if (p2 != -1) 527 if (p2 != -1)
538 printf("loading dnstrace..."); 528 printf("loading dnstrace...");
539 unsigned start = time(NULL);
540 unsigned last_print_traces = 0; 529 unsigned last_print_traces = 0;
541 unsigned last_print_remaining = 0;
542 unsigned char buf[MAX_BUF_SIZE]; 530 unsigned char buf[MAX_BUF_SIZE];
543 unsigned bw = 0; // bandwidth calculations 531 unsigned bw = 0; // bandwidth calculations
544 532
545 while (1) { 533 while (1) {
546 unsigned end = time(NULL); 534 unsigned end = time(NULL);
547 if (arg_netfilter && end - start >= NETLOCK_INTERVAL)
548 break;
549 if (end % DISPLAY_INTERVAL == 1 && last_print_traces != end) { // first print after 1 second 535 if (end % DISPLAY_INTERVAL == 1 && last_print_traces != end) { // first print after 1 second
550 if (!arg_netfilter) 536 hnode_print(bw);
551 hnode_print(bw);
552 last_print_traces = end; 537 last_print_traces = end;
553 bw = 0; 538 bw = 0;
554 } 539 }
555 if (arg_netfilter && last_print_remaining != end) {
556 logprintf(".");
557 fflush(0);
558 last_print_remaining = end;
559 }
560 540
561 fd_set rfds; 541 fd_set rfds;
562
563 FD_ZERO(&rfds); 542 FD_ZERO(&rfds);
564 if (!arg_netfilter) 543 FD_SET(0, &rfds);
565 FD_SET(0, &rfds);
566 544
567 FD_SET(s1, &rfds); 545 FD_SET(s1, &rfds);
568 FD_SET(s2, &rfds); 546 FD_SET(s2, &rfds);
@@ -596,11 +574,11 @@ static void run_trace(void) {
596 int sock = s1; 574 int sock = s1;
597 int icmp = 0; 575 int icmp = 0;
598 576
599 if (!arg_netfilter && FD_ISSET(0, &rfds)) { 577 if (FD_ISSET(0, &rfds)) {
600 getchar(); 578 getchar();
601 printf("\n\nStats: %u packets\n", stats_pkts); 579 printf("\n\nStats: %u packets\n", stats_pkts);
602 printf(" encrypted: TLS %u, QUIC %u, Tor %u\n", 580 printf(" encrypted: TLS %u, QUIC %u, SSH %u, Tor %u\n",
603 stats_tls, stats_quic, stats_tor); 581 stats_tls, stats_quic, stats_ssh, stats_tor);
604 printf(" unencrypted: HTTP %u\n", stats_http); 582 printf(" unencrypted: HTTP %u\n", stats_http);
605 printf(" C&C backchannel: PING %u, DNS %u, DoH %u, DoT %u, DoQ %u\n", 583 printf(" C&C backchannel: PING %u, DNS %u, DoH %u, DoT %u, DoQ %u\n",
606 stats_icmp_echo, stats_dns, stats_dns_doh, stats_dns_dot, stats_dns_doq); 584 stats_icmp_echo, stats_dns, stats_dns_doh, stats_dns_dot, stats_dns_doq);
@@ -628,7 +606,7 @@ static void run_trace(void) {
628 getchar(); 606 getchar();
629 continue; 607 continue;
630 } 608 }
631 else if (!arg_netfilter && FD_ISSET(p1, &rfds)) { 609 else if (FD_ISSET(p1, &rfds)) {
632 char buf[1024]; 610 char buf[1024];
633 ssize_t sz = read(p1, buf, 1024 - 1); 611 ssize_t sz = read(p1, buf, 1024 - 1);
634 if (sz == -1) 612 if (sz == -1)
@@ -650,7 +628,7 @@ static void run_trace(void) {
650 } 628 }
651 continue; 629 continue;
652 } 630 }
653 else if (!arg_netfilter && FD_ISSET(p2, &rfds)) { 631 else if (FD_ISSET(p2, &rfds)) {
654 char buf[1024]; 632 char buf[1024];
655 ssize_t sz = read(p2, buf, 1024 - 1); 633 ssize_t sz = read(p2, buf, 1024 - 1);
656 if (sz == -1) 634 if (sz == -1)
@@ -730,142 +708,6 @@ static void run_trace(void) {
730 print_stats(); 708 print_stats();
731} 709}
732 710
733static char *filter_start =
734 "*filter\n"
735 ":INPUT DROP [0:0]\n"
736 ":FORWARD DROP [0:0]\n"
737 ":OUTPUT DROP [0:0]\n";
738
739// return 1 if error
740static int print_filter(FILE *fp) {
741 if (dlist == NULL)
742 return 1;
743 fprintf(fp, "%s\n", filter_start);
744 fprintf(fp, "-A INPUT -s 127.0.0.0/8 -j ACCEPT\n");
745 fprintf(fp, "-A OUTPUT -d 127.0.0.0/8 -j ACCEPT\n");
746 fprintf(fp, "\n");
747
748 int i;
749 for (i = 0; i < HMAX; i++) {
750 HNode *ptr = htable[i];
751 while (ptr) {
752 // filter rules are targeting ip address, the port number is disregarded,
753 // so we look only at the first instance of an address
754 if (ptr->ip_instance == 1) {
755 char *protocol = (ptr->protocol == 6) ? "tcp" : "udp";
756 fprintf(fp, "-A INPUT -s %d.%d.%d.%d -p %s -j ACCEPT\n",
757 PRINT_IP(ptr->ip_src),
758 protocol);
759 fprintf(fp, "-A OUTPUT -d %d.%d.%d.%d -p %s -j ACCEPT\n",
760 PRINT_IP(ptr->ip_src),
761 protocol);
762 fprintf(fp, "\n");
763 }
764 ptr = ptr->hnext;
765 }
766 }
767 fprintf(fp, "COMMIT\n");
768
769 return 0;
770}
771
772static char *flush_rules[] = {
773 "-P INPUT ACCEPT",
774// "-P FORWARD DENY",
775 "-P OUTPUT ACCEPT",
776 "-F",
777 "-X",
778// "-t nat -F",
779// "-t nat -X",
780// "-t mangle -F",
781// "-t mangle -X",
782// "iptables -t raw -F",
783// "-t raw -X",
784 NULL
785};
786
787static void deploy_netfilter(void) {
788 int rv;
789 char *cmd;
790 int i;
791
792 if (dlist == NULL) {
793 logprintf("Sorry, no network traffic was detected. The firewall was not configured.\n");
794 return;
795 }
796 // find iptables command
797 char *iptables = NULL;
798 char *iptables_restore = NULL;
799 if (access("/sbin/iptables", X_OK) == 0) {
800 iptables = "/sbin/iptables";
801 iptables_restore = "/sbin/iptables-restore";
802 }
803 else if (access("/usr/sbin/iptables", X_OK) == 0) {
804 iptables = "/usr/sbin/iptables";
805 iptables_restore = "/usr/sbin/iptables-restore";
806 }
807 if (iptables == NULL || iptables_restore == NULL) {
808 fprintf(stderr, "Error: iptables command not found, netfilter not configured\n");
809 exit(1);
810 }
811
812 // flush all netfilter rules
813 i = 0;
814 while (flush_rules[i]) {
815 char *cmd;
816 if (asprintf(&cmd, "%s %s", iptables, flush_rules[i]) == -1)
817 errExit("asprintf");
818 int rv = system(cmd);
819 (void) rv;
820 free(cmd);
821 i++;
822 }
823
824 // create temporary file
825 char fname[] = "/tmp/firejail-XXXXXX";
826 int fd = mkstemp(fname);
827 if (fd == -1) {
828 fprintf(stderr, "Error: cannot create temporary configuration file\n");
829 exit(1);
830 }
831
832 FILE *fp = fdopen(fd, "w");
833 if (!fp) {
834 rv = unlink(fname);
835 (void) rv;
836 fprintf(stderr, "Error: cannot create temporary configuration file\n");
837 exit(1);
838 }
839 print_filter(fp);
840 fclose(fp);
841
842 logprintf("\n\n");
843 logprintf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
844 if (asprintf(&cmd, "cat %s >> %s", fname, arg_log) == -1)
845 errExit("asprintf");
846 rv = system(cmd);
847 (void) rv;
848 free(cmd);
849
850 if (asprintf(&cmd, "cat %s", fname) == -1)
851 errExit("asprintf");
852 rv = system(cmd);
853 (void) rv;
854 free(cmd);
855 logprintf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
856
857 // configuring
858 if (asprintf(&cmd, "%s %s", iptables_restore, fname) == -1)
859 errExit("asprintf");
860 rv = system(cmd);
861 if (rv)
862 fprintf(stdout, "Warning: possible netfilter problem!");
863 free(cmd);
864
865 rv = unlink(fname);
866 (void) rv;
867 logprintf("\nfirewall deployed\n");
868}
869 711
870void logprintf(char *fmt, ...) { 712void logprintf(char *fmt, ...) {
871 if (!arg_log) 713 if (!arg_log)
@@ -891,14 +733,8 @@ static const char *const usage_str =
891 "Options:\n" 733 "Options:\n"
892 " --help, -? - this help screen\n" 734 " --help, -? - this help screen\n"
893 " --log=filename - netlocker logfile\n" 735 " --log=filename - netlocker logfile\n"
894 " --netfilter - build the firewall rules and commit them\n"
895 " --print-map - print IP map\n" 736 " --print-map - print IP map\n"
896 " --squash-map - compress IP map\n" 737 " --squash-map - compress IP map\n";
897 " --tail - \"tail -f\" functionality\n"
898 "Examples:\n"
899 " # fnettrace - traffic trace\n"
900 " # fnettrace --netfilter --log=logfile - netlocker, dump output in logfile\n"
901 " # fnettrace --tail --log=logifile - similar to \"tail -f logfile\"\n";
902 738
903static void usage(void) { 739static void usage(void) {
904 puts(usage_str); 740 puts(usage_str);
@@ -956,10 +792,6 @@ int main(int argc, char **argv) {
956 fprintf(stderr, "static ip map: input %d, output %d\n", in, radix_nodes); 792 fprintf(stderr, "static ip map: input %d, output %d\n", in, radix_nodes);
957 return 0; 793 return 0;
958 } 794 }
959 else if (strcmp(argv[i], "--netfilter") == 0)
960 arg_netfilter = 1;
961 else if (strcmp(argv[i], "--tail") == 0)
962 arg_tail = 1;
963 else if (strncmp(argv[i], "--log=", 6) == 0) 795 else if (strncmp(argv[i], "--log=", 6) == 0)
964 arg_log = argv[i] + 6; 796 arg_log = argv[i] + 6;
965 else { 797 else {
@@ -968,19 +800,6 @@ int main(int argc, char **argv) {
968 } 800 }
969 } 801 }
970 802
971 // tail
972 if (arg_tail) {
973 if (!arg_log) {
974 fprintf(stderr, "Error: no log file\n");
975 usage();
976 exit(1);
977 }
978
979 tail(arg_log);
980 sleep(5);
981 exit(0);
982 }
983
984 if (getuid() != 0) { 803 if (getuid() != 0) {
985 fprintf(stderr, "Error: you need to be root to run this program\n"); 804 fprintf(stderr, "Error: you need to be root to run this program\n");
986 return 1; 805 return 1;
@@ -996,25 +815,10 @@ int main(int argc, char **argv) {
996 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); 815 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
997 816
998 ansi_clrscr(); 817 ansi_clrscr();
999 if (arg_netfilter) 818 char *fname = LIBDIR "/firejail/static-ip-map";
1000 logprintf("starting network lockdown\n"); 819 load_hostnames(fname);
1001 else {
1002 char *fname = LIBDIR "/firejail/static-ip-map";
1003 load_hostnames(fname);
1004 }
1005 820
1006 run_trace(); 821 run_trace();
1007 if (arg_netfilter) {
1008 // TCP path MTU discovery will not work properly since the firewall drops all ICMP packets
1009 // Instead, we use iPacketization Layer PMTUD (RFC 4821) support in Linux kernel
1010 int rv = system("echo 1 > /proc/sys/net/ipv4/tcp_mtu_probing");
1011 (void) rv;
1012
1013 deploy_netfilter();
1014 sleep(3);
1015 if (arg_log)
1016 unlink(arg_log);
1017 }
1018 822
1019 return 0; 823 return 0;
1020} 824}
diff --git a/src/fnettrace/static-ip-map.txt b/src/fnettrace/static-ip-map.txt
index 20c404064..59ec79f8f 100644
--- a/src/fnettrace/static-ip-map.txt
+++ b/src/fnettrace/static-ip-map.txt
@@ -141,6 +141,7 @@
141# some popular websites 141# some popular websites
1425.255.255.0/24 Yandex 1425.255.255.0/24 Yandex
14323.160.0.0/24 Twitch 14323.160.0.0/24 Twitch
14423.229.128.0/17 GoDaddy
14423.246.0.0/18 Netflix 14523.246.0.0/18 Netflix
14531.13.24.0/21 Facebook 14631.13.24.0/21 Facebook
14631.13.64.0/17 Facebook 14731.13.64.0/17 Facebook
@@ -218,6 +219,7 @@
218162.254.192.0/21 Steam 219162.254.192.0/21 Steam
219172.98.56.0/22 Rumble 220172.98.56.0/22 Rumble
220173.208.154.8/29 BitChute 221173.208.154.8/29 BitChute
222173.208.154.160/29 BitChute
221173.208.185.200/29 BitChute 223173.208.185.200/29 BitChute
222173.208.219.112/29 BitChute 224173.208.219.112/29 BitChute
223178.154.131.0/24 Yandex 225178.154.131.0/24 Yandex
@@ -243,6 +245,7 @@
243192.151.158.136/29 BitChute 245192.151.158.136/29 BitChute
244192.173.64.0/18 Netflix 246192.173.64.0/18 Netflix
245192.187.97.88/29 BitChute 247192.187.97.88/29 BitChute
248192.187.114.96/29 BitChute
246192.187.123.112/29 BitChute 249192.187.123.112/29 BitChute
247192.189.200.0/23 Dropbox 250192.189.200.0/23 Dropbox
248194.169.254.0/24 Ubuntu One 251194.169.254.0/24 Ubuntu One
@@ -325,6 +328,7 @@
325205.185.196.0/23 StackPath 328205.185.196.0/23 StackPath
326205.185.198.0/24 StackPath 329205.185.198.0/24 StackPath
327205.185.200.0/21 StackPath 330205.185.200.0/21 StackPath
331205.185.208.0/24 StackPath
328205.185.212.0/23 StackPath 332205.185.212.0/23 StackPath
329205.185.215.0/24 StackPath 333205.185.215.0/24 StackPath
330205.185.216.0/23 StackPath 334205.185.216.0/23 StackPath
diff --git a/src/fnettrace/tail.c b/src/fnettrace/tail.c
deleted file mode 100644
index 3b1b274f8..000000000
--- a/src/fnettrace/tail.c
+++ /dev/null
@@ -1,63 +0,0 @@
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
22void tail(const char *logfile) {
23 assert(logfile);
24
25 // wait for no more than 5 seconds for the logfile to appear in the filesystem
26 int cnt = 5;
27 while (access(logfile, R_OK) && cnt > 0)
28 cnt--;
29 if (cnt == 0)
30 exit(1);
31
32 off_t last_size = 0;
33
34 while (1) {
35 int fd = open(logfile, O_RDONLY);
36 if (fd == -1)
37 return;
38
39 off_t size = lseek(fd, 0, SEEK_END);
40 if (size < 0) {
41 close(fd);
42 return;
43 }
44
45 char *content = NULL;
46 int mmapped = 0;
47 if (size && size != last_size) {
48 content = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
49 close(fd);
50 if (content != MAP_FAILED)
51 mmapped = 1;
52 }
53
54 if (mmapped) {
55 printf("%.*s", (int) (size - last_size), content + last_size);
56 fflush(0);
57 munmap(content, size);
58 last_size = size;
59 }
60
61 sleep(1);
62 }
63}