aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.in4
-rw-r--r--README.md14
-rw-r--r--RELNOTES2
-rwxr-xr-xconfigure3
-rw-r--r--configure.ac2
-rw-r--r--etc/nolocal.net12
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/fs_lib.c1
-rw-r--r--src/firejail/main.c12
-rw-r--r--src/firejail/netfilter.c158
-rw-r--r--src/firejail/sbox.c9
-rw-r--r--src/firejail/usage.c6
-rw-r--r--src/firejail/util.c43
-rw-r--r--src/fnetfilter/Makefile.in45
-rw-r--r--src/fnetfilter/main.c115
-rw-r--r--src/man/firejail.txt52
-rwxr-xr-xtest/network/ip6.exp16
-rwxr-xr-xtest/network/net_netfilter.exp6
19 files changed, 367 insertions, 137 deletions
diff --git a/.gitignore b/.gitignore
index 0882eeecf..52a2718ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,7 @@ src/ftee/ftee
22src/tags 22src/tags
23src/faudit/faudit 23src/faudit/faudit
24src/fnet/fnet 24src/fnet/fnet
25src/fnetfilter/fnetfilter
25src/fseccomp/fseccomp 26src/fseccomp/fseccomp
26src/fcopy/fcopy 27src/fcopy/fcopy
27src/fldd/fldd 28src/fldd/fldd
diff --git a/Makefile.in b/Makefile.in
index 88ed1f476..54b924288 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,6 +1,6 @@
1all: apps man filters 1all: apps man filters
2MYLIBS = src/lib 2MYLIBS = src/lib
3APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/fnet src/fseccomp src/fbuilder src/fcopy src/fldd src/libpostexecseccomp 3APPS = src/firejail src/firemon src/firecfg src/fnetfilter src/libtrace src/libtracelog src/ftee src/faudit src/fnet src/fseccomp src/fbuilder src/fcopy src/fldd src/libpostexecseccomp
4MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 4MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5
5SECCOMP_FILTERS = seccomp seccomp.debug seccomp.32 seccomp.64 seccomp.block_secondary seccomp.mdwx 5SECCOMP_FILTERS = seccomp seccomp.debug seccomp.32 seccomp.64 seccomp.block_secondary seccomp.mdwx
6 6
@@ -97,6 +97,7 @@ endif
97 install -c -m 0644 src/firecfg/firecfg.config $(DESTDIR)/$(libdir)/firejail/. 97 install -c -m 0644 src/firecfg/firecfg.config $(DESTDIR)/$(libdir)/firejail/.
98 install -c -m 0755 src/faudit/faudit $(DESTDIR)/$(libdir)/firejail/. 98 install -c -m 0755 src/faudit/faudit $(DESTDIR)/$(libdir)/firejail/.
99 install -c -m 0755 src/fnet/fnet $(DESTDIR)/$(libdir)/firejail/. 99 install -c -m 0755 src/fnet/fnet $(DESTDIR)/$(libdir)/firejail/.
100 install -c -m 0755 src/fnetfilter/fnetfilter $(DESTDIR)/$(libdir)/firejail/.
100 install -c -m 0755 src/fcopy/fcopy $(DESTDIR)/$(libdir)/firejail/. 101 install -c -m 0755 src/fcopy/fcopy $(DESTDIR)/$(libdir)/firejail/.
101 install -c -m 0755 src/fldd/fldd $(DESTDIR)/$(libdir)/firejail/. 102 install -c -m 0755 src/fldd/fldd $(DESTDIR)/$(libdir)/firejail/.
102 install -c -m 0755 src/fbuilder/fbuilder $(DESTDIR)/$(libdir)/firejail/. 103 install -c -m 0755 src/fbuilder/fbuilder $(DESTDIR)/$(libdir)/firejail/.
@@ -167,6 +168,7 @@ install-strip: all
167 strip src/ftee/ftee 168 strip src/ftee/ftee
168 strip src/faudit/faudit 169 strip src/faudit/faudit
169 strip src/fnet/fnet 170 strip src/fnet/fnet
171 strip src/fnet/fnetfilter
170 strip src/fseccomp/fseccomp 172 strip src/fseccomp/fseccomp
171 strip src/fcopy/fcopy 173 strip src/fcopy/fcopy
172 strip src/fldd/fldd 174 strip src/fldd/fldd
diff --git a/README.md b/README.md
index 839afef67..924b2ddb3 100644
--- a/README.md
+++ b/README.md
@@ -210,6 +210,20 @@ $
210 --debug-private-lib 210 --debug-private-lib
211 Debug messages for --private-lib option. 211 Debug messages for --private-lib option.
212 212
213 --netfilter.print=name|pid
214 Print the firewall installed in the sandbox specified by name
215 or PID. Example:
216
217 $ firejail --net=browser --net=eth0 --netfilter firefox &
218 $ firejail --netfilter.print=browser
219
220 --netfilter6.print=name|pid
221 Print the IPv6 firewall installed in the sandbox specified by
222 name or PID. Example:
223
224 $ firejail --net=browser --net=eth0 --netfilter firefox &
225 $ firejail --netfilter6.print=browser
226
213````` 227`````
214 228
215## New profiles: 229## New profiles:
diff --git a/RELNOTES b/RELNOTES
index 785cfadc3..db156546c 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -25,6 +25,8 @@ firejail (0.9.51) baseline; urgency=low
25 * feature: --rlimit-cpu 25 * feature: --rlimit-cpu
26 * feature: --timeout 26 * feature: --timeout
27 * feature: profile build tool (--build) 27 * feature: profile build tool (--build)
28 * feature: --netfilter.print
29 * feature: --netfilter6.print
28 * new profiles: upstreamed many profiles from the following sources: 30 * new profiles: upstreamed many profiles from the following sources:
29 https://github.com/chiraag-nataraj/firejail-profiles, 31 https://github.com/chiraag-nataraj/firejail-profiles,
30 https://github.com/nyancat18/fe, 32 https://github.com/nyancat18/fe,
diff --git a/configure b/configure
index f64aa2dac..cd46ad8fd 100755
--- a/configure
+++ b/configure
@@ -3823,7 +3823,7 @@ if test "$prefix" = /usr; then
3823 sysconfdir="/etc" 3823 sysconfdir="/etc"
3824fi 3824fi
3825 3825
3826ac_config_files="$ac_config_files Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile" 3826ac_config_files="$ac_config_files Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile"
3827 3827
3828cat >confcache <<\_ACEOF 3828cat >confcache <<\_ACEOF
3829# This file is a shell script that caches the results of configure 3829# This file is a shell script that caches the results of configure
@@ -4537,6 +4537,7 @@ do
4537 "src/fcopy/Makefile") CONFIG_FILES="$CONFIG_FILES src/fcopy/Makefile" ;; 4537 "src/fcopy/Makefile") CONFIG_FILES="$CONFIG_FILES src/fcopy/Makefile" ;;
4538 "src/fnet/Makefile") CONFIG_FILES="$CONFIG_FILES src/fnet/Makefile" ;; 4538 "src/fnet/Makefile") CONFIG_FILES="$CONFIG_FILES src/fnet/Makefile" ;;
4539 "src/firejail/Makefile") CONFIG_FILES="$CONFIG_FILES src/firejail/Makefile" ;; 4539 "src/firejail/Makefile") CONFIG_FILES="$CONFIG_FILES src/firejail/Makefile" ;;
4540 "src/fnetfilter/Makefile") CONFIG_FILES="$CONFIG_FILES src/fnetfilter/Makefile" ;;
4540 "src/firemon/Makefile") CONFIG_FILES="$CONFIG_FILES src/firemon/Makefile" ;; 4541 "src/firemon/Makefile") CONFIG_FILES="$CONFIG_FILES src/firemon/Makefile" ;;
4541 "src/libtrace/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtrace/Makefile" ;; 4542 "src/libtrace/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtrace/Makefile" ;;
4542 "src/libtracelog/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtracelog/Makefile" ;; 4543 "src/libtracelog/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtracelog/Makefile" ;;
diff --git a/configure.ac b/configure.ac
index 900c8b959..9254a3ee2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -175,7 +175,7 @@ if test "$prefix" = /usr; then
175 sysconfdir="/etc" 175 sysconfdir="/etc"
176fi 176fi
177 177
178AC_OUTPUT(Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile \ 178AC_OUTPUT(Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/fnetfilter/Makefile \
179src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile \ 179src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/fbuilder/Makefile \
180src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile) 180src/ftee/Makefile src/faudit/Makefile src/fseccomp/Makefile src/fldd/Makefile src/libpostexecseccomp/Makefile)
181 181
diff --git a/etc/nolocal.net b/etc/nolocal.net
index 9fa785450..8955f740d 100644
--- a/etc/nolocal.net
+++ b/etc/nolocal.net
@@ -12,15 +12,25 @@
12# 12#
13################################################################### 13###################################################################
14 14
15 15#allow all loopback traffic
16-A INPUT -i lo -j ACCEPT 16-A INPUT -i lo -j ACCEPT
17
18# no incoming connections
17-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 19-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
20
21# allow ping etc.
18-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT 22-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
19-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT 23-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
20-A INPUT -p icmp --icmp-type echo-request -j ACCEPT 24-A INPUT -p icmp --icmp-type echo-request -j ACCEPT
21 25
26# accept dns requests going out to a server on the local network
22-A OUTPUT -p udp --dport 53 -j ACCEPT 27-A OUTPUT -p udp --dport 53 -j ACCEPT
28
29# drop all local network traffic
23-A OUTPUT -d 192.168.0.0/16 -j DROP 30-A OUTPUT -d 192.168.0.0/16 -j DROP
24-A OUTPUT -d 10.0.0.0/8 -j DROP 31-A OUTPUT -d 10.0.0.0/8 -j DROP
25-A OUTPUT -d 172.16.0.0/12 -j DROP 32-A OUTPUT -d 172.16.0.0/12 -j DROP
33
34# drop multicast traffic
35-A OUTPUT -d 244.0.0.0/4 -j DROP
26COMMIT 36COMMIT
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 59bd4b959..f7bebe1b6 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -516,7 +516,6 @@ void create_empty_dir_as_root(const char *dir, mode_t mode);
516void create_empty_file_as_root(const char *dir, mode_t mode); 516void create_empty_file_as_root(const char *dir, mode_t mode);
517int set_perms(const char *fname, uid_t uid, gid_t gid, mode_t mode); 517int set_perms(const char *fname, uid_t uid, gid_t gid, mode_t mode);
518void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid); 518void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid);
519char *read_text_file_or_exit(const char *fname);
520unsigned extract_timeout(const char *str); 519unsigned extract_timeout(const char *str);
521 520
522// fs_var.c 521// fs_var.c
@@ -607,6 +606,7 @@ void check_output(int argc, char **argv);
607void check_netfilter_file(const char *fname); 606void check_netfilter_file(const char *fname);
608void netfilter(const char *fname); 607void netfilter(const char *fname);
609void netfilter6(const char *fname); 608void netfilter6(const char *fname);
609void netfilter_print(pid_t pid, int ipv6);
610 610
611// netns.c 611// netns.c
612void check_netns(const char *nsname); 612void check_netns(const char *nsname);
@@ -766,6 +766,7 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
766// sbox.c 766// sbox.c
767// programs 767// programs
768#define PATH_FNET (LIBDIR "/firejail/fnet") 768#define PATH_FNET (LIBDIR "/firejail/fnet")
769#define PATH_FNETFILTER (LIBDIR "/firejail/fnetfilter")
769#define PATH_FIREMON (PREFIX "/bin/firemon") 770#define PATH_FIREMON (PREFIX "/bin/firemon")
770#define PATH_FIREJAIL (PREFIX "/bin/firejail") 771#define PATH_FIREJAIL (PREFIX "/bin/firejail")
771#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp") 772#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp")
diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c
index 23fdb8a6a..46ee22bf3 100644
--- a/src/firejail/fs_lib.c
+++ b/src/firejail/fs_lib.c
@@ -387,6 +387,7 @@ void fs_private_lib(void) {
387 fslib_copy_libs(LIBDIR "/firejail/fcopy"); 387 fslib_copy_libs(LIBDIR "/firejail/fcopy");
388 fslib_copy_libs(LIBDIR "/firejail/fldd"); 388 fslib_copy_libs(LIBDIR "/firejail/fldd");
389 fslib_copy_libs(LIBDIR "/firejail/fnet"); 389 fslib_copy_libs(LIBDIR "/firejail/fnet");
390 fslib_copy_libs(LIBDIR "/firejail/fnetfilter");
390 fslib_copy_libs(LIBDIR "/firejail/fseccomp"); 391 fslib_copy_libs(LIBDIR "/firejail/fseccomp");
391 fslib_copy_libs(LIBDIR "/firejail/ftee"); 392 fslib_copy_libs(LIBDIR "/firejail/ftee");
392 // mount lib filesystem 393 // mount lib filesystem
diff --git a/src/firejail/main.c b/src/firejail/main.c
index c8b347b5f..d6b0a230e 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -429,6 +429,18 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
429 exit_err_feature("networking"); 429 exit_err_feature("networking");
430 exit(0); 430 exit(0);
431 } 431 }
432 else if (strncmp(argv[i], "--netfilter.print=", 18) == 0) {
433 // extract pid or sandbox name
434 pid_t pid = read_pid(argv[i] + 18);
435 netfilter_print(pid, 0);
436 exit(0);
437 }
438 else if (strncmp(argv[i], "--netfilter6.print=", 19) == 0) {
439 // extract pid or sandbox name
440 pid_t pid = read_pid(argv[i] + 19);
441 netfilter_print(pid, 1);
442 exit(0);
443 }
432#endif 444#endif
433 //************************************* 445 //*************************************
434 // independent commands - the program will exit! 446 // independent commands - the program will exit!
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c
index cb0d9d7af..e1d0edd01 100644
--- a/src/firejail/netfilter.c
+++ b/src/firejail/netfilter.c
@@ -24,33 +24,24 @@
24#include <sys/wait.h> 24#include <sys/wait.h>
25#include <fcntl.h> 25#include <fcntl.h>
26 26
27static char *client_filter =
28"*filter\n"
29":INPUT DROP [0:0]\n"
30":FORWARD DROP [0:0]\n"
31":OUTPUT ACCEPT [0:0]\n"
32"-A INPUT -i lo -j ACCEPT\n"
33"-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
34"# echo replay is handled by -m state RELATED/ESTABLISHED below\n"
35"#-A INPUT -p icmp --icmp-type echo-reply -j ACCEPT\n"
36"-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT\n"
37"-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT\n"
38"-A INPUT -p icmp --icmp-type echo-request -j ACCEPT \n"
39"# disable STUN\n"
40"-A OUTPUT -p udp --dport 3478 -j DROP\n"
41"-A OUTPUT -p udp --dport 3479 -j DROP\n"
42"-A OUTPUT -p tcp --dport 3478 -j DROP\n"
43"-A OUTPUT -p tcp --dport 3479 -j DROP\n"
44"COMMIT\n";
45 27
46void check_netfilter_file(const char *fname) { 28void check_netfilter_file(const char *fname) {
47 EUID_ASSERT(); 29 EUID_ASSERT();
48 invalid_filename(fname, 0); // no globbing
49 30
50 if (is_dir(fname) || is_link(fname) || strstr(fname, "..") || access(fname, R_OK )) { 31 char *tmp = strdup(fname);
51 fprintf(stderr, "Error: invalid network filter file %s\n", fname); 32 if (!tmp)
33 errExit("strdup");
34 char *ptr = strchr(tmp, ',');
35 if (ptr)
36 *ptr = '\0';
37
38 invalid_filename(tmp, 0); // no globbing
39
40 if (is_dir(tmp) || is_link(tmp) || strstr(tmp, "..") || access(tmp, R_OK )) {
41 fprintf(stderr, "Error: invalid network filter file %s\n", tmp);
52 exit(1); 42 exit(1);
53 } 43 }
44 free(tmp);
54} 45}
55 46
56 47
@@ -72,41 +63,28 @@ void netfilter(const char *fname) {
72 return; 63 return;
73 } 64 }
74 65
75 // read filter 66 if (arg_debug)
76 char *filter = client_filter; 67 printf("Installing firewall\n");
77 int allocated = 0;
78 if (netfilter_default)
79 fname = netfilter_default;
80 if (fname) {
81 filter = read_text_file_or_exit(fname);
82 allocated = 1;
83 }
84
85 // create the filter file
86 FILE *fp = fopen(SBOX_STDIN_FILE, "w");
87 if (!fp) {
88 fprintf(stderr, "Error: cannot open %s\n", SBOX_STDIN_FILE);
89 exit(1);
90 }
91 fprintf(fp, "%s\n", filter);
92 fclose(fp);
93 68
69 // create an empty user-owned SBOX_STDIN_FILE
70 create_empty_file_as_root(SBOX_STDIN_FILE, 0644);
71 if (set_perms(SBOX_STDIN_FILE, getuid(), getgid(), 0644))
72 errExit("set_perms");
94 73
95 // push filter 74 if (fname == NULL)
96 if (arg_debug) 75 sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FNETFILTER, SBOX_STDIN_FILE);
97 printf("Installing network filter:\n%s\n", filter); 76 else
77 sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FNETFILTER, fname, SBOX_STDIN_FILE);
98 78
99 // first run of iptables on this platform installs a number of kernel modules such as ip_tables, x_tables, iptable_filter 79 // first run of iptables on this platform installs a number of kernel modules such as ip_tables, x_tables, iptable_filter
100 // we run this command with caps and seccomp disabled in order to allow the loading of these modules 80 // we run this command with caps and seccomp disabled in order to allow the loading of these modules
101 sbox_run(SBOX_ROOT /* | SBOX_CAPS_NETWORK | SBOX_SECCOMP*/ | SBOX_STDIN_FROM_FILE, 1, iptables_restore); 81 sbox_run(SBOX_ROOT | SBOX_STDIN_FROM_FILE, 1, iptables_restore);
102 unlink(SBOX_STDIN_FILE); 82 unlink(SBOX_STDIN_FILE);
103 83
104 // debug 84 // debug
105 if (arg_debug) 85 if (arg_debug)
106 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-vL"); 86 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-vL");
107 87
108 if (allocated)
109 free(filter);
110 return; 88 return;
111} 89}
112 90
@@ -131,29 +109,91 @@ void netfilter6(const char *fname) {
131 return; 109 return;
132 } 110 }
133 111
134 // create the filter file
135 char *filter = read_text_file_or_exit(fname);
136 FILE *fp = fopen(SBOX_STDIN_FILE, "w");
137 if (!fp) {
138 fprintf(stderr, "Error: cannot open %s\n", SBOX_STDIN_FILE);
139 exit(1);
140 }
141 fprintf(fp, "%s\n", filter);
142 fclose(fp);
143
144 // push filter
145 if (arg_debug) 112 if (arg_debug)
146 printf("Installing network filter:\n%s\n", filter); 113 printf("Installing IPv6 firewall\n");
114
115 // create an empty user-owned SBOX_STDIN_FILE
116 create_empty_file_as_root(SBOX_STDIN_FILE, 0644);
117 if (set_perms(SBOX_STDIN_FILE, getuid(), getgid(), 0644))
118 errExit("set_perms");
119
120 sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FNETFILTER, fname, SBOX_STDIN_FILE);
147 121
148 // first run of iptables on this platform installs a number of kernel modules such as ip_tables, x_tables, iptable_filter 122 // first run of iptables on this platform installs a number of kernel modules such as ip_tables, x_tables, iptable_filter
149 // we run this command with caps and seccomp disabled in order to allow the loading of these modules 123 // we run this command with caps and seccomp disabled in order to allow the loading of these modules
150 sbox_run(SBOX_ROOT | /* SBOX_CAPS_NETWORK | SBOX_SECCOMP | */ SBOX_STDIN_FROM_FILE, 1, ip6tables_restore); 124 sbox_run(SBOX_ROOT | SBOX_STDIN_FROM_FILE, 1, ip6tables_restore);
151 unlink(SBOX_STDIN_FILE); 125 unlink(SBOX_STDIN_FILE);
152 126
153 // debug 127 // debug
154 if (arg_debug) 128 if (arg_debug)
155 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, ip6tables, "-vL"); 129 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, ip6tables, "-vL");
156 130
157 free(filter);
158 return; 131 return;
159} 132}
133
134void netfilter_print(pid_t pid, int ipv6) {
135 EUID_ASSERT();
136
137 // verify sandbox
138 EUID_ROOT();
139 char *comm = pid_proc_comm(pid);
140 EUID_USER();
141 if (!comm) {
142 fprintf(stderr, "Error: cannot find sandbox\n");
143 exit(1);
144 }
145
146 // check for firejail sandbox
147 if (strcmp(comm, "firejail") != 0) {
148 fprintf(stderr, "Error: cannot find sandbox\n");
149 exit(1);
150 }
151 free(comm);
152
153 // check network namespace
154 char *name;
155 if (asprintf(&name, "/run/firejail/network/%d-netmap", pid) == -1)
156 errExit("asprintf");
157 struct stat s;
158 if (stat(name, &s) == -1) {
159 fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n");
160 exit(1);
161 }
162
163 // join the network namespace
164 pid_t child;
165 if (find_child(pid, &child) == -1) {
166 fprintf(stderr, "Error: cannot join the network namespace\n");
167 exit(1);
168 }
169
170 EUID_ROOT();
171 if (join_namespace(child, "net")) {
172 fprintf(stderr, "Error: cannot join the network namespace\n");
173 exit(1);
174 }
175
176 // find iptables executable
177 char *iptables = NULL;
178 char *iptables_restore = NULL;
179 if (ipv6) {
180 if (stat("/sbin/ip6tables", &s) == 0)
181 iptables = "/sbin/ip6tables";
182 else if (stat("/usr/sbin/ip6tables", &s) == 0)
183 iptables = "/usr/sbin/ip6tables";
184 }
185 else {
186 if (stat("/sbin/iptables", &s) == 0)
187 iptables = "/sbin/iptables";
188 else if (stat("/usr/sbin/iptables", &s) == 0)
189 iptables = "/usr/sbin/iptables";
190 }
191
192 if (iptables == NULL) {
193 fprintf(stderr, "Error: iptables command not found\n");
194 exit(1);
195 }
196
197 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-vL");
198}
199
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c
index 1d6cc2353..274a4353f 100644
--- a/src/firejail/sbox.c
+++ b/src/firejail/sbox.c
@@ -104,13 +104,6 @@ static struct sock_fprog prog = {
104 .filter = filter, 104 .filter = filter,
105}; 105};
106 106
107typedef struct sbox_config {
108 char *name;
109 char *path;
110 unsigned filters;
111} SboxConfig;
112
113
114int sbox_run(unsigned filter, int num, ...) { 107int sbox_run(unsigned filter, int num, ...) {
115 EUID_ROOT(); 108 EUID_ROOT();
116 109
@@ -142,7 +135,7 @@ int sbox_run(unsigned filter, int num, ...) {
142 if (filter & SBOX_STDIN_FROM_FILE) { 135 if (filter & SBOX_STDIN_FROM_FILE) {
143 int fd; 136 int fd;
144 if((fd = open(SBOX_STDIN_FILE, O_RDONLY)) == -1) { 137 if((fd = open(SBOX_STDIN_FILE, O_RDONLY)) == -1) {
145 fprintf(stderr,"Error: cannot open /tmp/netfilter\n"); 138 fprintf(stderr,"Error: cannot open %s\n", SBOX_STDIN_FILE);
146 exit(1); 139 exit(1);
147 } 140 }
148 dup2(fd,STDIN_FILENO); 141 dup2(fd,STDIN_FILENO);
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index 38de99471..f1581e847 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -122,8 +122,10 @@ void usage(void) {
122 printf(" --net=ethernet_interface - enable network namespaces and connect to this\n"); 122 printf(" --net=ethernet_interface - enable network namespaces and connect to this\n");
123 printf("\tEthernet interface.\n"); 123 printf("\tEthernet interface.\n");
124 printf(" --net=none - enable a new, unconnected network namespace.\n"); 124 printf(" --net=none - enable a new, unconnected network namespace.\n");
125 printf(" --netfilter[=filename] - enable the default client network filter.\n"); 125 printf(" --netfilter[=filename] - enable firewall.\n");
126 printf(" --netfilter6=filename - enable the IPv6 network filter.\n"); 126 printf(" --netfilter.print=name|pid - print the firewall.\n");
127 printf(" --netfilter6=filename - enable IPv6 firewall.\n");
128 printf(" --netfilter6.print=name|pid - print the IPv6 firewall.\n");
127 printf(" --netns=name - Run the program in a named, persistent network namespace.\n"); 129 printf(" --netns=name - Run the program in a named, persistent network namespace.\n");
128 printf(" --netstats - monitor network statistics.\n"); 130 printf(" --netstats - monitor network statistics.\n");
129#endif 131#endif
diff --git a/src/firejail/util.c b/src/firejail/util.c
index cea2b76e3..fde180e49 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -908,49 +908,6 @@ void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) {
908 ASSERT_PERMS(fname, uid, gid, mode); 908 ASSERT_PERMS(fname, uid, gid, mode);
909} 909}
910 910
911char *read_text_file_or_exit(const char *fname) {
912 assert(fname);
913
914 // open file
915 int fd = open(fname, O_RDONLY);
916 if (fd == -1) {
917 fprintf(stderr, "Error: cannot read %s\n", fname);
918 exit(1);
919 }
920
921 int size = lseek(fd, 0, SEEK_END);
922 if (size == -1)
923 goto errexit;
924 if (lseek(fd, 0 , SEEK_SET) == -1)
925 goto errexit;
926
927 // allocate memory
928 char *data = malloc(size + 1); // + '\0'
929 if (data == NULL)
930 goto errexit;
931 memset(data, 0, size + 1);
932
933 // read file
934 int rd = 0;
935 while (rd < size) {
936 int rv = read(fd, (unsigned char *) data + rd, size - rd);
937 if (rv == -1) {
938 goto errexit;
939 }
940 rd += rv;
941 }
942
943 // close file
944 close(fd);
945 return data;
946
947errexit:
948 close(fd);
949 fprintf(stderr, "Error: cannot read %s\n", fname);
950 exit(1);
951}
952
953
954unsigned extract_timeout(const char *str) { 911unsigned extract_timeout(const char *str) {
955 unsigned s; 912 unsigned s;
956 unsigned m; 913 unsigned m;
diff --git a/src/fnetfilter/Makefile.in b/src/fnetfilter/Makefile.in
new file mode 100644
index 000000000..1063737e1
--- /dev/null
+++ b/src/fnetfilter/Makefile.in
@@ -0,0 +1,45 @@
1all: fnetfilter
2
3CC=@CC@
4prefix=@prefix@
5exec_prefix=@exec_prefix@
6libdir=@libdir@
7sysconfdir=@sysconfdir@
8
9VERSION=@PACKAGE_VERSION@
10NAME=@PACKAGE_NAME@
11HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
12HAVE_SECCOMP=@HAVE_SECCOMP@
13HAVE_CHROOT=@HAVE_CHROOT@
14HAVE_BIND=@HAVE_BIND@
15HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
16HAVE_NETWORK=@HAVE_NETWORK@
17HAVE_USERNS=@HAVE_USERNS@
18HAVE_X11=@HAVE_X11@
19HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
20HAVE_WHITELIST=@HAVE_WHITELIST@
21HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
22HAVE_APPARMOR=@HAVE_APPARMOR@
23HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
24HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
25EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
26HAVE_GCOV=@HAVE_GCOV@
27EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
28
29H_FILE_LIST = $(sort $(wildcard *.[h]))
30C_FILE_LIST = $(sort $(wildcard *.c))
31OBJS = $(C_FILE_LIST:.c=.o)
32BINOBJS = $(foreach file, $(OBJS), $file)
33CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
34LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
35
36%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h
37 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
38
39fnetfilter: $(OBJS)
40 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
41
42clean:; rm -f *.o fnetfilter *.gcov *.gcda *.gcno
43
44distclean: clean
45 rm -fr Makefile
diff --git a/src/fnetfilter/main.c b/src/fnetfilter/main.c
new file mode 100644
index 000000000..67ab31832
--- /dev/null
+++ b/src/fnetfilter/main.c
@@ -0,0 +1,115 @@
1 /*
2 * Copyright (C) 2014-2017 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 "../include/common.h"
21
22#define MAXBUF 4098
23int arg_quiet = 0;
24
25static char *default_filter =
26"*filter\n"
27":INPUT DROP [0:0]\n"
28":FORWARD DROP [0:0]\n"
29":OUTPUT ACCEPT [0:0]\n"
30"-A INPUT -i lo -j ACCEPT\n"
31"-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
32"# echo replay is handled by -m state RELATED/ESTABLISHED below\n"
33"#-A INPUT -p icmp --icmp-type echo-reply -j ACCEPT\n"
34"-A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT\n"
35"-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT\n"
36"-A INPUT -p icmp --icmp-type echo-request -j ACCEPT \n"
37"# disable STUN\n"
38"-A OUTPUT -p udp --dport 3478 -j DROP\n"
39"-A OUTPUT -p udp --dport 3479 -j DROP\n"
40"-A OUTPUT -p tcp --dport 3478 -j DROP\n"
41"-A OUTPUT -p tcp --dport 3479 -j DROP\n"
42"COMMIT\n";
43
44static void usage(void) {
45 printf("Usage:\n");
46 printf("\tfnetfilter netfilter-command destination-file\n");
47}
48
49int main(int argc, char **argv) {
50#if 0
51{
52system("cat /proc/self/status");
53int i;
54for (i = 0; i < argc; i++)
55 printf("*%s* ", argv[i]);
56printf("\n");
57}
58#endif
59
60 char *quiet = getenv("FIREJAIL_QUIET");
61 if (quiet && strcmp(quiet, "yes") == 0)
62 arg_quiet = 1;
63
64 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) {
65 usage();
66 return 0;
67 }
68
69 if (argc != 2 && argc != 3) {
70 usage();
71 return 1;
72 }
73
74 char *destfile = (argc == 3)? argv[2]: argv[1];
75 char *command = (argc == 3)? argv[1]: NULL;
76//printf("command %s\n", command);
77//printf("destfile %s\n", destfile);
78
79 // handle default config (command = NULL, destfile)
80 if (command == NULL) {
81 // create a default filter file
82 FILE *fp = fopen(destfile, "w");
83 if (!fp) {
84 fprintf(stderr, "Error fnetfilter: cannot open %s\n", destfile);
85 exit(1);
86 }
87 fprintf(fp, "%s\n", default_filter);
88 fclose(fp);
89 }
90 else {
91 // copy the file
92 FILE *fp1 = fopen(command, "r");
93 if (!fp1) {
94 fprintf(stderr, "Error fnetfilter: cannot open %s\n", command);
95 exit(1);
96 }
97
98 FILE *fp2 = fopen(destfile, "w");
99 if (!fp2) {
100 fprintf(stderr, "Error fnetfilter: cannot open %s\n", destfile);
101 exit(1);
102 }
103
104 char buf[MAXBUF];
105 while (fgets(buf, MAXBUF, fp1))
106 fprintf(fp2, "%s", buf);
107
108 fclose(fp1);
109 fclose(fp2);
110 }
111
112
113printf("fnetfilter running\n");
114 return 0;
115}
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index e0eb723bc..bf27c07ad 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -858,10 +858,13 @@ be created and configured using "ip netns".
858 858
859.TP 859.TP
860\fB\-\-netfilter 860\fB\-\-netfilter
861Enable a default client network filter in the new network namespace. 861Enable a default firewall if a new network namespace is created inside the sandbox.
862New network namespaces are created using \-\-net option. If a new network namespaces is not created, 862This option has no effect for sandboxes using the system network namespace.
863\-\-netfilter option does nothing. 863.br
864The default filter is as follows: 864
865.br
866The default firewall is optimized for regular desktop applications. No incoming
867connections are accepted:
865.br 868.br
866 869
867.br 870.br
@@ -904,19 +907,18 @@ Example:
904$ firejail \-\-net=eth0 \-\-netfilter firefox 907$ firejail \-\-net=eth0 \-\-netfilter firefox
905.TP 908.TP
906\fB\-\-netfilter=filename 909\fB\-\-netfilter=filename
907Enable the network filter specified by filename in the new network namespace. The filter file format 910Enable the firewall specified by filename if a new network namespace is created inside the sandbox.
908is the format of iptables-save and iptable-restore commands. 911This option has no effect for sandboxes using the system network namespace.
909New network namespaces are created using \-\-net option. If a new network namespaces is not created,
910\-\-netfilter option does nothing.
911.br 912.br
912 913
913.br 914.br
914The following filters are available in /etc/firejail directory: 915Please use the regular iptables-save/iptables-restore format for the filter file. The following
916examples are available in /etc/firejail directory:
915.br 917.br
916 918
917.br 919.br
918.B webserver.net 920.B webserver.net
919is a webserver filter that allows access only to TCP ports 80 and 443. 921is a webserver firewall that allows access only to TCP ports 80 and 443.
920Example: 922Example:
921.br 923.br
922 924
@@ -928,7 +930,7 @@ $ firejail --netfilter=/etc/firejail/webserver.net --net=eth0 \\
928 930
929.br 931.br
930.B nolocal.net 932.B nolocal.net
931is a client filter that disable access to local network. Example: 933is a desktop client firewall that disable access to local network. Example:
932.br 934.br
933 935
934.br 936.br
@@ -936,11 +938,31 @@ $ firejail --netfilter=/etc/firejail/nolocal.net \\
936.br 938.br
937--net=eth0 firefox 939--net=eth0 firefox
938.TP 940.TP
941\fB\-\-netfilter.print=name|pid
942Print the firewall installed in the sandbox specified by name or PID. Example:
943.br
944
945.br
946$ firejail --net=browser --net=eth0 --netfilter firefox &
947.br
948$ firejail --netfilter.print=browser
949
950.TP
939\fB\-\-netfilter6=filename 951\fB\-\-netfilter6=filename
940Enable the IPv6 network filter specified by filename in the new network namespace. The filter file format 952Enable the IPv6 firewall specified by filename if a new network namespace is created inside the sandbox.
941is the format of ip6tables-save and ip6table-restore commands. 953This option has no effect for sandboxes using the system network namespace.
942New network namespaces are created using \-\-net option. If a new network namespaces is not created, 954Please use the regular iptables-save/iptables-restore format for the filter file.
943\-\-netfilter6 option does nothing. 955
956.TP
957\fB\-\-netfilter6.print=name|pid
958Print the IPv6 firewall installed in the sandbox specified by name or PID. Example:
959.br
960
961.br
962$ firejail --net=browser --net=eth0 --netfilter firefox &
963.br
964$ firejail --netfilter6.print=browser
965
944.TP 966.TP
945\fB\-\-netstats 967\fB\-\-netstats
946Monitor network namespace statistics, see \fBMONITORING\fR section for more details. 968Monitor network namespace statistics, see \fBMONITORING\fR section for more details.
diff --git a/test/network/ip6.exp b/test/network/ip6.exp
index 26780e167..c55f690db 100755
--- a/test/network/ip6.exp
+++ b/test/network/ip6.exp
@@ -10,7 +10,7 @@ match_max 100000
10send -- "firejail --debug --noprofile --net=br0 --ip6=2001:0db8:0:f101::1/64 --netfilter6=ipv6.net\r" 10send -- "firejail --debug --noprofile --net=br0 --ip6=2001:0db8:0:f101::1/64 --netfilter6=ipv6.net\r"
11expect { 11expect {
12 timeout {puts "TESTING ERROR 0\n";exit} 12 timeout {puts "TESTING ERROR 0\n";exit}
13 "Installing network filter" 13 "Installing IPv6 firewall"
14} 14}
15expect { 15expect {
16 timeout {puts "TESTING ERROR 1\n";exit} 16 timeout {puts "TESTING ERROR 1\n";exit}
@@ -46,10 +46,12 @@ send -- "exit\r"
46sleep 2 46sleep 2
47 47
48 48
49
50
49send -- "firejail --debug --profile=ip6.profile\r" 51send -- "firejail --debug --profile=ip6.profile\r"
50expect { 52expect {
51 timeout {puts "TESTING ERROR 10\n";exit} 53 timeout {puts "TESTING ERROR 10\n";exit}
52 "Installing network filter" 54 "Installing IPv6 firewall"
53} 55}
54expect { 56expect {
55 timeout {puts "TESTING ERROR 11\n";exit} 57 timeout {puts "TESTING ERROR 11\n";exit}
@@ -82,7 +84,17 @@ expect {
82} 84}
83 85
84send -- "exit\r" 86send -- "exit\r"
87sleep 2
85 88
89send -- "firejail --debug --netfilter6=ipv6.net\r"
90expect {
91 timeout {puts "TESTING ERROR 11\n";exit}
92 "Installing IPv6 firewall" {puts "TESTING ERROR 12\n";exit}
93 "Child process initialized"
94}
86after 100 95after 100
96send -- "exit\r"
87 97
98
99after 100
88puts "\nall done\n" 100puts "\nall done\n"
diff --git a/test/network/net_netfilter.exp b/test/network/net_netfilter.exp
index 52fd3bf11..8f371bafc 100755
--- a/test/network/net_netfilter.exp
+++ b/test/network/net_netfilter.exp
@@ -11,7 +11,7 @@ match_max 100000
11send -- "firejail --debug --noprofile --net=br0 --ip=10.10.20.5 --netfilter\r" 11send -- "firejail --debug --noprofile --net=br0 --ip=10.10.20.5 --netfilter\r"
12expect { 12expect {
13 timeout {puts "TESTING ERROR 0\n";exit} 13 timeout {puts "TESTING ERROR 0\n";exit}
14 "Installing network filter" 14 "Installing firewall"
15} 15}
16expect { 16expect {
17 timeout {puts "TESTING ERROR 1\n";exit} 17 timeout {puts "TESTING ERROR 1\n";exit}
@@ -51,7 +51,7 @@ sleep 1
51send -- "firejail --debug --noprofile --net=br0 --ip=10.10.20.5 --netfilter=netfilter.filter\r" 51send -- "firejail --debug --noprofile --net=br0 --ip=10.10.20.5 --netfilter=netfilter.filter\r"
52expect { 52expect {
53 timeout {puts "TESTING ERROR 6\n";exit} 53 timeout {puts "TESTING ERROR 6\n";exit}
54 "Installing network filter" 54 "Installing firewall"
55} 55}
56expect { 56expect {
57 timeout {puts "TESTING ERROR 6.1\n";exit} 57 timeout {puts "TESTING ERROR 6.1\n";exit}
@@ -71,7 +71,7 @@ sleep 1
71send -- "firejail --debug --net=br0 --ip=10.10.20.5 --profile=netfilter.profile\r" 71send -- "firejail --debug --net=br0 --ip=10.10.20.5 --profile=netfilter.profile\r"
72expect { 72expect {
73 timeout {puts "TESTING ERROR 7\n";exit} 73 timeout {puts "TESTING ERROR 7\n";exit}
74 "Installing network filter" 74 "Installing firewall"
75} 75}
76expect { 76expect {
77 timeout {puts "TESTING ERROR 7.1\n";exit} 77 timeout {puts "TESTING ERROR 7.1\n";exit}