mirror of
https://github.com/netblue30/firejail.git
synced 2026-05-15 14:16:14 -06:00
feature: stats support for --nettrace
This commit is contained in:
parent
cb39a0eafd
commit
f3e428e6fa
8 changed files with 142 additions and 17 deletions
1
RELNOTES
1
RELNOTES
|
|
@ -7,6 +7,7 @@ firejail (0.9.73) baseline; urgency=low
|
|||
* feature: add IPv6 support for --net.print option
|
||||
* feature: QUIC (HTTP/3) support in --nettrace
|
||||
* feature: use seccomp filters build at install time for --restrict-namespaces
|
||||
* feature: stats support for --nettrace
|
||||
* modif: Stop forwarding own double-dash to the shell (#5599 #5600)
|
||||
* modif: Prevent sandbox name (--name=) and host name (--hostname=)
|
||||
from containing only digits (#5578 #5741)
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ void netfilter_trace(pid_t pid, const char *cmd) {
|
|||
arg[3] = NULL;
|
||||
|
||||
clearenv();
|
||||
sbox_exec_v(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, arg);
|
||||
sbox_exec_v(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP | SBOX_ALLOW_STDIN, arg);
|
||||
// it will never get here!!
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,4 +70,9 @@ char* retrieve_hostname(uint32_t ip);
|
|||
// tail.c
|
||||
void tail(const char *logfile);
|
||||
|
||||
// terminal.c
|
||||
void terminal_handler(int s);
|
||||
void terminal_set(void);
|
||||
void terminal_restore(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@ static int arg_netfilter = 0;
|
|||
static int arg_tail = 0;
|
||||
static char *arg_log = NULL;
|
||||
|
||||
uint32_t stats_pkts = 0;
|
||||
uint32_t stats_icmp = 0;
|
||||
uint32_t stats_dns = 0;
|
||||
|
||||
|
||||
typedef struct hnode_t {
|
||||
struct hnode_t *hnext; // used for hash table and unused linked list
|
||||
struct hnode_t *dnext; // used to display streams on the screen
|
||||
|
|
@ -331,7 +336,7 @@ static void hnode_print(unsigned bw) {
|
|||
else
|
||||
sprintf(stats, "%u KB/s ", bw / (1024 * DISPLAY_INTERVAL));
|
||||
// int len = snprintf(line, LINE_MAX, "%32s geoip %d, IP database %d\n", stats, geoip_calls, radix_nodes);
|
||||
int len = snprintf(line, LINE_MAX, "%32s address:port (protocol) host (packets)\n", stats);
|
||||
int len = snprintf(line, LINE_MAX, "%32s address:port (protocol) network (packets)\n", stats);
|
||||
adjust_line(line, len, cols);
|
||||
printf("%s", line);
|
||||
|
||||
|
|
@ -418,6 +423,7 @@ static void hnode_print(unsigned bw) {
|
|||
|
||||
ptr = next;
|
||||
}
|
||||
printf("press any key to access stats\n");
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
|
|
@ -432,6 +438,14 @@ static void hnode_print(unsigned bw) {
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
void print_stats(void) {
|
||||
printf("\nIP table: %d entries, %d unknown\n", radix_nodes, geoip_calls);
|
||||
printf(" address network (packets)\n");
|
||||
radix_print(1);
|
||||
printf("Packets: %u total, ICMP %u, DNS %u\n", stats_pkts, stats_icmp, stats_dns);
|
||||
}
|
||||
|
||||
// trace rx traffic coming in
|
||||
static void run_trace(void) {
|
||||
if (arg_netfilter)
|
||||
|
|
@ -449,6 +463,7 @@ static void run_trace(void) {
|
|||
unsigned last_print_remaining = 0;
|
||||
unsigned char buf[MAX_BUF_SIZE];
|
||||
unsigned bw = 0; // bandwidth calculations
|
||||
|
||||
while (1) {
|
||||
unsigned end = time(NULL);
|
||||
if (arg_netfilter && end - start >= NETLOCK_INTERVAL)
|
||||
|
|
@ -470,6 +485,8 @@ static void run_trace(void) {
|
|||
FD_SET(s1, &rfds);
|
||||
FD_SET(s2, &rfds);
|
||||
FD_SET(s3, &rfds);
|
||||
if (!arg_netfilter)
|
||||
FD_SET(0, &rfds);
|
||||
int maxfd = (s1 > s2) ? s1 : s2;
|
||||
maxfd = (s3 > maxfd) ? s3 : maxfd;
|
||||
maxfd++;
|
||||
|
|
@ -484,9 +501,20 @@ static void run_trace(void) {
|
|||
else if (rv == 0)
|
||||
continue;
|
||||
|
||||
int icmp = 0;
|
||||
|
||||
// rx tcp traffic by default
|
||||
int sock = s1;
|
||||
if (FD_ISSET(s2, &rfds))
|
||||
int icmp = 0;
|
||||
|
||||
if (FD_ISSET(0, &rfds)) {
|
||||
getchar();
|
||||
print_stats();
|
||||
printf("press any key to continue...");
|
||||
fflush(0);
|
||||
getchar();
|
||||
continue;
|
||||
}
|
||||
else if (FD_ISSET(s2, &rfds))
|
||||
sock = s2;
|
||||
else if (FD_ISSET(s3, &rfds)) {
|
||||
sock = s3;
|
||||
|
|
@ -516,22 +544,32 @@ static void run_trace(void) {
|
|||
ip_src = ntohl(ip_src);
|
||||
|
||||
uint8_t hlen = (buf[0] & 0x0f) * 4;
|
||||
uint16_t port_src = 0;
|
||||
if (icmp)
|
||||
hnode_add(ip_src, 0, 0, bytes + 14);
|
||||
else {
|
||||
uint16_t port_src;
|
||||
memcpy(&port_src, buf + hlen, 2);
|
||||
port_src = ntohs(port_src);
|
||||
|
||||
uint8_t protocol = buf[9];
|
||||
hnode_add(ip_src, protocol, port_src, bytes + 14);
|
||||
}
|
||||
|
||||
// stats
|
||||
stats_pkts++;
|
||||
if (icmp)
|
||||
stats_icmp++;
|
||||
if (port_src == 53)
|
||||
stats_dns++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(s1);
|
||||
close(s2);
|
||||
close(s3);
|
||||
print_stats();
|
||||
}
|
||||
|
||||
static char *filter_start =
|
||||
|
|
@ -733,7 +771,7 @@ int main(int argc, char **argv) {
|
|||
else if (strcmp(argv[i], "--print-map") == 0) {
|
||||
char *fname = "static-ip-map.txt";
|
||||
load_hostnames(fname);
|
||||
radix_print();
|
||||
radix_print(0);
|
||||
return 0;
|
||||
}
|
||||
else if (strncmp(argv[i], "--squash-map=", 13) == 0) {
|
||||
|
|
@ -755,7 +793,7 @@ int main(int argc, char **argv) {
|
|||
printf("# License GPLv2\n");
|
||||
printf("#\n");
|
||||
|
||||
radix_print();
|
||||
radix_print(0);
|
||||
printf("\n#\n#\n# input %d, output %d\n#\n#\n", in, radix_nodes);
|
||||
fprintf(stderr, "static ip map: input %d, output %d\n", in, radix_nodes);
|
||||
return 0;
|
||||
|
|
@ -790,6 +828,12 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
terminal_set();
|
||||
// handle CTRL-C
|
||||
signal (SIGINT, terminal_handler);
|
||||
signal (SIGTERM, terminal_handler);
|
||||
atexit(terminal_restore);
|
||||
|
||||
// kill the process if the parent died
|
||||
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -151,12 +151,22 @@ RNode *radix_longest_prefix_match(uint32_t ip) {
|
|||
}
|
||||
|
||||
static uint32_t sum;
|
||||
static void print(RNode *ptr, int level) {
|
||||
static void print(RNode *ptr, int level, int pkts) {
|
||||
if (!ptr)
|
||||
return;
|
||||
if (ptr->name) {
|
||||
printf("%d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level);
|
||||
printf("%s\n", ptr->name);
|
||||
if (pkts) {
|
||||
if (ptr->pkts) {
|
||||
printf(" %d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level);
|
||||
printf("%s", ptr->name);
|
||||
printf(" (%u)\n", ptr->pkts);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("%d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level);
|
||||
printf("%s", ptr->name);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr->zero == NULL && ptr->one == NULL)
|
||||
|
|
@ -164,22 +174,21 @@ static void print(RNode *ptr, int level) {
|
|||
|
||||
level++;
|
||||
sum <<= 1;
|
||||
print(ptr->zero, level);
|
||||
print(ptr->zero, level, pkts);
|
||||
sum++;
|
||||
print(ptr->one, level);
|
||||
print(ptr->one, level, pkts);
|
||||
sum--;
|
||||
sum >>= 1;
|
||||
}
|
||||
|
||||
void radix_print(void) {
|
||||
void radix_print(int pkts) {
|
||||
if (!head)
|
||||
return;
|
||||
printf("\n");
|
||||
sum = 0;
|
||||
print(head->zero, 1);
|
||||
print(head->zero, 1, pkts);
|
||||
assert(sum == 0);
|
||||
sum = 1;
|
||||
print(head->one, 1);
|
||||
print(head->one, 1, pkts);
|
||||
assert(sum == 1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ typedef struct rnode_t {
|
|||
extern int radix_nodes;
|
||||
RNode *radix_longest_prefix_match(uint32_t ip);
|
||||
RNode*radix_add(uint32_t ip, uint32_t mask, char *name);
|
||||
void radix_print(void);
|
||||
void radix_print(int pkts);
|
||||
void radix_squash(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@
|
|||
199.9.248.0/21 Twitch
|
||||
199.16.156.0/22 Twitter
|
||||
199.59.148.0/22 Twitter
|
||||
199.168.96.24/29 BitChute
|
||||
205.185.194.0/24 Steam
|
||||
205.196.6.0/24 Steam
|
||||
207.45.72.0/22 Netflix
|
||||
|
|
@ -212,6 +213,19 @@
|
|||
208.80.152.0/22 Wikipedia
|
||||
209.140.128.0/18 eBay
|
||||
|
||||
# Imperva
|
||||
199.83.128.0/21 Imperva
|
||||
198.143.32.0/19 Imperva
|
||||
149.126.72.0/21 Imperva
|
||||
103.28.248.0/22 Imperva
|
||||
45.64.64.0/22 Imperva
|
||||
185.11.124.0/22 Imperva
|
||||
192.230.64.0/18 Imperva
|
||||
107.154.0.0/16 Imperva
|
||||
45.60.0.0/16 Imperva
|
||||
45.223.0.0/16 Imperva
|
||||
131.125.128.0/17 Imperva
|
||||
|
||||
# Level 3
|
||||
66.114.192.0/18 Level 3
|
||||
66.147.128.0/18 Level 3
|
||||
|
|
|
|||
52
src/fnettrace/terminal.c
Normal file
52
src/fnettrace/terminal.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2014-2023 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"
|
||||
#include <termios.h>
|
||||
|
||||
static struct termios tlocal; // startup terminal setting
|
||||
static struct termios twait; // no wait on key press
|
||||
static int tset = 0;
|
||||
|
||||
void terminal_restore(void) {
|
||||
if (tset)
|
||||
tcsetattr(0, TCSANOW, &tlocal);
|
||||
}
|
||||
|
||||
void terminal_handler(int s) {
|
||||
// Remove unused parameter warning
|
||||
(void)s;
|
||||
terminal_restore();
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
void terminal_set(void) {
|
||||
if (tset == 0) {
|
||||
tcgetattr(0, &twait); // get current terminal attributes; 0 is the file descriptor for stdin
|
||||
memcpy(&tlocal, &twait, sizeof(tlocal));
|
||||
twait.c_lflag &= ~ICANON; // disable canonical mode
|
||||
twait.c_lflag &= ~ECHO; // no echo
|
||||
twait.c_cc[VMIN] = 1; // wait until at least one keystroke available
|
||||
twait.c_cc[VTIME] = 0; // no timeout
|
||||
tset = 1;
|
||||
}
|
||||
tcsetattr(0, TCSANOW, &twait);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue