mirror of
https://github.com/netblue30/firejail.git
synced 2026-05-15 14:16:14 -06:00
--icmptrace
This commit is contained in:
parent
730739d89e
commit
729b1251cd
8 changed files with 362 additions and 8 deletions
1
Makefile
1
Makefile
|
|
@ -14,6 +14,7 @@ SBOX_APPS = src/fbuilder/fbuilder src/ftee/ftee src/fids/fids
|
|||
SBOX_APPS_NON_DUMPABLE = src/fcopy/fcopy src/fldd/fldd src/fnet/fnet src/fnetfilter/fnetfilter src/fzenity/fzenity
|
||||
SBOX_APPS_NON_DUMPABLE += src/fsec-optimize/fsec-optimize src/fsec-print/fsec-print src/fseccomp/fseccomp
|
||||
SBOX_APPS_NON_DUMPABLE += src/fnettrace/fnettrace src/fnettrace-dns/fnettrace-dns src/fnettrace-sni/fnettrace-sni
|
||||
SBOX_APPS_NON_DUMPABLE += src/fnettrace-icmp/fnettrace-icmp
|
||||
MYDIRS = src/lib $(MAN_SRC) $(COMPLETIONDIRS)
|
||||
MYLIBS = src/libpostexecseccomp/libpostexecseccomp.so src/libtrace/libtrace.so src/libtracelog/libtracelog.so
|
||||
COMPLETIONS = src/zsh_completion/_firejail src/bash_completion/firejail.bash_completion
|
||||
|
|
|
|||
23
README.md
23
README.md
|
|
@ -272,6 +272,29 @@ Milestone page: https://github.com/netblue30/firejail/milestone/1
|
|||
07:53:10 192.0.77.2 i0.wp.com
|
||||
07:53:11 192.0.73.2 1.gravatar.com
|
||||
`````
|
||||
### icmptrace
|
||||
`````
|
||||
--icmptrace[=name|pid]
|
||||
Monitor ICMP traffic. The sandbox can be specified by name or
|
||||
pid. Only networked sandboxes created with --net are supported.
|
||||
This option is only available when running the sandbox as root.
|
||||
|
||||
Without a name/pid, Firejail will monitor the main system net‐
|
||||
work namespace.
|
||||
|
||||
Example
|
||||
$ sudo firejail --icmptrace
|
||||
20:53:54 192.168.1.60 -> 142.250.65.174 - 98 bytes - Echo re‐
|
||||
quest/0
|
||||
20:53:54 142.250.65.174 -> 192.168.1.60 - 98 bytes - Echo re‐
|
||||
ply/0
|
||||
20:53:55 192.168.1.60 -> 142.250.65.174 - 98 bytes - Echo re‐
|
||||
quest/0
|
||||
20:53:55 142.250.65.174 -> 192.168.1.60 - 98 bytes - Echo re‐
|
||||
ply/0
|
||||
20:53:55 192.168.1.60 -> 1.1.1.1 - 154 bytes - Destination un‐
|
||||
reachable/Port unreachable
|
||||
`````
|
||||
|
||||
### Profile Statistics
|
||||
|
||||
|
|
|
|||
2
RELNOTES
2
RELNOTES
|
|
@ -7,7 +7,7 @@ firejail (0.9.71) baseline; urgency=low
|
|||
* feature: support for custom AppArmor profiles (--apparmor=) (#5274 #5316
|
||||
#5317)
|
||||
* feature: added support for ICMP in nettrace
|
||||
* feature: --dnstrace and --snitrace
|
||||
* feature: --dnstrace, --icmptrace, and --snitrace
|
||||
* modif: removed --cgroup= command (#5190 #5200)
|
||||
* modif: set --shell=none as the default (#5190)
|
||||
* modif: removed --shell= command (#5190 #5196 #5209)
|
||||
|
|
|
|||
|
|
@ -450,13 +450,13 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
|
|||
exit_err_feature("networking");
|
||||
exit(0);
|
||||
}
|
||||
else if (strncmp(argv[i], "--dnstrace=", 15) == 0) {
|
||||
else if (strncmp(argv[i], "--dnstrace=", 11) == 0) {
|
||||
if (checkcfg(CFG_NETWORK)) {
|
||||
if (getuid() != 0) {
|
||||
fprintf(stderr, "Error: --dnstrace is only available to root user\n");
|
||||
exit(1);
|
||||
}
|
||||
pid_t pid = require_pid(argv[i] + 15);
|
||||
pid_t pid = require_pid(argv[i] + 11);
|
||||
netfilter_trace(pid, LIBDIR "/firejail/fnettrace-dns");
|
||||
}
|
||||
else
|
||||
|
|
@ -475,19 +475,49 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
|
|||
exit_err_feature("networking");
|
||||
exit(0);
|
||||
}
|
||||
else if (strncmp(argv[i], "--snitrace=", 15) == 0) {
|
||||
else if (strncmp(argv[i], "--snitrace=", 11) == 0) {
|
||||
if (checkcfg(CFG_NETWORK)) {
|
||||
if (getuid() != 0) {
|
||||
fprintf(stderr, "Error: --snitrace is only available to root user\n");
|
||||
exit(1);
|
||||
}
|
||||
pid_t pid = require_pid(argv[i] + 15);
|
||||
pid_t pid = require_pid(argv[i] + 11);
|
||||
netfilter_trace(pid, LIBDIR "/firejail/fnettrace-sni");
|
||||
}
|
||||
else
|
||||
exit_err_feature("networking");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
else if (strcmp(argv[i], "--icmptrace") == 0) {
|
||||
if (checkcfg(CFG_NETWORK)) {
|
||||
if (getuid() != 0) {
|
||||
fprintf(stderr, "Error: --icmptrace is only available to root user\n");
|
||||
exit(1);
|
||||
}
|
||||
netfilter_trace(0, LIBDIR "/firejail/fnettrace-icmp");
|
||||
}
|
||||
else
|
||||
exit_err_feature("networking");
|
||||
exit(0);
|
||||
}
|
||||
else if (strncmp(argv[i], "--icmptrace=", 12) == 0) {
|
||||
if (checkcfg(CFG_NETWORK)) {
|
||||
if (getuid() != 0) {
|
||||
fprintf(stderr, "Error: -icmptrace is only available to root user\n");
|
||||
exit(1);
|
||||
}
|
||||
pid_t pid = require_pid(argv[i] + 12);
|
||||
netfilter_trace(pid, LIBDIR "/firejail/fnettrace-icmp");
|
||||
}
|
||||
else
|
||||
exit_err_feature("networking");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
else if (strncmp(argv[i], "--bandwidth=", 12) == 0) {
|
||||
if (checkcfg(CFG_NETWORK)) {
|
||||
logargs(argc, argv);
|
||||
|
|
|
|||
17
src/fnettrace-icmp/Makefile
Normal file
17
src/fnettrace-icmp/Makefile
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
.PHONY: all
|
||||
all: fnettrace-icmp
|
||||
|
||||
ROOT = ../..
|
||||
include $(ROOT)/src/common.mk
|
||||
|
||||
%.o : %.c $(H_FILE_LIST) $(ROOT)/config.mk
|
||||
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
|
||||
|
||||
fnettrace-icmp: $(OBJS) $(ROOT)/config.mk
|
||||
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:; rm -fr *.o fnettrace-icmp *.gcov *.gcda *.gcno *.plist
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean
|
||||
34
src/fnettrace-icmp/fnettrace_icmp.h
Normal file
34
src/fnettrace-icmp/fnettrace_icmp.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef FNETTRACE_SNI_H
|
||||
#define FNETTRACE_SNI_H
|
||||
|
||||
#include "../include/common.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#endif
|
||||
215
src/fnettrace-icmp/main.c
Normal file
215
src/fnettrace-icmp/main.c
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* 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_icmp.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <time.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/if_ether.h>
|
||||
#define MAX_BUF_SIZE (64 * 1024)
|
||||
|
||||
char *type_description[19] = {
|
||||
"Echo reply",
|
||||
"unassigned",
|
||||
"unassigned",
|
||||
"Destination unreachable",
|
||||
"Source quench",
|
||||
"Redirect message",
|
||||
"unassigned",
|
||||
"unassigned",
|
||||
"Echo request",
|
||||
"Router advertisement",
|
||||
"Router solicitation"
|
||||
"Time exceeded",
|
||||
"Bad IP header",
|
||||
"Timestamp",
|
||||
"Timestamp replay",
|
||||
"Information request",
|
||||
"Information reply",
|
||||
"Address mask request",
|
||||
"Address mask reply"
|
||||
};
|
||||
|
||||
char *code_dest_unreachable[16] = {
|
||||
"Network unreachable",
|
||||
"Host unreachable",
|
||||
"Protocol unreachable",
|
||||
"Port unreachable",
|
||||
"Fragmentation required, and DF flag set",
|
||||
"Source route failed",
|
||||
"Network unknown",
|
||||
"Host unknown",
|
||||
"Source host isolated",
|
||||
"Network administratively prohibited",
|
||||
"Host administratively prohibited",
|
||||
"Network unreachable for ToS",
|
||||
"Host unreachable for ToS",
|
||||
"Communication administratively prohibited",
|
||||
"Host Precedence Violation",
|
||||
"Precedence cutoff in effect "
|
||||
};
|
||||
|
||||
char *code_redirect_message[4] = {
|
||||
"Datagram for the Network",
|
||||
"Datagram for the Host",
|
||||
"Datagram for the ToS & network",
|
||||
"Datagram for the ToS & host "
|
||||
};
|
||||
|
||||
char *code_time_exceeded[2] = {
|
||||
"TTL expired in transit",
|
||||
"Fragment reassembly time exceeded "
|
||||
};
|
||||
|
||||
char *code_bad_ip_header[3] = {
|
||||
"Pointer indicates the error",
|
||||
"Missing a required option",
|
||||
"Bad length"
|
||||
};
|
||||
|
||||
static void print_icmp(uint32_t ip_dest, uint32_t ip_src, uint8_t type, uint8_t code, unsigned icmp_bytes) {
|
||||
char type_number[10];
|
||||
char *type_ptr = type_number;
|
||||
if (type < 19)
|
||||
type_ptr = type_description[type];
|
||||
else
|
||||
sprintf(type_number, "%u", type);
|
||||
|
||||
char code_number[10];
|
||||
char *code_ptr = code_number;
|
||||
if (type ==3 && code < 16)
|
||||
code_ptr = code_dest_unreachable[code];
|
||||
else if (type == 5 && code < 4)
|
||||
code_ptr = code_redirect_message[code];
|
||||
else if (type == 11 && code < 2)
|
||||
code_ptr = code_time_exceeded[code];
|
||||
else if (type == 12 && code < 3)
|
||||
code_ptr = code_bad_ip_header[code];
|
||||
else
|
||||
sprintf(code_number, "%u", code);
|
||||
|
||||
time_t seconds = time(NULL);
|
||||
struct tm *t = localtime(&seconds);
|
||||
printf("%02d:%02d:%02d %d.%d.%d.%d -> %d.%d.%d.%d - %u bytes - %s/%s\n",
|
||||
t->tm_hour, t->tm_min, t->tm_sec,
|
||||
PRINT_IP(ip_src),
|
||||
PRINT_IP(ip_dest),
|
||||
icmp_bytes,
|
||||
type_ptr,
|
||||
code_ptr);
|
||||
}
|
||||
|
||||
// https://www.kernel.org/doc/html/latest/networking/filter.html
|
||||
static void custom_bpf(int sock) {
|
||||
struct sock_filter code[] = {
|
||||
// sudo tcpdump "icmp" -dd
|
||||
{ 0x28, 0, 0, 0x0000000c },
|
||||
{ 0x15, 0, 3, 0x00000800 },
|
||||
{ 0x30, 0, 0, 0x00000017 },
|
||||
{ 0x15, 0, 1, 0x00000001 },
|
||||
{ 0x6, 0, 0, 0x00040000 },
|
||||
{ 0x6, 0, 0, 0x00000000 },
|
||||
};
|
||||
|
||||
struct sock_fprog bpf = {
|
||||
.len = (unsigned short) sizeof(code) / sizeof(code[0]),
|
||||
.filter = code,
|
||||
};
|
||||
|
||||
int rv = setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));
|
||||
if (rv < 0) {
|
||||
fprintf(stderr, "Error: cannot attach BPF filter\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void run_trace(void) {
|
||||
// grab all Ethernet packets and use a custom BPF filter to get TLS/SNI packets
|
||||
int s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||
if (s < 0)
|
||||
errExit("socket");
|
||||
custom_bpf(s);
|
||||
|
||||
unsigned char buf[MAX_BUF_SIZE];
|
||||
while (1) {
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(s, &rfds);
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
int rv = select(s + 1, &rfds, NULL, NULL, &tv);
|
||||
if (rv < 0)
|
||||
errExit("select");
|
||||
else if (rv == 0)
|
||||
continue;
|
||||
unsigned bytes = recvfrom(s, buf, MAX_BUF_SIZE, 0, NULL, NULL);
|
||||
|
||||
if (bytes >= (14 + 20 + 2)) { // size of MAC + IP + ICMP code and type fields
|
||||
uint8_t ip_hlen = (buf[14] & 0x0f) * 4;
|
||||
uint8_t type = *(buf + 14 +ip_hlen);
|
||||
uint8_t code = *(buf + 14 + ip_hlen + 1);
|
||||
|
||||
uint32_t ip_dest;
|
||||
memcpy(&ip_dest, buf + 14 + 16, 4);
|
||||
ip_dest = ntohl(ip_dest);
|
||||
uint32_t ip_src;
|
||||
memcpy(&ip_src, buf + 14 + 12, 4);
|
||||
ip_src = ntohl(ip_src);
|
||||
|
||||
print_icmp(ip_dest, ip_src, type, code, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
close(s);
|
||||
}
|
||||
|
||||
|
||||
static void usage(void) {
|
||||
printf("Usage: fnettrace-icmp [OPTIONS]\n");
|
||||
printf("Options:\n");
|
||||
printf(" --help, -? - this help screen\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-?") == 0) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Error: invalid argument\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (getuid() != 0) {
|
||||
fprintf(stderr, "Error: you need to be root to run this program\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
time_t now = time(NULL);
|
||||
printf("ICMP trace for %s\n", ctime(&now));
|
||||
run_trace();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -791,7 +791,9 @@ Without a name/pid, Firejail will monitor the main system network namespace.
|
|||
.br
|
||||
|
||||
.br
|
||||
$ sudo firejail --dnstrace=browser
|
||||
Example:
|
||||
.br
|
||||
$ sudo firejail --dnstrace
|
||||
.br
|
||||
11:31:43 9.9.9.9 linux.com (type 1)
|
||||
.br
|
||||
|
|
@ -917,6 +919,34 @@ $ firejail --ignore=seccomp --ignore=caps firefox
|
|||
$ firejail \-\-ignore="net eth0" firefox
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETWORK
|
||||
.TP
|
||||
\fB\-\-icmptrace[=name|pid]
|
||||
Monitor ICMP traffic. The sandbox can be specified by name or pid. Only networked sandboxes
|
||||
created with \-\-net are supported. This option is only available when running the sandbox as root.
|
||||
.br
|
||||
|
||||
.br
|
||||
Without a name/pid, Firejail will monitor the main system network namespace.
|
||||
.br
|
||||
|
||||
.br
|
||||
Example
|
||||
.br
|
||||
$ sudo firejail --icmptrace
|
||||
.br
|
||||
20:53:54 192.168.1.60 -> 142.250.65.174 - 98 bytes - Echo request/0
|
||||
.br
|
||||
20:53:54 142.250.65.174 -> 192.168.1.60 - 98 bytes - Echo reply/0
|
||||
.br
|
||||
20:53:55 192.168.1.60 -> 142.250.65.174 - 98 bytes - Echo request/0
|
||||
.br
|
||||
20:53:55 142.250.65.174 -> 192.168.1.60 - 98 bytes - Echo reply/0
|
||||
.br
|
||||
20:53:55 192.168.1.60 -> 1.1.1.1 - 154 bytes - Destination unreachable/Port unreachable
|
||||
.br
|
||||
#endif
|
||||
|
||||
.TP
|
||||
\fB\-\-\include=file.profile
|
||||
Include 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.
|
|||
.br
|
||||
|
||||
.br
|
||||
$ sudo firejail --nettrace=browser
|
||||
Example:
|
||||
.br
|
||||
$ sudo firejail --nettrace
|
||||
.br
|
||||
95 KB/s geoip 457, IP database 4436
|
||||
.br
|
||||
|
|
@ -2791,7 +2823,9 @@ Without a name/pid, Firejail will monitor the main system network namespace.
|
|||
.br
|
||||
|
||||
.br
|
||||
$ sudo firejail --snitrace=browser
|
||||
Example:
|
||||
.br
|
||||
$ sudo firejail --snitrace
|
||||
.br
|
||||
07:49:51 23.185.0.3 linux.com
|
||||
.br
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue