From f5c0b6af59b4c5e4c677d8bd9703beb4d2e628c3 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Wed, 2 Feb 2022 10:58:14 -0500 Subject: netlocker fixes --- src/firejail/netfilter.c | 11 ++++----- src/firejail/usage.c | 1 + src/fnettrace/fnettrace.h | 8 ++++++ src/fnettrace/main.c | 38 +++++++++++++++++++++++----- src/fnettrace/tail.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ src/jailcheck/network.c | 1 + src/man/firejail.txt | 12 +++++---- 7 files changed, 117 insertions(+), 17 deletions(-) create mode 100644 src/fnettrace/tail.c (limited to 'src') diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c index 939ab29fa..5b49fe19a 100644 --- a/src/firejail/netfilter.c +++ b/src/firejail/netfilter.c @@ -41,17 +41,16 @@ void netfilter_netlock(pid_t pid) { // try to find a X terminal char *terminal = NULL; - if (access("/usr/bin/lxterminal", X_OK) == 0) - terminal = "/usr/bin/lxterminal"; - else if (access("/usr/bin/xterm", X_OK) == 0) + if (access("/usr/bin/xterm", X_OK) == 0) terminal = "/usr/bin/xterm"; + else if (access("/usr/bin/lxterminal", X_OK) == 0) + terminal = "/usr/bin/lxterminal"; else if (access("/usr/bin/xfce4-terminal", X_OK) == 0) terminal = "/usr/bin/xfce4-terminal"; else if (access("/usr/bin/konsole", X_OK) == 0) terminal = "/usr/bin/konsole"; // problem: newer gnome-terminal versions don't support -e command line option??? -// else if (access("/usr/bin/gnome-terminal", X_OK) == 0) -// terminal = "/usr/bin/gnome-terminal"; +// same for mate-terminal if (isatty(STDIN_FILENO)) terminal = NULL; @@ -64,7 +63,7 @@ void netfilter_netlock(pid_t pid) { drop_privs(0); char *cmd; - if (asprintf(&cmd, "%s -e \"tail -f %s\"", terminal, flog) == -1) + if (asprintf(&cmd, "%s -e \"%s/firejail/fnettrace --tail --log=%s\"", terminal, LIBDIR, flog) == -1) errExit("asprintf"); int rv = system(cmd); (void) rv; diff --git a/src/firejail/usage.c b/src/firejail/usage.c index c903841c5..0b24467be 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -147,6 +147,7 @@ static char *usage_str = " --netfilter.print=name|pid - print the firewall.\n" " --netfilter6=filename - enable IPv6 firewall.\n" " --netfilter6.print=name|pid - print the IPv6 firewall.\n" + " --netlock - enable the network locking feature\n" " --netmask=address - define a network mask when dealing with unconfigured\n" "\tparent interfaces.\n" " --netns=name - Run the program in a named, persistent network namespace.\n" diff --git a/src/fnettrace/fnettrace.h b/src/fnettrace/fnettrace.h index 66b7378da..b30a9f10d 100644 --- a/src/fnettrace/fnettrace.h +++ b/src/fnettrace/fnettrace.h @@ -23,10 +23,15 @@ #include "../include/common.h" #include #include +#include #include #include #include #include +#include +#include + + //#define DEBUG 1 #define NETLOCK_INTERVAL 60 // seconds @@ -62,4 +67,7 @@ extern int geoip_calls; void load_hostnames(const char *fname); char* retrieve_hostname(uint32_t ip); +// tail.c +void tail(const char *logfile); + #endif \ No newline at end of file diff --git a/src/fnettrace/main.c b/src/fnettrace/main.c index e58cc79b3..31d49d839 100644 --- a/src/fnettrace/main.c +++ b/src/fnettrace/main.c @@ -23,6 +23,7 @@ #define MAX_BUF_SIZE (64 * 1024) static int arg_netfilter = 0; +static int arg_tail = 0; static char *arg_log = NULL; typedef struct hnode_t { @@ -574,11 +575,16 @@ void logprintf(char* fmt, ...) { } static void usage(void) { - printf("Usage: fnetlock [OPTIONS]\n"); + printf("Usage: fnettrace [OPTIONS]\n"); printf("Options:\n"); printf(" --help, -? - this help screen\n"); printf(" --log=filename - netlocker logfile\n"); printf(" --netfilter - build the firewall rules and commit them.\n"); + printf(" --tail - \"tail -f\" functionality\n"); + printf("Examples:\n"); + printf(" # fnettrace - traffic trace\n"); + printf(" # fnettrace --netfilter --log=logfile - netlocker, dump output in logfile\n"); + printf(" # fnettrace --tail --log=logifile - similar to \"tail -f logfile\"\n"); printf("\n"); } @@ -599,11 +605,6 @@ int main(int argc, char **argv) { printf("%s\n", name); #endif - if (getuid() != 0) { - fprintf(stderr, "Error: you need to be root to run this program\n"); - return 1; - } - for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-?") == 0) { usage(); @@ -611,6 +612,8 @@ int main(int argc, char **argv) { } else if (strcmp(argv[i], "--netfilter") == 0) arg_netfilter = 1; + else if (strcmp(argv[i], "--tail") == 0) + arg_tail = 1; else if (strncmp(argv[i], "--log=", 6) == 0) arg_log = argv[i] + 6; else { @@ -619,6 +622,24 @@ int main(int argc, char **argv) { } } + // tail + if (arg_tail) { + if (!arg_log) { + fprintf(stderr, "Error: no log file\n"); + usage(); + exit(1); + } + + tail(arg_log); + sleep(5); + exit(0); + } + + if (getuid() != 0) { + fprintf(stderr, "Error: you need to be root to run this program\n"); + return 1; + } + ansi_clrscr(); if (arg_netfilter) logprintf("starting network lockdown\n"); @@ -629,6 +650,11 @@ int main(int argc, char **argv) { run_trace(); if (arg_netfilter) { + // TCP path MTU discovery will not work properly since the firewall drops all ICMP packets + // Instead, we use iPacketization Layer PMTUD (RFC 4821) support in Linux kernel + int rv = system("echo 1 > /proc/sys/net/ipv4/tcp_mtu_probing"); + (void) rv; + deploy_netfilter(); sleep(3); if (arg_log) diff --git a/src/fnettrace/tail.c b/src/fnettrace/tail.c new file mode 100644 index 000000000..a910788d6 --- /dev/null +++ b/src/fnettrace/tail.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2014-2022 Firejail Authors + * + * This file is part of firejail project + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "fnettrace.h" + +void tail(const char *logfile) { + assert(logfile); + + // wait for no more than 5 seconds for the logfile to appear in the filesystem + int cnt = 5; + while (access(logfile, R_OK) && cnt > 0) + cnt--; + if (cnt == 0) + exit(1); + + off_t last_size = 0; + + while (1) { + int fd = open(logfile, O_RDONLY); + if (fd == -1) + return; + + off_t size = lseek(fd, 0, SEEK_END); + if (size < 0) { + close(fd); + return; + } + + char *content = NULL; + int mmapped = 0; + if (size && size != last_size) { + content = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + close(fd); + if (content != MAP_FAILED) + mmapped = 1; + } + + if (mmapped) { + printf("%.*s", (int) (size - last_size), content + last_size); + fflush(0); + munmap(content, size); + last_size = size; + } + + sleep(1); + } +} diff --git a/src/jailcheck/network.c b/src/jailcheck/network.c index 474224fc5..8f70c6ff0 100644 --- a/src/jailcheck/network.c +++ b/src/jailcheck/network.c @@ -40,6 +40,7 @@ void network_test(void) { for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (strcmp(ifa->ifa_name, "lo") == 0) continue; + found = 1; break; } diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 59dc5d310..4cbe7f13d 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -1458,17 +1458,19 @@ $ firejail --name=browser --net=eth0 --netfilter firefox & $ firejail --netfilter6.print=browser .TP -\fB\-\-netlock=name/pid +\fB\-\-netlock Several type of programs (email clients, multiplayer games etc.) talk to a very small number of IP addresses. But the best example is tor browser. It only talks to a guard node, and there are two or three more on standby in case the main one fails. During startup, the browser contacts all of them, after that it keeps talking to the main one... for weeks! -Use the network locking feature to build and deploy a network firewall in your sandbox. -The firewall allows only the network traffic to the IP addresses detected during the program -startup. Traffic to any other address is quietly dropped. By default the startup monitoring -time is one minute. Example: +Use the network locking feature to build and deploy a custom network firewall in your sandbox. +The firewall allows only the traffic to the IP addresses detected during the program +startup. Traffic to any other address is quietly dropped. By default the network monitoring +time is one minute. + +A network namespace (\-\-net=eth0) is required for this feature to work. Example: .br .br -- cgit v1.2.3-70-g09d2