diff options
author | 2022-09-27 12:12:43 -0400 | |
---|---|---|
committer | 2022-09-27 12:12:43 -0400 | |
commit | 1ac8ca3c6f6ea6a2002fba05e402e0eb3f47acd8 (patch) | |
tree | f6b64766fa975a9005fa58d47777e690d5baae42 /src/fnettrace | |
parent | Merge branch 'master' of ssh://github.com/netblue30/firejail (diff) | |
download | firejail-1ac8ca3c6f6ea6a2002fba05e402e0eb3f47acd8.tar.gz firejail-1ac8ca3c6f6ea6a2002fba05e402e0eb3f47acd8.tar.zst firejail-1ac8ca3c6f6ea6a2002fba05e402e0eb3f47acd8.zip |
ICMP support in --nettrace
Diffstat (limited to 'src/fnettrace')
-rw-r--r-- | src/fnettrace/main.c | 136 | ||||
-rw-r--r-- | src/fnettrace/static-ip-map | 9 |
2 files changed, 89 insertions, 56 deletions
diff --git a/src/fnettrace/main.c b/src/fnettrace/main.c index f5e9bea65..da5ac02c6 100644 --- a/src/fnettrace/main.c +++ b/src/fnettrace/main.c | |||
@@ -74,7 +74,7 @@ void hfree(HNode *ptr) { | |||
74 | hnode_unused = ptr; | 74 | hnode_unused = ptr; |
75 | } | 75 | } |
76 | 76 | ||
77 | 77 | // using protocol 0 and port 0 for ICMP | |
78 | static void hnode_add(uint32_t ip_src, uint8_t protocol, uint16_t port_src, uint32_t bytes) { | 78 | static void hnode_add(uint32_t ip_src, uint8_t protocol, uint16_t port_src, uint32_t bytes) { |
79 | uint8_t h = hash(ip_src); | 79 | uint8_t h = hash(ip_src); |
80 | 80 | ||
@@ -183,7 +183,7 @@ static char *print_bw(unsigned units) { | |||
183 | 183 | ||
184 | unsigned i; | 184 | unsigned i; |
185 | for (i = 0; i < DISPLAY_BW_UNITS; i++, ptr++) | 185 | for (i = 0; i < DISPLAY_BW_UNITS; i++, ptr++) |
186 | sprintf(ptr, "%s", (i < units)? "*": " "); | 186 | sprintf(ptr, "%s", (i < units) ? "*" : " "); |
187 | sprintf(ptr, "%s", " "); | 187 | sprintf(ptr, "%s", " "); |
188 | } | 188 | } |
189 | 189 | ||
@@ -196,7 +196,7 @@ static inline void adjust_line(char *str, int len, int cols) { | |||
196 | len = LINE_MAX; | 196 | len = LINE_MAX; |
197 | if (cols > 4 && len > cols) { | 197 | if (cols > 4 && len > cols) { |
198 | str[cols] = '\0'; | 198 | str[cols] = '\0'; |
199 | str[cols- 1] = '\n'; | 199 | str[cols - 1] = '\n'; |
200 | } | 200 | } |
201 | } | 201 | } |
202 | 202 | ||
@@ -211,18 +211,44 @@ static unsigned adjust_bandwidth(unsigned bw) { | |||
211 | unsigned max = 0; | 211 | unsigned max = 0; |
212 | for ( i = 0; i < BWMAX_CNT; i++) { | 212 | for ( i = 0; i < BWMAX_CNT; i++) { |
213 | sum += array[i]; | 213 | sum += array[i]; |
214 | max = (max > array[i])? max: array[i]; | 214 | max = (max > array[i]) ? max : array[i]; |
215 | } | 215 | } |
216 | sum /= BWMAX_CNT; | 216 | sum /= BWMAX_CNT; |
217 | 217 | ||
218 | if (++instance >= BWMAX_CNT) | 218 | if (++instance >= BWMAX_CNT) |
219 | instance = 0; | 219 | instance = 0; |
220 | 220 | ||
221 | return (max < (sum / 2))? sum: max; | 221 | return (max < (sum / 2)) ? sum : max; |
222 | } | 222 | } |
223 | 223 | ||
224 | typedef struct port_type_t { | ||
225 | uint16_t port; | ||
226 | char *service; | ||
227 | } PortType; | ||
228 | static PortType ports[] = { | ||
229 | {20, "(FTP)"}, | ||
230 | {21, "(FTP)"}, | ||
231 | {22, "(SSH)"}, | ||
232 | {23, "(telnet)"}, | ||
233 | {25, "(SMTP)"}, | ||
234 | {43, "(WHOIS)"}, | ||
235 | {67, "(DHCP)"}, | ||
236 | {68, "(DHCP)"}, | ||
237 | {69, "(TFTP)"}, | ||
238 | {80, "(HTTP)"}, | ||
239 | {109, "(POP2)"}, | ||
240 | {110, "(POP3)"}, | ||
241 | {113, "(IRC)"}, | ||
242 | {123, "(NTP)"}, | ||
243 | {161, "(SNP)"}, | ||
244 | {162, "(SNP)"}, | ||
245 | {194, "(IRC)"}, | ||
246 | {0, NULL}, | ||
247 | }; | ||
248 | |||
249 | |||
224 | static inline const char *common_port(uint16_t port) { | 250 | static inline const char *common_port(uint16_t port) { |
225 | if (port > 194) { | 251 | if (port >= 6660 && port <= 9150) { |
226 | if (port >= 6660 && port <= 6669) | 252 | if (port >= 6660 && port <= 6669) |
227 | return "(IRC)"; | 253 | return "(IRC)"; |
228 | else if (port == 6679) | 254 | else if (port == 6679) |
@@ -244,44 +270,23 @@ static inline const char *common_port(uint16_t port) { | |||
244 | return NULL; | 270 | return NULL; |
245 | } | 271 | } |
246 | 272 | ||
247 | if (port == 20 || port == 21) | 273 | if (port <= 194) { |
248 | return "(FTP)"; | 274 | PortType *ptr =&ports[0]; |
249 | else if (port == 22) | 275 | while(ptr->service != NULL) { |
250 | return "(SSH)"; | 276 | if (ptr->port == port) |
251 | else if (port == 23) | 277 | return ptr->service; |
252 | return "(telnet)"; | 278 | ptr++; |
253 | else if (port == 25) | 279 | } |
254 | return "(SMTP)"; | 280 | } |
255 | else if (port == 43) | ||
256 | return "(WHOIS)"; | ||
257 | else if (port == 67) | ||
258 | return "(DHCP)"; | ||
259 | else if (port == 69) | ||
260 | return "(TFTP)"; | ||
261 | else if (port == 80) | ||
262 | return "(HTTP)"; | ||
263 | else if (port == 109) | ||
264 | return "(POP2)"; | ||
265 | else if (port == 110) | ||
266 | return "(POP3)"; | ||
267 | else if (port == 113) | ||
268 | return "(IRC)"; | ||
269 | else if (port == 123) | ||
270 | return "(NTP)"; | ||
271 | else if (port == 161) | ||
272 | return "(SNMP)"; | ||
273 | else if (port == 162) | ||
274 | return "(SNMP)"; | ||
275 | else if (port == 194) | ||
276 | return "(IRC)"; | ||
277 | 281 | ||
278 | return NULL; | 282 | return NULL; |
279 | } | 283 | } |
280 | 284 | ||
281 | 285 | ||
286 | |||
282 | static void hnode_print(unsigned bw) { | 287 | static void hnode_print(unsigned bw) { |
283 | assert(!arg_netfilter); | 288 | assert(!arg_netfilter); |
284 | bw = (bw < 1024 * DISPLAY_INTERVAL)? 1024 * DISPLAY_INTERVAL: bw; | 289 | bw = (bw < 1024 * DISPLAY_INTERVAL) ? 1024 * DISPLAY_INTERVAL : bw; |
285 | #ifdef DEBUG | 290 | #ifdef DEBUG |
286 | printf("*********************\n"); | 291 | printf("*********************\n"); |
287 | debug_dlist(); | 292 | debug_dlist(); |
@@ -322,10 +327,10 @@ static void hnode_print(unsigned bw) { | |||
322 | char bytes[11]; | 327 | char bytes[11]; |
323 | if (ptr->bytes > (DISPLAY_INTERVAL * 1024 * 1024 * 2)) // > 2 MB/second | 328 | if (ptr->bytes > (DISPLAY_INTERVAL * 1024 * 1024 * 2)) // > 2 MB/second |
324 | snprintf(bytes, 11, "%u MB/s", | 329 | snprintf(bytes, 11, "%u MB/s", |
325 | (unsigned) (ptr->bytes / (DISPLAY_INTERVAL * 1024* 1024))); | 330 | (unsigned) (ptr->bytes / (DISPLAY_INTERVAL * 1024 * 1024))); |
326 | else if (ptr->bytes > (DISPLAY_INTERVAL * 1024 * 2)) // > 2 KB/second | 331 | else if (ptr->bytes > (DISPLAY_INTERVAL * 1024 * 2)) // > 2 KB/second |
327 | snprintf(bytes, 11, "%u KB/s", | 332 | snprintf(bytes, 11, "%u KB/s", |
328 | (unsigned) (ptr->bytes / (DISPLAY_INTERVAL * 1024))); | 333 | (unsigned) (ptr->bytes / (DISPLAY_INTERVAL * 1024))); |
329 | else | 334 | else |
330 | snprintf(bytes, 11, "%u B/s ", (unsigned) (ptr->bytes / DISPLAY_INTERVAL)); | 335 | snprintf(bytes, 11, "%u B/s ", (unsigned) (ptr->bytes / DISPLAY_INTERVAL)); |
331 | 336 | ||
@@ -363,9 +368,13 @@ static void hnode_print(unsigned bw) { | |||
363 | 368 | ||
364 | if (protocol == NULL) | 369 | if (protocol == NULL) |
365 | protocol = ""; | 370 | protocol = ""; |
371 | if (ptr->port_src == 0) | ||
372 | len = snprintf(line, LINE_MAX, "%10s %s %d.%d.%d.%d (ICMP) %s\n", | ||
373 | bytes, bwline, PRINT_IP(ptr->ip_src), ptr->hostname); | ||
374 | else | ||
375 | len = snprintf(line, LINE_MAX, "%10s %s %d.%d.%d.%d:%u%s %s\n", | ||
376 | bytes, bwline, PRINT_IP(ptr->ip_src), ptr->port_src, protocol, ptr->hostname); | ||
366 | 377 | ||
367 | len = snprintf(line, LINE_MAX, "%10s %s %d.%d.%d.%d:%u%s %s\n", | ||
368 | bytes, bwline, PRINT_IP(ptr->ip_src), ptr->port_src, protocol, ptr->hostname); | ||
369 | adjust_line(line, len, cols); | 378 | adjust_line(line, len, cols); |
370 | printf("%s", line); | 379 | printf("%s", line); |
371 | 380 | ||
@@ -399,6 +408,7 @@ static void hnode_print(unsigned bw) { | |||
399 | #endif | 408 | #endif |
400 | } | 409 | } |
401 | 410 | ||
411 | // trace rx traffic coming in | ||
402 | static void run_trace(void) { | 412 | static void run_trace(void) { |
403 | if (arg_netfilter) | 413 | if (arg_netfilter) |
404 | logprintf("accumulating traffic for %d seconds\n", NETLOCK_INTERVAL); | 414 | logprintf("accumulating traffic for %d seconds\n", NETLOCK_INTERVAL); |
@@ -406,7 +416,8 @@ static void run_trace(void) { | |||
406 | // trace only rx ipv4 tcp and upd | 416 | // trace only rx ipv4 tcp and upd |
407 | int s1 = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); | 417 | int s1 = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); |
408 | int s2 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); | 418 | int s2 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); |
409 | if (s1 < 0 || s2 < 0) | 419 | int s3 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); |
420 | if (s1 < 0 || s2 < 0 || s3 < 0) | ||
410 | errExit("socket"); | 421 | errExit("socket"); |
411 | 422 | ||
412 | unsigned start = time(NULL); | 423 | unsigned start = time(NULL); |
@@ -434,18 +445,29 @@ static void run_trace(void) { | |||
434 | FD_ZERO(&rfds); | 445 | FD_ZERO(&rfds); |
435 | FD_SET(s1, &rfds); | 446 | FD_SET(s1, &rfds); |
436 | FD_SET(s2, &rfds); | 447 | FD_SET(s2, &rfds); |
448 | FD_SET(s3, &rfds); | ||
437 | int maxfd = (s1 > s2) ? s1 : s2; | 449 | int maxfd = (s1 > s2) ? s1 : s2; |
438 | maxfd++; | 450 | maxfd = (s3 > maxfd) ? s3 : maxfd; |
451 | maxfd++; | ||
452 | |||
439 | struct timeval tv; | 453 | struct timeval tv; |
440 | tv.tv_sec = 1; | 454 | tv.tv_sec = 1; |
441 | tv.tv_usec = 0; | 455 | tv.tv_usec = 0; |
456 | |||
442 | int rv = select(maxfd, &rfds, NULL, NULL, &tv); | 457 | int rv = select(maxfd, &rfds, NULL, NULL, &tv); |
443 | if (rv < 0) | 458 | if (rv < 0) |
444 | errExit("select"); | 459 | errExit("select"); |
445 | else if (rv == 0) | 460 | else if (rv == 0) |
446 | continue; | 461 | continue; |
447 | 462 | ||
448 | int sock = (FD_ISSET(s1, &rfds)) ? s1 : s2; | 463 | int icmp = 0; |
464 | int sock = s1; | ||
465 | if (FD_ISSET(s2, &rfds)) | ||
466 | sock = s2; | ||
467 | else if (FD_ISSET(s3, &rfds)) { | ||
468 | sock = s3; | ||
469 | icmp = 1; | ||
470 | } | ||
449 | 471 | ||
450 | unsigned bytes = recvfrom(sock, buf, MAX_BUF_SIZE, 0, NULL, NULL); | 472 | unsigned bytes = recvfrom(sock, buf, MAX_BUF_SIZE, 0, NULL, NULL); |
451 | if (bytes >= 20) { // size of IP header | 473 | if (bytes >= 20) { // size of IP header |
@@ -470,12 +492,16 @@ static void run_trace(void) { | |||
470 | ip_src = ntohl(ip_src); | 492 | ip_src = ntohl(ip_src); |
471 | 493 | ||
472 | uint8_t hlen = (buf[0] & 0x0f) * 4; | 494 | uint8_t hlen = (buf[0] & 0x0f) * 4; |
473 | uint16_t port_src; | 495 | if (icmp) |
474 | memcpy(&port_src, buf + hlen, 2); | 496 | hnode_add(ip_src, 0, 0, bytes + 14); |
475 | port_src = ntohs(port_src); | 497 | else { |
476 | 498 | uint16_t port_src; | |
477 | uint8_t protocol = buf[9]; | 499 | memcpy(&port_src, buf + hlen, 2); |
478 | hnode_add(ip_src, protocol, port_src, bytes + 14); | 500 | port_src = ntohs(port_src); |
501 | |||
502 | uint8_t protocol = buf[9]; | ||
503 | hnode_add(ip_src, protocol, port_src, bytes + 14); | ||
504 | } | ||
479 | } | 505 | } |
480 | } | 506 | } |
481 | } | 507 | } |
@@ -506,7 +532,7 @@ static int print_filter(FILE *fp) { | |||
506 | // filter rules are targeting ip address, the port number is disregarded, | 532 | // filter rules are targeting ip address, the port number is disregarded, |
507 | // so we look only at the first instance of an address | 533 | // so we look only at the first instance of an address |
508 | if (ptr->ip_instance == 1) { | 534 | if (ptr->ip_instance == 1) { |
509 | char *protocol = (ptr->protocol == 6)? "tcp": "udp"; | 535 | char *protocol = (ptr->protocol == 6) ? "tcp" : "udp"; |
510 | fprintf(fp, "-A INPUT -s %d.%d.%d.%d -p %s -j ACCEPT\n", | 536 | fprintf(fp, "-A INPUT -s %d.%d.%d.%d -p %s -j ACCEPT\n", |
511 | PRINT_IP(ptr->ip_src), | 537 | PRINT_IP(ptr->ip_src), |
512 | protocol); | 538 | protocol); |
@@ -583,7 +609,7 @@ static void deploy_netfilter(void) { | |||
583 | exit(1); | 609 | exit(1); |
584 | } | 610 | } |
585 | 611 | ||
586 | FILE* fp = fdopen(fd, "w"); | 612 | FILE *fp = fdopen(fd, "w"); |
587 | if (!fp) { | 613 | if (!fp) { |
588 | rv = unlink(fname); | 614 | rv = unlink(fname); |
589 | (void) rv; | 615 | (void) rv; |
@@ -621,21 +647,21 @@ static void deploy_netfilter(void) { | |||
621 | logprintf("\nfirewall deployed\n"); | 647 | logprintf("\nfirewall deployed\n"); |
622 | } | 648 | } |
623 | 649 | ||
624 | void logprintf(char* fmt, ...) { | 650 | void logprintf(char *fmt, ...) { |
625 | if (!arg_log) | 651 | if (!arg_log) |
626 | return; | 652 | return; |
627 | 653 | ||
628 | FILE *fp = fopen(arg_log, "a"); | 654 | FILE *fp = fopen(arg_log, "a"); |
629 | if (fp) { // disregard if error | 655 | if (fp) { // disregard if error |
630 | va_list args; | 656 | va_list args; |
631 | va_start(args,fmt); | 657 | va_start(args, fmt); |
632 | vfprintf(fp, fmt, args); | 658 | vfprintf(fp, fmt, args); |
633 | va_end(args); | 659 | va_end(args); |
634 | fclose(fp); | 660 | fclose(fp); |
635 | } | 661 | } |
636 | 662 | ||
637 | va_list args; | 663 | va_list args; |
638 | va_start(args,fmt); | 664 | va_start(args, fmt); |
639 | vfprintf(stdout, fmt, args); | 665 | vfprintf(stdout, fmt, args); |
640 | va_end(args); | 666 | va_end(args); |
641 | } | 667 | } |
diff --git a/src/fnettrace/static-ip-map b/src/fnettrace/static-ip-map index d1ce29dac..dfde16f6e 100644 --- a/src/fnettrace/static-ip-map +++ b/src/fnettrace/static-ip-map | |||
@@ -65,9 +65,13 @@ | |||
65 | 214.0.0.0/8 US Army | 65 | 214.0.0.0/8 US Army |
66 | 215.0.0.0/8 US Army | 66 | 215.0.0.0/8 US Army |
67 | 67 | ||
68 | # whois/DNS | 68 | # DNS |
69 | 1.1.1.0/24 Cloudflare DNS | 69 | 1.1.1.0/24 Cloudflare DNS |
70 | 1.0.0.0/24 Cloudflare DNS | 70 | 1.0.0.0/24 Cloudflare DNS |
71 | 4.2.2.1/32 Level3 DNS | ||
72 | 4.2.2.2/32 Level3 DNS | ||
73 | 4.2.2.3/32 Level3 DNS | ||
74 | 4.2.2.4/32 Level3 DNS | ||
71 | 8.8.4.0/24 Google DNS | 75 | 8.8.4.0/24 Google DNS |
72 | 8.8.8.0/24 Google DNS | 76 | 8.8.8.0/24 Google DNS |
73 | 9.9.9.0/24 Quad9 DNS | 77 | 9.9.9.0/24 Quad9 DNS |
@@ -76,6 +80,9 @@ | |||
76 | 149.112.120.0/21 CIRA DNS Canada | 80 | 149.112.120.0/21 CIRA DNS Canada |
77 | 176.103.128.0/19 Adguard DNS | 81 | 176.103.128.0/19 Adguard DNS |
78 | 185.228.168.0/24 Cleanbrowsing DNS | 82 | 185.228.168.0/24 Cleanbrowsing DNS |
83 | 208.67.216.0/21 OpenDNS | ||
84 | |||
85 | # whois | ||
79 | 193.0.0.0/21 whois.ripe.net Netherlands | 86 | 193.0.0.0/21 whois.ripe.net Netherlands |
80 | 199.5.26.0/24 whois.arin.net US | 87 | 199.5.26.0/24 whois.arin.net US |
81 | 199.15.80.0/21 whois.publicinterestregistry.net Canada | 88 | 199.15.80.0/21 whois.publicinterestregistry.net Canada |