In this post i will show an example on how to pratically realize a more secure web browsing environment exploiting some great Linux kernel features to create sandboxed environments for browsers. If you don’t know what i’m talking about and you haven’t yet done it, read the first part!
There are many tools in the wild to build the sandboxes using the features explained, some more user friendly, other more complex, some more complete, other more specific to one or few features.
After some tests and with the help of many friends from the Veteran Unix Admins group on facebook, the primary tool I’ve chosen to use is firejail.
Firejail is a great utility aiming to build sandboxes and it match almost perfectly our needs. With just a little bit of shell scripting, a little patch I have sent to firejail and a couple of other tools supported by firejail itself, we have all what is needed for our architecture.
As for the browser, we will use the worst one in terms of privacy, google chrome. Chrome has been chosen cause it’s the most fucking son of a bitch hard to make works as expected at least between the most diffuse browsers, and is a very commonly used one.
The Linux distribution over this post is focused is Devuan GNU/Linux, if you don’t use it, shame on you, but the commands and scripts should works on every deb based distro like Ubuntu, Debian and others. If you are in the rpm world, you will have to adapt things for you, or better, you should switch to Devuan too.
As explained in the precedent post, we will have 3 different level of browser isolation:
- trusted
- secure
- paranoid
so, let’s go
System preparation
As already said, we will use firejail, so, you need to install it. The already packaged version in Devuan is updates, so, if you use devuan, you can just do:
# apt-get update && apt-get install firejail
if you use another distro and your package manager show a version < of 0.9.42~rc2 you should compile and install it from the git upstream repository
we will also need xpra and the dummy xorg driver and a little bit of python
# apt-get install xpra xserver-xorg-video-dummy python-opengl tor privoxy bridge-utils
I assume you already have a working Xorg, sudo and pulseaudio or working alsa config, chrome ( or the browser you will use ) installed.
3d accelleration should works too, but if you have issues with it, you can follow instruction in https://xpra.org/trac/wiki/Usage/OpenGL or try to use http://www.virtualgl.org/
Add 3 users to the system:
# groupadd -r fjtrusted # useradd -r -s /bin/bash -g fjtrusted -G audio,video -d /home/trusted fjtrusted # mkdir /home/trusted && chown fjtrusted.fjtrusted /home/trusted # groupadd -r fjsecure # useradd -r -s /bin/bash -g fjsecure -G audio -d /home/secure fjsecure # mkdir /home/secure && chown fjsecure.fjsecure /home/secure # groupadd -r fjparanoid # useradd -r -s /bin/bash -g fjparanoid -d /home/paranoid fjparanoid # mkdir /home/paranoid && chown fjparanoid.fjparanoid /home/paranoid
Maybe you noted we use standard /home directory for users, and maybe, like me, you don’t like it as they are mere “service” users. I agree, but sadly for how firejail works, for now, we must stick on that, as only it implement /home directory in a special way, and you should really stay in it to use it without issues.
Create utility directory for firejail:
# mkdir -p /var/lib/firejail/templates/{paranoid,secure}
If you use Devuan, debian, and probably also others, there is another limitation to take care about. Firejail doesn’t work so well with symlinks, and there are a couple of symlinks we need to get rid of. in Devuan, /dev/shm is a symlink to /run/shm. Same apply to /var/run, symlinked to /run.
A dirty but effective workaround is to put in /etc/rc.local the following lines:
rm /dev/shm mkdir /dev/shm mount --bind /run/shm /dev/shm rm /var/run mkdir /var/run mount --bind /run /var/run
Time to configure sudo. As we launch browsers on other users from our X session, we need to add permission to our user to launch it without using a password.
# addgroup firejail # adduser myusername firejail # visudo -f /etc/sudoers.d/firejail
And then in the visudo editor put this line:
%firejail ALL=(ALL) NOPASSWD: /usr/bin/firejail, /usr/bin/firetools, /usr/bin/xpra, /usr/bin/vglrun
From now on i assume you are using google-chrome-unstable, of course change it with the browser you use.
Level 1: trusted browser
The goals for this browser session are:
- limited access to filesystem
- running with a dedicated user different from one i login on the machine and launch my desktop and other apps
- access to audio, mic, webcam
- persistent configs
- fully usage of browser plugins and extensions
- full access to networking
so, it offers limited protection, and it will be used only for trusted web sites. Also, it will share the same Xorg session with other apps, so, it will share resources and it cannot be considered really secure, just a little bit more than a common browser session.
edit the file /var/lib/firejail/anon-common.profile and put those line in:
whitelist ${DOWNLOADS} mkdir ~/.config mkdir ~/.config/google-chrome-unstable whitelist ~/.config/google-chrome-unstable mkdir ~/.cache mkdir ~/.cache/google-chrome-unstable whitelist ~/.cache/google-chrome-unstable mkdir ~/.pki whitelist ~/.pki include /etc/firejail/whitelist-common.inc whitelist /dev/dri whitelist /dev/null whitelist /dev/full whitelist /dev/zero whitelist /dev/tty whitelist /dev/pts whitelist /dev/ptmx whitelist /dev/random whitelist /dev/urandom whitelist /dev/log blacklist /media blacklist /mnt blacklist /srv
those are rules applied to all of our browser sessions.
Then, create and edit /var/lib/firehail/chrome-trusted.profile and put those lines in:
noblacklist ~/.config/google-chrome-unstable noblacklist ~/.cache/google-chrome-unstable include /etc/firejail/disable-common.inc include /etc/firejail/disable-programs.inc include /var/lib/firejail/anon-common.profile include /etc/firejail/disable-devel.inc netfilter whitelist /dev/nvidia0 whitelist /dev/nvidiactl whitelist /dev/shm whitelist /dev/snd whitelist /dev/video0 whitelist /dev/video1 whitelist /dev/video2 whitelist /dev/video3 whitelist /var/run/pcscd/ hostname trusted shell none
Note the line “whitelist /var/run/pcscd/”. This is needed if you have a smart card reader you want to use with chrome for certificate based authentication.
then, time to write a script to launch our browser. Create and edit /usr/local/bin/chrome-trusted and put those lines in:
xhost +SI:localuser:fjtrusted && sudo -u fjtrusted /usr/bin/firejail --name=trusted --profile=/var/lib/firejail/chrome-trusted.profile --env=DISPLAY=$DISPLAY /usr/bin/google-chrome-unstable --ssl-version-min=tls1 $@
save it, and give it execution permissions:
# chmod +x /usr/local/bin/chrome-trusted
then, you are ready to go. You now have a browser that have only limited access to filesystem ( /tmp, /home/trusted/Download and /home/trusted/.config|.cache things in read write, other parts of the fs in read only, other parts aren’t visible at all ) and fully working with permanent configuration, running as fjtrusted user.
Note that if you launch many concurrent sessions of the chrome-trusted browser, they will end up to open a new tab on the existent browser, as it has access to the real singleton socket opened by chrome, so, they will end up in the same browser session. Take care to know it.
Level 2: secure browser:
Goals for this level is to have a browser a little bit more secured than the trusted level, it will open different sessions if launched more time concurrently, it will NOT have persistent storage, and it can only save files in /tmp if you want to copy them in the “outside” system, if you download them in ~/Download, they will be discarded.
Also, this session will NOT have access to webcam.
It will, anyway, share the same X11 session with the rest of the system, and it will have access to the same networking as the rest. It has to be used with web sites you almost think are safe to browse, and it offer limited protection in case they aren’t.
Create and edit the file /var/lib/firejail/chrome-secure.profile and put those line in:
noblacklist ~/.config/google-chrome-unstable noblacklist ~/.cache/google-chrome-unstable include /etc/firejail/disable-common.inc include /etc/firejail/disable-programs.inc include /var/lib/firejail/anon-common.profile include /etc/firejail/disable-devel.inc netfilter whitelist /dev/nvidia0 whitelist /dev/nvidiactl whitelist /dev/shm whitelist /dev/snd whitelist /var/lib/firejail/templates/secure private-template /var/lib/firejail/templates/secure hostname secure shell none
then create the launcher script /usr/local/bin/chrome-secure:
xhost +SI:localuser:fjsecure sudo -u fjsecure /usr/bin/firejail --name=secure_$$ --profile=/var/lib/firejail/chrome-secure.profile /usr/bin/google-chrome-unstable --ssl-version-min=tls1 $@
and give it execution permission:
# chmod +x /usr/local/bin/chrome-secure
Now you should create your template configuration, your browser will be restored to this config every time you launch it. To do that you should launch outside the sandbox for the first time:
# sudo -u fjsecure bash $ /usr/bin/google-chrome-unstable
and configure it how you prefer, installing your preferred extensions, and do now any configuration you really want to have. This is time also to configure eventual proxies, or adblocker and so on. Every time you would like to change any configuration in permanent manner, you will have to launch the browser this way. After the configuration is ready, close the browser and it’s time to the next trick.
As firejail will override the fjsecure user with a tmpfs, it cannot copy your “template” config from /home/secure, so, the solution is to bind mount it on another directory and make firejail copy from there.
Edit /etc/rc.local and put this line before the final exit 0:
# mount --bind /home/secure/ /var/lib/firejail/templates/secure
and you are ready.
Level 3: paranoid browser
As the name suggest, this is the more paranoid configuration. This browser will be the most volatile, anonymous and secure browser in your system. It will not have access to any part of the fs in write mode, and even in read more it will have very limited access.
It will not access to sound, mic or cam at all. It will access network only through tor, and it will run on a separate networking namespace.
Also, it will NOT share clipboard with the X11 session, as it will run on a completely separate session using xpra.
as usual, edit the profile for this session, by creating the file /var/lib/firejail/chrome-paranoid.profile, and put those line in it:
noblacklist ~/.config/google-chrome-unstable noblacklist ~/.cache/google-chrome-unstable include /etc/firejail/disable-common.inc include /etc/firejail/disable-programs.inc include /var/lib/firejail/anon-common.profile include /etc/firejail/disable-devel.inc netfilter whitelist /var/lib/firejail/templates/paranoid private-template /var/lib/firejail/templates/paranoid whitelist /tmp/.X11-unix/ ipc-namespace nogroups hostname paranoid noexec /tmp net br1 ip 192.168.6.2 defaultgw 192.168.6.1 dns 192.168.6.1 shell none seccomp.drop umount2,ptrace,kexec_load,kexec_file_load,open_by_handle_at,init_module,finit_module,delete_module,iopl,ioperm,swapon,swapoff,syslog,process_vm_readv,process_vm_writev,sysfs,_sysctl,adjtimex,clock_adjtime,lookup_dcookie,perf_event_open,fanotify_init,kcmp,add_key,request_key,keyctl,uselib,acct,modify_ldt,pivot_root,io_setup,io_destroy,io_getevents,io_submit,io_cancel,remap_file_pages,mbind,get_mempolicy,set_mempolicy,migrate_pages,move_pages,vmsplice,chroot,tuxcall,reboot,nfsservctl,get_kernel_syms
sometime chrome complain about not be able to sandbox it’s processes, you can both launch it with –no-sandbox ( it’s already sandboxed! ) or you can drop the line “seccomp.drop” in the profile and trust the chrome sandbox.
NOTE: this profile isn’t yet really complete, i will prepare soon a better one with also /etc override and other tricks!
now it time for the launcher: edit /usr/local/bin/chrome-paranoid:
xhost +SI:localuser:fjparanoid export XAUTHORITY="/home/paranoid/.Xauthority" sudo -u fjanon /usr/bin/firejail --name=paranoid_$$ --profile=/var/lib/firejail/chrome-patanoid.profile --debug --x11=xpra sh -c "/usr/bin/google-chrome-unstable --no-sandbox --ssl-version-min=tls1 $@"
then, you will have to create your configuration as done with the secure profile, so
# sudo -u fjparanoid bash $ /usr/bin/google-chrome-unstable
here you will also have to configure a proxy for chrome to make it fully use tor. This isn’t needed to use it on normal internet web sites, but to make it resolve .onion internal address in tor, it must use a proxy.
I use privoxy, so, point it to 192.168.6.1, port 8118, type socks5
Also, you have to configure privoxy to listen on 192.168.6.1 port 8118, editing the file /etc/privoxy/config and configuring:
listen-address 192.168.6.1:8118 forward-socks4a / 127.0.0.1:9050 .
And then you must configure tor too editing /etc/tor/torrc
VirtualAddrNetworkIPv4 10.192.0.0/10 AutomapHostsOnResolve 1 TransPort 9040 TransListenAddress 192.168.6.1 DNSPort 53 DNSListenAddress 192.168.6.1
then, add a line on /etc/modules:
# echo "dummy" >> /etc/modules
to load the dummy module at boot, and in /etc/network/interfaces add this:
auto br1 iface br1 inet static bridge_ports dummy0 bridge_hello 2 bridge_maxage 12 bridge_stp off address 192.168.6.1 netmask 255.255.255.0
and start networking
# ifup br1
last pass, fix some configs at boot by add at rc.local those lines:
mount --bind /home/paranoid/ /var/lib/firejail/templates/paranoid # Tor's TransPort _trans_port="9040" # your internal interface _int_if="br1" iptables -t nat -I PREROUTING -i $_int_if -p tcp --dport 8118 -j RETURN iptables -t nat -A PREROUTING -i $_int_if -p udp --dport 53 -j REDIRECT --to-ports 53 iptables -t nat -A PREROUTING -i $_int_if -p tcp --syn -j REDIRECT --to-ports $_trans_port
save it, apply by hands all the commands in /etc/rc.local or restart your system, and the first step is ready.
What’s next?
The configurations we have done are great, and you can already start to use a more secure browser environment, but they are not enough, and many other things can be done.
In the next post, the part 3, i will talk about add cgroups to limit cpu and memory used by the browsers, i will add traffic shaping to the receipt, and than i will start talking about using apparmor to make the whole thing more secure.
Hope i will find the time to write the next part soon!
Leave a Reply
You must be logged in to post a comment.