more on nettrace

This commit is contained in:
netblue30 2022-01-07 09:52:00 -05:00
parent c18d68f36d
commit 500a56efd3
10 changed files with 4595 additions and 63 deletions

View file

@ -138,6 +138,7 @@ endif
# profiles and settings
install -m 0755 -d $(DESTDIR)$(sysconfdir)/firejail
install -m 0644 -t $(DESTDIR)$(sysconfdir)/firejail src/firecfg/firecfg.config
install -m 0644 -t $(DESTDIR)$(sysconfdir)/firejail src/fnettrace/hostnames
install -m 0644 -t $(DESTDIR)$(sysconfdir)/firejail etc/profile-a-l/*.profile etc/profile-m-z/*.profile etc/inc/*.inc etc/net/*.net etc/firejail.config etc/ids.config
sh -c "if [ ! -f $(DESTDIR)/$(sysconfdir)/firejail/login.users ]; then install -c -m 0644 etc/login.users $(DESTDIR)/$(sysconfdir)/firejail/.; fi;"
ifeq ($(BUSYBOX_WORKAROUND),yes)

View file

@ -298,19 +298,23 @@ INTRUSION DETECTION SYSTEM (IDS)
### Network Monitor
`````
--nettrace=name|pid
--nettrace=name|pid
Monitor TCP and UDP traffic coming into the sandbox specified by
name or pid. Only networked sandboxes created with --net are
supported.
$ firejail --nettrace=browser
9.9.9.9:53 => 192.168.1.60 UDP: 122 B/sec
72.21.91.29:80 => 192.168.1.60 TCP: 257 B/sec
80.92.126.65:123 => 192.168.1.60 UDP: 25 B/sec
69.30.241.50:443 => 192.168.1.60 TCP: 88 KB/sec
140.82.112.4:443 => 192.168.1.60 TCP: 1861 B/sec
86 KB/s ********* 64.222.84.207:443 United States
76 KB/s ******** 192.229.210.163:443 MCI
111 B/s 9.9.9.9:53 Quad9 DNS
32 KB/s *** 142.250.179.182:443 Google
(14 streams in the last one minute)
If /usr/bin/geoiplookup is installed (geoip-bin packet in De
bian), the country the IP address originates from is added to
the trace. We also use the static IP map in /etc/firejail/host
names to print the domain names for some of the more common web
sites and cloud platforms. No external services are contacted
for reverse IP lookup.
`````

View file

@ -27,12 +27,14 @@
#include <netinet/in.h>
#include <time.h>
#include <stdarg.h>
//#define DEBUG 1
//#define NETLOCK_INTERVAL 15
#define NETLOCK_INTERVAL 60
#define DISPLAY_INTERVAL 3
#define DISPLAY_INTERVAL 2
#define DISPLAY_TTL 4
#define DISPLAY_BW_UNITS 20
void logprintf(char* fmt, ...);
static inline void ansi_topleft(void) {
char str[] = {0x1b, '[', '1', ';', '1', 'H', '\0'};
@ -53,6 +55,12 @@ static inline uint8_t hash(uint32_t ip) {
return *ptr ^ *(ptr + 1) ^ *(ptr + 2) ^ *(ptr + 3);
}
// main.c
void logprintf(char* fmt, ...);
// hostnames.c
void load_hostnames(const char *fname);
char* retrieve_hostname(uint32_t ip);
void build_list(const char *fname);
#endif

4029
src/fnettrace/hostnames Normal file

File diff suppressed because it is too large Load diff

120
src/fnettrace/hostnames.c Normal file
View file

@ -0,0 +1,120 @@
/*
* Copyright (C) 2014-2021 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 "radix.h"
#define MAXBUF 1024
char *retrieve_hostname(uint32_t ip) {
char *rv = NULL;
char *cmd;
if (asprintf(&cmd, "/usr/bin/geoiplookup %d.%d.%d.%d", PRINT_IP(ip)) == -1)
errExit("asprintf");
FILE *fp = popen(cmd, "r");
if (fp) {
char *ptr;
char buf[MAXBUF];
if (fgets(buf, MAXBUF, fp)) {
ptr = strchr(buf, '\n');
if (ptr)
*ptr = '\0';
if (strncmp(buf, "GeoIP Country Edition:", 22) == 0) {
ptr = buf + 22;
if (*ptr == ' ' && *(ptr + 3) == ',' && *(ptr + 4) == ' ') {
rv = ptr + 5;
radix_add(ip, 0xffffffff, ptr + 5);
}
}
}
fclose(fp);
return rv;
}
return NULL;
}
void load_hostnames(const char *fname) {
assert(fname);
FILE *fp = fopen(fname, "r");
if (!fp) {
fprintf(stderr, "Warning: cannot find %s file\n", fname);
return;
}
char buf[MAXBUF];
int line = 0;
while (fgets(buf, MAXBUF, fp)) {
line++;
// skip empty spaces
char *start = buf;
while (*start == ' ' || *start == '\t')
start++;
// comments
if (*start == '#')
continue;
char *end = strchr(start, '#');
if (end)
*end = '\0';
// end
end = strchr(start, '\n');
if (end)
*end = '\0';
end = start + strlen(start);
if (end == start) // empty line
continue;
// line format: 1.2.3.4/32 name_without_empty_spaces
// a single empty space between address and name
end = strchr(start, ' ');
if (!end)
goto errexit;
*end = '\0';
end++;
if (*end == '\0')
goto errexit;
uint32_t ip;
uint32_t mask;
if (atocidr(start, &ip, &mask)) {
fprintf(stderr, "Error: invalid CIDR address\n");
goto errexit;
}
radix_add(ip, mask, end);
}
fclose(fp);
return;
errexit:
fprintf(stderr, "Error: invalid line %d in file %s\n", line, fname);
exit(1);
}
void build_list(const char *fname) {
assert(fname);
load_hostnames(fname);
radix_build_list();
}

View file

@ -18,37 +18,42 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "fnettrace.h"
//#define DEBUG 1
#include "radix.h"
#include <sys/ioctl.h>
#define MAX_BUF_SIZE (64 * 1024)
static int arg_netfilter = 0;
static char *arg_log = NULL;
typedef struct hlist_t {
struct hlist_t *hnext; // used for hash table
struct hlist_t *dnext; // used to display stremas on the screen
typedef struct hnode_t {
struct hnode_t *hnext; // used for hash table
struct hnode_t *dnext; // used to display stremas on the screen
uint32_t ip_src;
uint32_t ip_dst;
uint64_t bytes; // number of bytes received in the last display interval
uint32_t bytes; // number of bytes received in the last display interval
uint16_t port_src;
uint16_t ip_instance;
// the firewall is build based on source address, and in the linked list
// we have elements with the same address but different ports
uint8_t protocol;
} HList;
// the firewall is build based on source address, and in the linked list
// we have elements with the same address but different ports
uint8_t ip_instance;
char *hostname;
int ttl;
} HNode;
// hash table
#define HMAX 256
HList *htable[HMAX] = {NULL};
HNode *htable[HMAX] = {NULL};
// display linked list
HList *dlist = NULL;
HNode *dlist = NULL;
static void hlist_add(uint32_t ip_src, uint32_t ip_dst, uint8_t protocol, uint16_t port_src, uint64_t bytes) {
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);
// find
int ip_instance = 0;
HList *ptr = htable[h];
HNode *ptr = htable[h];
while (ptr) {
if (ptr->ip_src == ip_src) {
ip_instance++;
@ -63,9 +68,10 @@ static void hlist_add(uint32_t ip_src, uint32_t ip_dst, uint8_t protocol, uint16
#ifdef DEBUG
printf("malloc %d.%d.%d.%d\n", PRINT_IP(ip_src));
#endif
HList *hnew = malloc(sizeof(HList));
HNode *hnew = malloc(sizeof(HNode));
if (!hnew)
errExit("malloc");
hnew->hostname = NULL;
hnew->ip_src = ip_src;
hnew->ip_dst = ip_dst;
hnew->port_src = port_src;
@ -73,6 +79,7 @@ static void hlist_add(uint32_t ip_src, uint32_t ip_dst, uint8_t protocol, uint16
hnew->hnext = NULL;
hnew->bytes = bytes;
hnew->ip_instance = ip_instance + 1;
hnew->ttl = DISPLAY_TTL;
if (htable[h] == NULL)
htable[h] = hnew;
else {
@ -95,17 +102,17 @@ static void hlist_add(uint32_t ip_src, uint32_t ip_dst, uint8_t protocol, uint16
logprintf(" %d.%d.%d.%d ", PRINT_IP(hnew->ip_src));
}
static void hlist_free(HList *elem) {
static void hnode_free(HNode *elem) {
assert(elem);
#ifdef DEBUG
printf("free %d.%d.%d.%d\n", PRINT_IP(elem->ip_src));
#endif
uint8_t h = hash(elem->ip_src);
HList *ptr = htable[h];
HNode *ptr = htable[h];
assert(ptr);
HList *prev = NULL;
HNode *prev = NULL;
while (ptr != elem) {
prev = ptr;
ptr = ptr->hnext;
@ -119,25 +126,45 @@ static void hlist_free(HList *elem) {
#ifdef DEBUG
static void debug_dlist(void) {
HList *ptr = dlist;
HNode *ptr = dlist;
while (ptr) {
printf("dlist %d.%d.%d.%d:%d\n", PRINT_IP(ptr->ip_src), ptr->port_src);
ptr = ptr->dnext;
}
}
static void debug_hlist(void) {
static void debug_hnode(void) {
int i;
for (i = 0; i < HMAX; i++) {
HList *ptr = htable[i];
HNode *ptr = htable[i];
while (ptr) {
printf("hlist (%d) %d.%d.%d.%d:%d\n", i, PRINT_IP(ptr->ip_src), ptr->port_src);
printf("hnode (%d) %d.%d.%d.%d:%d\n", i, PRINT_IP(ptr->ip_src), ptr->port_src);
ptr = ptr->hnext;
}
}
}
#endif
static void hlist_print(void) {
static char *bw_line[DISPLAY_BW_UNITS + 1] = { NULL };
static char *print_bw(unsigned units) {
if (units > DISPLAY_BW_UNITS)
units = DISPLAY_BW_UNITS ;
if (bw_line[units] == NULL) {
char *ptr = malloc(DISPLAY_BW_UNITS + 1);
if (!ptr)
errExit("malloc");
bw_line[units] = ptr;
unsigned i;
for (i = 0; i < DISPLAY_BW_UNITS; i++, ptr++)
sprintf(ptr, "%s", (i < units)? "*": " ");
}
return bw_line[units];
}
static void hnode_print(void) {
assert(!arg_netfilter);
ansi_clrscr();
@ -145,30 +172,66 @@ static void hlist_print(void) {
printf("*********************\n");
debug_dlist();
printf("-----------------------------\n");
debug_hlist();
debug_hnode();
printf("*********************\n");
#endif
HList *ptr = dlist;
HList *prev = NULL;
while (ptr) {
HList *next = ptr->dnext;
if (ptr->bytes) {
char ip_src[30];
sprintf(ip_src, "%d.%d.%d.%d:%u", PRINT_IP(ptr->ip_src), ptr->port_src);
char ip_dst[30];
sprintf(ip_dst, "%d.%d.%d.%d", PRINT_IP(ptr->ip_dst));
printf("%-22s => %-15s %s:",
ip_src,
ip_dst,
(ptr->protocol == 6)? "TCP": "UDP");
// get terminal size
struct winsize sz;
int col = 80;
if (isatty(STDIN_FILENO)) {
if (!ioctl(0, TIOCGWINSZ, &sz))
col = sz.ws_col;
}
#define LINE_MAX 200
char line[LINE_MAX + 1];
if (col > LINE_MAX)
col = LINE_MAX;
if (ptr->bytes > (DISPLAY_INTERVAL * 1024 * 2)) // > 2 KB/second
printf(" %lu KB/sec\n",
ptr->bytes / (DISPLAY_INTERVAL * 1024));
HNode *ptr = dlist;
HNode *prev = NULL;
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",
(unsigned) (ptr->bytes / (DISPLAY_INTERVAL * 1024* 1024)));
else if (ptr->bytes > (DISPLAY_INTERVAL * 1024 * 2)) // > 2 KB/second
sprintf(bytes, "%u KB/s",
(unsigned) (ptr->bytes / (DISPLAY_INTERVAL * 1024)));
else
printf(" %lu B/sec\n",
ptr->bytes / DISPLAY_INTERVAL);
sprintf(bytes, "%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 {
ptr->hostname = strdup(hostname);
if (!ptr->hostname)
errExit("strdup");
}
unsigned bwunit = bwmax / DISPLAY_BW_UNITS;
unsigned units = ptr->bytes / bwunit;
char *bwline = print_bw(units);
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';
}
printf("%s", line);
if (ptr->bytes)
ptr->ttl = DISPLAY_TTL;
ptr->bytes = 0;
prev = ptr;
}
@ -178,7 +241,7 @@ static void hlist_print(void) {
dlist = next;
else
prev->dnext = next;
hlist_free(ptr);
hnode_free(ptr);
}
ptr = next;
@ -199,14 +262,18 @@ static void run_trace(void) {
unsigned last_print_traces = 0;
unsigned last_print_remaining = 0;
unsigned char buf[MAX_BUF_SIZE];
unsigned bwcurrent = 0;
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)
hlist_print();
hnode_print();
last_print_traces = end;
bwcurrent = 0;
}
if (arg_netfilter && last_print_remaining != end) {
logprintf(".");
@ -233,6 +300,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
// filter out loopback traffic
if (buf[12] != 127) {
uint32_t ip_src;
@ -248,7 +316,7 @@ static void run_trace(void) {
memcpy(&port_src, buf + hlen, 2);
port_src = ntohs(port_src);
hlist_add(ip_src, ip_dst, buf[9], port_src, (uint64_t) bytes);
hnode_add(ip_src, ip_dst, buf[9], port_src, bytes + 14);
}
}
}
@ -274,7 +342,7 @@ static int print_filter(FILE *fp) {
int i;
for (i = 0; i < HMAX; i++) {
HList *ptr = htable[i];
HNode *ptr = htable[i];
while (ptr) {
// filter rules are targeting ip address, the port number is disregarded,
// so we look only at the first instance of an address
@ -416,6 +484,7 @@ void logprintf(char* fmt, ...) {
static void usage(void) {
printf("Usage: fnetlock [OPTIONS]\n");
printf("Options:\n");
printf(" --build=filename - compact list of addresses\n");
printf(" --help, -? - this help screen\n");
printf(" --netfilter - build the firewall rules and commit them.\n");
printf(" --log=filename - logfile\n");
@ -424,7 +493,26 @@ static void usage(void) {
int main(int argc, char **argv) {
int i;
printf("\n\n");
#ifdef DEBUG
// radix test
radix_add(0x09000000, 0xff000000, "IBM");
radix_add(0x09090909, 0xffffffff, "Quad9 DNS");
radix_add(0x09000000, 0xff000000, "IBM");
radix_print();
printf("This test should print \"IBM, Quad9 DNS, IBM\"\n");
char *name = radix_find_first(0x09090909);
printf("%s, ", name);
name = radix_find_last(0x09090909);
printf("%s, ", name);
name = radix_find_last(0x09322209);
printf("%s\n", name);
#endif
if (argc == 2 && strncmp(argv[1], "--build=", 8) == 0) {
build_list(argv[1] + 8);
return 0;
}
if (getuid() != 0) {
fprintf(stderr, "Error: you need to be root to run this program\n");
@ -449,6 +537,13 @@ int main(int argc, char **argv) {
ansi_clrscr();
if (arg_netfilter)
logprintf("starting network lockdown\n");
else {
char *fname;
if (asprintf(&fname, "%s/hostnames", SYSCONFDIR) == -1)
errExit("asprintf");
load_hostnames(fname);
free(fname);
}
run_trace();
if (arg_netfilter) {

218
src/fnettrace/radix.c Normal file
View file

@ -0,0 +1,218 @@
/*
* Copyright (C) 2014-2021 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>
#include "radix.h"
#include "fnettrace.h"
RNode *head = 0;
static inline RNode *addOne(RNode *ptr, uint32_t ip, uint32_t mask, char *name) {
assert(ptr);
if (ptr->one)
return ptr->one;
RNode *node = malloc(sizeof(RNode));
if (!node)
errExit("malloc");
memset(node, 0, sizeof(RNode));
node->ip = ip;
node->mask = mask;
if (name) {
node->name = strdup(name);
if (!node->name)
errExit("strdup");
}
ptr->one = node;
return node;
}
static inline RNode *addZero(RNode *ptr, uint32_t ip, uint32_t mask, char *name) {
assert(ptr);
if (ptr->zero)
return ptr->zero;
RNode *node = malloc(sizeof(RNode));
if (!node)
errExit("malloc");
memset(node, 0, sizeof(RNode));
node->ip = ip;
node->mask = mask;
if (name) {
node->name = strdup(name);
if (!node->name)
errExit("strdup");
}
ptr->zero = node;
return node;
}
// add to radix tree
void radix_add(uint32_t ip, uint32_t mask, char *name) {
assert(name);
char *tmp = strdup(name);
if (!tmp)
errExit("strdup");
name = tmp;
uint32_t m = 0x80000000;
uint32_t lastm = 0;
if (head == 0) {
head = malloc(sizeof(RNode));
memset(head, 0, sizeof(RNode));
}
RNode *ptr = head;
int i;
for (i = 0; i < 32; i++, m >>= 1) {
if (!(m & mask))
break;
lastm |= m;
int valid = (lastm == mask)? 1: 0;
if (m & ip)
ptr = addOne(ptr, ip & lastm, mask & lastm, (valid)? name: NULL);
else
ptr = addZero(ptr, ip & lastm, mask & lastm, (valid)? name: NULL);
}
assert(ptr);
if (!ptr->name) {
ptr->name = strdup(name);
if (!ptr->name)
errExit("strdup");
}
}
// find first match
char *radix_find_first(uint32_t ip) {
if (!head)
return NULL;
uint32_t m = 0x80000000;
RNode *ptr = head;
int i;
for (i = 0; i < 32; i++, m >>= 1) {
if (m & ip)
ptr = ptr->one;
else
ptr = ptr->zero;
if (!ptr)
return NULL;
if (ptr->name)
return ptr->name;
}
return NULL;
}
// find last match
char *radix_find_last(uint32_t ip) {
if (!head)
return NULL;
uint32_t m = 0x80000000;
RNode *ptr = head;
RNode *rv = NULL;
int i;
for (i = 0; i < 32; i++, m >>= 1) {
if (m & ip)
ptr = ptr->one;
else
ptr = ptr->zero;
if (!ptr)
break;
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(" ");
printf("%08x %08x", ptr->ip, ptr->mask);
if (ptr->name)
printf(" (%s)\n", ptr->name);
else
printf(" (NULL)\n");
if (ptr->zero)
radix_print_node(ptr->zero, level + 1);
if (ptr->one)
radix_print_node(ptr->one, level + 1);
}
void radix_print(void) {
if (!head) {
printf("radix tree is empty\n");
return;
}
printf("radix IPv4 tree\n");
radix_print_node(head, 0);
}
static inline int mask2cidr(uint32_t mask) {
uint32_t m = 0x80000000;
int i;
int cnt = 0;
for (i = 0; i < 32; i++, m = m >> 1) {
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;
}
else {
if (ptr->zero)
radix_build_list_node(ptr->zero);
if (ptr->one)
radix_build_list_node(ptr->one);
}
}
void radix_build_list(void) {
if (!head) {
printf("radix tree is empty\n");
return;
}
radix_build_list_node(head);
}

37
src/fnettrace/radix.h Normal file
View file

@ -0,0 +1,37 @@
/*
* Copyright (C) 2014-2021 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.
*/
#ifndef RADIX_H
#define RADIX_H
typedef struct rnode_t {
struct rnode_t *zero;
struct rnode_t *one;
uint32_t ip;
uint32_t mask;
char *name;
} RNode;
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);
void radix_print(void);
void radix_build_list(void);
#endif

