aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@protonmail.com>2022-10-24 08:35:01 -0400
committerLibravatar netblue30 <netblue30@protonmail.com>2022-10-24 08:35:01 -0400
commit729b1251cd1783a0bc72a96ebc5aba455ccb375f (patch)
tree4abb82b3883dc4d1ce5261815f7e53fd8bc4cc3c
parentMerge pull request #5431 from netblue30/musl_warnings (diff)
downloadfirejail-729b1251cd1783a0bc72a96ebc5aba455ccb375f.tar.gz
firejail-729b1251cd1783a0bc72a96ebc5aba455ccb375f.tar.zst
firejail-729b1251cd1783a0bc72a96ebc5aba455ccb375f.zip
--icmptrace
-rw-r--r--Makefile1
-rw-r--r--README.md23
-rw-r--r--RELNOTES2
-rw-r--r--src/firejail/main.c38
-rw-r--r--src/fnettrace-icmp/Makefile17
-rw-r--r--src/fnettrace-icmp/fnettrace_icmp.h34
-rw-r--r--src/fnettrace-icmp/main.c215
-rw-r--r--src/man/firejail.txt40
8 files changed, 362 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index 5784aa8b2..0499ff170 100644
--- a/Makefile
+++ b/Makefile
@@ -14,6 +14,7 @@ SBOX_APPS = src/fbuilder/fbuilder src/ftee/ftee src/fids/fids
14SBOX_APPS_NON_DUMPABLE = src/fcopy/fcopy src/fldd/fldd src/fnet/fnet src/fnetfilter/fnetfilter src/fzenity/fzenity 14SBOX_APPS_NON_DUMPABLE = src/fcopy/fcopy src/fldd/fldd src/fnet/fnet src/fnetfilter/fnetfilter src/fzenity/fzenity
15SBOX_APPS_NON_DUMPABLE += src/fsec-optimize/fsec-optimize src/fsec-print/fsec-print src/fseccomp/fseccomp 15SBOX_APPS_NON_DUMPABLE += src/fsec-optimize/fsec-optimize src/fsec-print/fsec-print src/fseccomp/fseccomp
16SBOX_APPS_NON_DUMPABLE += src/fnettrace/fnettrace src/fnettrace-dns/fnettrace-dns src/fnettrace-sni/fnettrace-sni 16SBOX_APPS_NON_DUMPABLE += src/fnettrace/fnettrace src/fnettrace-dns/fnettrace-dns src/fnettrace-sni/fnettrace-sni
17SBOX_APPS_NON_DUMPABLE += src/fnettrace-icmp/fnettrace-icmp
17MYDIRS = src/lib $(MAN_SRC) $(COMPLETIONDIRS) 18MYDIRS = src/lib $(MAN_SRC) $(COMPLETIONDIRS)
18MYLIBS = src/libpostexecseccomp/libpostexecseccomp.so src/libtrace/libtrace.so src/libtracelog/libtracelog.so 19MYLIBS = src/libpostexecseccomp/libpostexecseccomp.so src/libtrace/libtrace.so src/libtracelog/libtracelog.so
19COMPLETIONS = src/zsh_completion/_firejail src/bash_completion/firejail.bash_completion 20COMPLETIONS = src/zsh_completion/_firejail src/bash_completion/firejail.bash_completion
diff --git a/README.md b/README.md
index 7acdcd1f1..023436e0d 100644
--- a/README.md
+++ b/README.md
@@ -272,6 +272,29 @@ Milestone page: https://github.com/netblue30/firejail/milestone/1
272 07:53:10 192.0.77.2 i0.wp.com 272 07:53:10 192.0.77.2 i0.wp.com
273 07:53:11 192.0.73.2 1.gravatar.com 273 07:53:11 192.0.73.2 1.gravatar.com
274````` 274`````
275### icmptrace
276`````
277 --icmptrace[=name|pid]
278 Monitor ICMP traffic. The sandbox can be specified by name or
279 pid. Only networked sandboxes created with --net are supported.
280 This option is only available when running the sandbox as root.
281
282 Without a name/pid, Firejail will monitor the main system net‐
283 work namespace.
284
285 Example
286 $ sudo firejail --icmptrace
287 20:53:54 192.168.1.60 -> 142.250.65.174 - 98 bytes - Echo re‐
288 quest/0
289 20:53:54 142.250.65.174 -> 192.168.1.60 - 98 bytes - Echo re‐
290 ply/0
291 20:53:55 192.168.1.60 -> 142.250.65.174 - 98 bytes - Echo re‐
292 quest/0
293 20:53:55 142.250.65.174 -> 192.168.1.60 - 98 bytes - Echo re‐
294 ply/0
295 20:53:55 192.168.1.60 -> 1.1.1.1 - 154 bytes - Destination un‐
296 reachable/Port unreachable
297`````
275 298
276### Profile Statistics 299### Profile Statistics
277 300
diff --git a/RELNOTES b/RELNOTES
index 366083739..5d8dc2365 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -7,7 +7,7 @@ firejail (0.9.71) baseline; urgency=low
7 * feature: support for custom AppArmor profiles (--apparmor=) (#5274 #5316 7 * feature: support for custom AppArmor profiles (--apparmor=) (#5274 #5316
8 #5317) 8 #5317)
9 * feature: added support for ICMP in nettrace 9 * feature: added support for ICMP in nettrace
10 * feature: --dnstrace and --snitrace 10 * feature: --dnstrace, --icmptrace, and --snitrace
11 * modif: removed --cgroup= command (#5190 #5200) 11 * modif: removed --cgroup= command (#5190 #5200)
12 * modif: set --shell=none as the default (#5190) 12 * modif: set --shell=none as the default (#5190)
13 * modif: removed --shell= command (#5190 #5196 #5209) 13 * modif: removed --shell= command (#5190 #5196 #5209)
diff --git a/src/firejail/main.c b/src/firejail/main.c
index fe80c5e2e..ed5b4901b 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -450,13 +450,13 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
450 exit_err_feature("networking"); 450 exit_err_feature("networking");
451 exit(0); 451 exit(0);
452 } 452 }
453 else if (strncmp(argv[i], "--dnstrace=", 15) == 0) { 453 else if (strncmp(argv[i], "--dnstrace=", 11) == 0) {
454 if (checkcfg(CFG_NETWORK)) { 454 if (checkcfg(CFG_NETWORK)) {
455 if (getuid() != 0) { 455 if (getuid() != 0) {
456 fprintf(stderr, "Error: --dnstrace is only available to root user\n"); 456 fprintf(stderr, "Error: --dnstrace is only available to root user\n");
457 exit(1); 457 exit(1);
458 } 458 }
459 pid_t pid = require_pid(argv[i] + 15); 459 pid_t pid = require_pid(argv[i] + 11);
460 netfilter_trace(pid, LIBDIR "/firejail/fnettrace-dns"); 460 netfilter_trace(pid, LIBDIR "/firejail/fnettrace-dns");
461 } 461 }
462 else 462 else
@@ -475,19 +475,49 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
475 exit_err_feature("networking"); 475 exit_err_feature("networking");
476 exit(0); 476 exit(0);
477 } 477 }
478 else if (strncmp(argv[i], "--snitrace=", 15) == 0) { 478 else if (strncmp(argv[i], "--snitrace=", 11) == 0) {
479 if (checkcfg(CFG_NETWORK)) { 479 if (checkcfg(CFG_NETWORK)) {
480 if (getuid() != 0) { 480 if (getuid() != 0) {
481 fprintf(stderr, "Error: --snitrace is only available to root user\n"); 481 fprintf(stderr, "Error: --snitrace is only available to root user\n");
482 exit(1); 482 exit(1);
483 } 483 }
484 pid_t pid = require_pid(argv[i] + 15); 484 pid_t pid = require_pid(argv[i] + 11);
485 netfilter_trace(pid, LIBDIR "/firejail/fnettrace-sni"); 485 netfilter_trace(pid, LIBDIR "/firejail/fnettrace-sni");
486 } 486 }
487 else 487 else
488 exit_err_feature("networking"); 488 exit_err_feature("networking");
489 exit(0); 489 exit(0);
490 } 490 }
491
492
493 else if (strcmp(argv[i], "--icmptrace") == 0) {
494 if (checkcfg(CFG_NETWORK)) {
495 if (getuid() != 0) {
496 fprintf(stderr, "Error: --icmptrace is only available to root user\n");
497 exit(1);
498 }
499 netfilter_trace(0, LIBDIR "/firejail/fnettrace-icmp");
500 }
501 else
502 exit_err_feature("networking");
503 exit(0);
504 }
505 else if (strncmp(argv[i], "--icmptrace=", 12) == 0) {
506 if (checkcfg(CFG_NETWORK)) {
507 if (getuid() != 0) {
508 fprintf(stderr, "Error: -icmptrace is only available to root user\n");
509 exit(1);
510 }
511 pid_t pid = require_pid(argv[i] + 12);
512 netfilter_trace(pid, LIBDIR "/firejail/fnettrace-icmp");
513 }
514 else
515 exit_err_feature("networking");
516 exit(0);
517 }
518
519
520
491 else if (strncmp(argv[i], "--bandwidth=", 12) == 0) { 521 else if (strncmp(argv[i], "--bandwidth=", 12) == 0) {
492 if (checkcfg(CFG_NETWORK)) { 522 if (checkcfg(CFG_NETWORK)) {
493 logargs(argc, argv); 523 logargs(argc, argv);
diff --git a/src/fnettrace-icmp/Makefile b/src/fnettrace-icmp/Makefile
new file mode 100644
index 000000000..4dfdc891a
--- /dev/null
+++ b/src/fnettrace-icmp/Makefile
@@ -0,0 +1,17 @@
1.PHONY: all
2all: fnettrace-icmp
3
4ROOT = ../..
5include $(ROOT)/src/common.mk
6
7%.o : %.c $(H_FILE_LIST) $(ROOT)/config.mk
8 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
9
10fnettrace-icmp: $(OBJS) $(ROOT)/config.mk
11 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
12
13.PHONY: clean
14clean:; rm -fr *.o fnettrace-icmp *.gcov *.gcda *.gcno *.plist
15
16.PHONY: distclean
17distclean: clean
diff --git a/src/fnettrace-icmp/fnettrace_icmp.h b/src/fnettrace-icmp/fnettrace_icmp.h
new file mode 100644
index 000000000..790a3ce7f
--- /dev/null
+++ b/src/fnettrace-icmp/fnettrace_icmp.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2014-2022 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#ifndef FNETTRACE_SNI_H
21#define FNETTRACE_SNI_H
22
23#include "../include/common.h"
24#include <unistd.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <netinet/in.h>
29#include <time.h>
30#include <stdarg.h>
31#include <fcntl.h>
32#include <sys/mman.h>
33
34#endif \ No newline at end of file
diff --git a/src/fnettrace-icmp/main.c b/src/fnettrace-icmp/main.c
new file mode 100644
index 000000000..47d61a326
--- /dev/null
+++ b/src/fnettrace-icmp/main.c
@@ -0,0 +1,215 @@
1/*
2 * Copyright (C) 2014-2022 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_icmp.h"
21#include <sys/ioctl.h>
22#include <time.h>
23#include <linux/filter.h>
24#include <linux/if_ether.h>
25#define MAX_BUF_SIZE (64 * 1024)
26
27char *type_description[19] = {
28 "Echo reply",
29 "unassigned",
30 "unassigned",
31 "Destination unreachable",
32 "Source quench",
33 "Redirect message",
34 "unassigned",
35 "unassigned",
36 "Echo request",
37 "Router advertisement",
38 "Router solicitation"
39 "Time exceeded",
40 "Bad IP header",
41 "Timestamp",
42 "Timestamp replay",
43 "Information request",
44 "Information reply",
45 "Address mask request",
46 "Address mask reply"
47};
48
49char *code_dest_unreachable[16] = {
50 "Network unreachable",
51 "Host unreachable",
52 "Protocol unreachable",
53 "Port unreachable",
54 "Fragmentation required, and DF flag set",
55 "Source route failed",
56 "Network unknown",
57 "Host unknown",
58 "Source host isolated",
59 "Network administratively prohibited",
60 "Host administratively prohibited",
61 "Network unreachable for ToS",
62 "Host unreachable for ToS",
63 "Communication administratively prohibited",
64 "Host Precedence Violation",
65 "Precedence cutoff in effect "
66};
67
68char *code_redirect_message[4] = {
69 "Datagram for the Network",
70 "Datagram for the Host",
71 "Datagram for the ToS & network",
72 "Datagram for the ToS & host "
73};
74
75char *code_time_exceeded[2] = {
76 "TTL expired in transit",
77 "Fragment reassembly time exceeded "
78};
79
80char *code_bad_ip_header[3] = {
81 "Pointer indicates the error",
82 "Missing a required option",
83 "Bad length"
84};
85
86static void print_icmp(uint32_t ip_dest, uint32_t ip_src, uint8_t type, uint8_t code, unsigned icmp_bytes) {
87 char type_number[10];
88 char *type_ptr = type_number;
89 if (type < 19)
90 type_ptr = type_description[type];
91 else
92 sprintf(type_number, "%u", type);
93
94 char code_number[10];
95 char *code_ptr = code_number;
96 if (type ==3 && code < 16)
97 code_ptr = code_dest_unreachable[code];
98 else if (type == 5 && code < 4)
99 code_ptr = code_redirect_message[code];
100 else if (type == 11 && code < 2)
101 code_ptr = code_time_exceeded[code];
102 else if (type == 12 && code < 3)
103 code_ptr = code_bad_ip_header[code];
104 else
105 sprintf(code_number, "%u", code);
106
107 time_t seconds = time(NULL);
108 struct tm *t = localtime(&seconds);
109 printf("%02d:%02d:%02d %d.%d.%d.%d -> %d.%d.%d.%d - %u bytes - %s/%s\n",
110 t->tm_hour, t->tm_min, t->tm_sec,
111 PRINT_IP(ip_src),
112 PRINT_IP(ip_dest),
113 icmp_bytes,
114 type_ptr,
115 code_ptr);
116}
117
118// https://www.kernel.org/doc/html/latest/networking/filter.html
119static void custom_bpf(int sock) {
120 struct sock_filter code[] = {
121 // sudo tcpdump "icmp" -dd
122 { 0x28, 0, 0, 0x0000000c },
123 { 0x15, 0, 3, 0x00000800 },
124 { 0x30, 0, 0, 0x00000017 },
125 { 0x15, 0, 1, 0x00000001 },
126 { 0x6, 0, 0, 0x00040000 },
127 { 0x6, 0, 0, 0x00000000 },
128 };
129
130 struct sock_fprog bpf = {
131 .len = (unsigned short) sizeof(code) / sizeof(code[0]),
132 .filter = code,
133 };
134
135 int rv = setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));
136 if (rv < 0) {
137 fprintf(stderr, "Error: cannot attach BPF filter\n");
138 exit(1);
139 }
140}
141
142static void run_trace(void) {
143 // grab all Ethernet packets and use a custom BPF filter to get TLS/SNI packets
144 int s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
145 if (s < 0)
146 errExit("socket");
147 custom_bpf(s);
148
149 unsigned char buf[MAX_BUF_SIZE];
150 while (1) {
151 fd_set rfds;
152 FD_ZERO(&rfds);
153 FD_SET(s, &rfds);
154 struct timeval tv;
155 tv.tv_sec = 1;
156 tv.tv_usec = 0;
157 int rv = select(s + 1, &rfds, NULL, NULL, &tv);
158 if (rv < 0)
159 errExit("select");
160 else if (rv == 0)
161 continue;
162 unsigned bytes = recvfrom(s, buf, MAX_BUF_SIZE, 0, NULL, NULL);
163
164 if (bytes >= (14 + 20 + 2)) { // size of MAC + IP + ICMP code and type fields
165 uint8_t ip_hlen = (buf[14] & 0x0f) * 4;
166 uint8_t type = *(buf + 14 +ip_hlen);
167 uint8_t code = *(buf + 14 + ip_hlen + 1);
168
169 uint32_t ip_dest;
170 memcpy(&ip_dest, buf + 14 + 16, 4);
171 ip_dest = ntohl(ip_dest);
172 uint32_t ip_src;
173 memcpy(&ip_src, buf + 14 + 12, 4);
174 ip_src = ntohl(ip_src);
175
176 print_icmp(ip_dest, ip_src, type, code, bytes);
177 }
178 }
179
180 close(s);
181}
182
183
184static void usage(void) {
185 printf("Usage: fnettrace-icmp [OPTIONS]\n");
186 printf("Options:\n");
187 printf(" --help, -? - this help screen\n");
188 printf("\n");
189}
190
191int main(int argc, char **argv) {
192 int i;
193
194 for (i = 1; i < argc; i++) {
195 if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-?") == 0) {
196 usage();
197 return 0;
198 }
199 else {
200 fprintf(stderr, "Error: invalid argument\n");
201 return 1;
202 }
203 }
204
205 if (getuid() != 0) {
206 fprintf(stderr, "Error: you need to be root to run this program\n");
207 return 1;
208 }
209
210 time_t now = time(NULL);
211 printf("ICMP trace for %s\n", ctime(&now));
212 run_trace();
213
214 return 0;
215}
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index a7e418981..b4be1cd62 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -791,7 +791,9 @@ Without a name/pid, Firejail will monitor the main system network namespace.
791.br 791.br
792 792
793.br 793.br
794$ sudo firejail --dnstrace=browser 794Example:
795.br
796$ sudo firejail --dnstrace
795.br 797.br
79611:31:43 9.9.9.9 linux.com (type 1) 79811:31:43 9.9.9.9 linux.com (type 1)
797.br 799.br
@@ -917,6 +919,34 @@ $ firejail --ignore=seccomp --ignore=caps firefox
917$ firejail \-\-ignore="net eth0" firefox 919$ firejail \-\-ignore="net eth0" firefox
918#endif 920#endif
919 921
922#ifdef HAVE_NETWORK
923.TP
924\fB\-\-icmptrace[=name|pid]
925Monitor ICMP traffic. The sandbox can be specified by name or pid. Only networked sandboxes
926created with \-\-net are supported. This option is only available when running the sandbox as root.
927.br
928
929.br
930Without a name/pid, Firejail will monitor the main system network namespace.
931.br
932
933.br
934Example
935.br
936$ sudo firejail --icmptrace
937.br
93820:53:54 192.168.1.60 -> 142.250.65.174 - 98 bytes - Echo request/0
939.br
94020:53:54 142.250.65.174 -> 192.168.1.60 - 98 bytes - Echo reply/0
941.br
94220:53:55 192.168.1.60 -> 142.250.65.174 - 98 bytes - Echo request/0
943.br
94420:53:55 142.250.65.174 -> 192.168.1.60 - 98 bytes - Echo reply/0
945.br
94620:53:55 192.168.1.60 -> 1.1.1.1 - 154 bytes - Destination unreachable/Port unreachable
947.br
948#endif
949
920.TP 950.TP
921\fB\-\-\include=file.profile 951\fB\-\-\include=file.profile
922Include a profile file before the regular profiles are used. 952Include a profile file before the regular profiles are used.
@@ -1597,7 +1627,9 @@ Without a name/pid, Firejail will monitor the main system network namespace.
1597.br 1627.br
1598 1628
1599.br 1629.br
1600$ sudo firejail --nettrace=browser 1630Example:
1631.br
1632$ sudo firejail --nettrace
1601.br 1633.br
1602 95 KB/s geoip 457, IP database 4436 1634 95 KB/s geoip 457, IP database 4436
1603.br 1635.br
@@ -2791,7 +2823,9 @@ Without a name/pid, Firejail will monitor the main system network namespace.
2791.br 2823.br
2792 2824
2793.br 2825.br
2794$ sudo firejail --snitrace=browser 2826Example:
2827.br
2828$ sudo firejail --snitrace
2795.br 2829.br
279607:49:51 23.185.0.3 linux.com 283007:49:51 23.185.0.3 linux.com
2797.br 2831.br