View file

@ -73,6 +73,25 @@ static inline int atoip(const char *str, uint32_t *ip) {
return 0;
}
// read an IPv4 address in CIDR format, for example 192.168.1.0/24
static inline int atocidr(const char *str, uint32_t *ip, uint32_t *mask) {
unsigned a, b, c, d, e;
// extract ip
int rv = sscanf(str, "%u.%u.%u.%u/%u", &a, &b, &c, &d, &e);
if (rv != 5 || a > 255 || b > 255 || c > 255 || d > 255 || e > 32)
return 1;
*ip = a * 0x1000000 + b * 0x10000 + c * 0x100 + d;
// extract mask
uint32_t tmp;
unsigned i;
for (i = 0, *mask = 0, tmp = 0x80000000; i < e; i++, tmp >>= 1) {
*mask |= tmp;
}
return 0;
}
// verify an ip address is in the network range given by ifip and mask
static inline char *in_netrange(uint32_t ip, uint32_t ifip, uint32_t ifmask) {
if ((ip & ifmask) != (ifip & ifmask))

View file

@ -1488,20 +1488,21 @@ created with \-\-net are supported.
.br
$ firejail --nettrace=browser
.br
9.9.9.9:53 => 192.168.1.60 UDP: 122 B/sec
86 KB/s ********* 64.222.84.207:443 United States
.br
72.21.91.29:80 => 192.168.1.60 TCP: 257 B/sec
76 KB/s ******** 192.229.210.163:443 MCI
.br
80.92.126.65:123 => 192.168.1.60 UDP: 25 B/sec
111 B/s 9.9.9.9:53 Quad9 DNS
.br
69.30.241.50:443 => 192.168.1.60 TCP: 88 KB/sec
.br
140.82.112.4:443 => 192.168.1.60 TCP: 1861 B/sec
32 KB/s *** 142.250.179.182:443 Google
.br
.br
(14 streams in the last one minute)
If /usr/bin/geoiplookup is installed (geoip-bin packet in Debian),
the country the IP address originates from is added to the trace.
We also use the static IP map in /etc/firejail/hostnames
to print the domain names for some of the more common websites and cloud platforms.
No external services are contacted for reverse IP lookup.
#endif
.TP
\fB\-\-nice=value