Firejail Usage

Welcome to Firejail, a SUID security sandbox based on Linux namespaces and seccomp-bpf. We are a volunteer weekend project and our target is the desktop. Linux beginner or accomplished programmer, you are welcome to join us at http://github.com/netblue30/firejail.

In this project we take several solid, well-established enterprise security technologies, configure them, and make them available to home users. In other words, Firejail is a consumer product, as opposed to an enterprise product.

Our primary goal is ease of use and efficacy. One tech that fits the bill is sandboxing. It scales well, and requires little or no user input. We provide default sandbox configurations for over 1000 regular desktop applications, and we also added many features that were missing from the original Google implementation.

In this document I’ll start with SUID, move to sandbox configuration and management, and explore some of the most common usage scenarios.

 
 

SUID

SUID (Set owner User ID upon execution) is a special type of file permission. Most programs running on your computer inherit access permissions from the user logged in. SUID allows the program to run as root, rather than the user that started the program.

We use this kernel feature to start the sandbox, since most kernel technologies involved in sandboxing require root privileges. Once the sandbox is up, the privileges are dropped, and the real program starts as regular user. For example, in the case of a Firefox browser we build the sandbox as root, drop privileges, then we start the browser as a regular user.

SUID programs are considered dangerous on multiuser systems. It is not a great idea to install Firejail on such systems. If you have a server full of people logging in over SSH, forget about it!

Here are some of the ways to mitigate the problems introduced by SUID:

1. Configure /etc/firejail/firejail.users

The file contains a simple list with all the users allowed to run Firejail. If the file is not configured, all users are allowed to run Firejail.

2. Use firecfg

Integrate your desktop software with Firejail, by running firecfg utility described in Desktop Integration section. As a result, most programs will be sandboxed automatically, and a /etc/firejail/firejail.users file is created.

3. Set force-nonewprivs flag

Turn on force-nonewprivs flag in /etc/firejail/firejail.config file. As root, open the file in a text editor and add this line:

force-nonewprivs yes
 

The flag prevents rising privileges after the sandbox was started. It is believed to clean most SUID problems that will ever be attributed to Firejail.

Note: you should avoid doing this if you use a Chromium-based browser and have set kernel.unprivileged_userns_clone=0 (or are on one of the few distros that do this by default.) Unfortunately, Chromium-based browsers need to rise privileges in order to install their own SUID sandbox.

4. Create a special firejail group

This is equivalent to /etc/firejail/firejail.users trick above, but build using file system primitives. Create a firejail group, set /usr/bin/firejail executable as part of this group, change the file mode to 4750, and add only the users allowed to use Firejail to the group. Sample set of instructions on Debian:

$ su
# addgroup firejail
# chown root:firejail /usr/bin/firejail
# chmod 4750 /usr/bin/firejail
# ls -l /usr/bin/firejail
-rwsr-x--- 1 root firejail 1584496 Apr 5 21:53 /usr/bin/firejail
 

To add the user to the group, type:

# usermod -a -G firejail username
 

A logout and login back is necessary after adding the user to the group.

 

Install

Try installing Firejail using your package manager first. Firejail is included in a large number of distributions. Among them Arch, Debian, Gentoo, Mint, Slackware, Ubuntu.

You can find newer versions of the software on our download page. We keep there up to date .deb packages for Debian/Ubuntu/Mint. You can also download the source archive and compile it yourself. There are no external dependencies, all you need is a C compiler (sudo apt install build-essential) and a regular compile/install (./configure && make && make install).

 

Basic Usage

Start the sandbox by prefixing your application with “firejail”:

$ firejail firefox
Reading profile /etc/firejail/firefox.profile
Reading profile /etc/firejail/disable-common.inc
Reading profile /etc/firejail/disable-programs.inc
Reading profile /etc/firejail/disable-devel.inc
Reading profile /etc/firejail/whitelist-common.inc
Blacklist violations are logged to syslog
Child process initialized
 

Any type of GUI programs should work with sound, video and hardware acceleration support if available on the platform.

 

Desktop Integration

To integrate Firejail with your desktop environment run:

$ sudo firecfg

As a result:

  • Clicking on desktop manager icons and menus will sandbox the application automatically. We support Cinnamon, KDE, LXDE/LXQT, MATE and XFCE desktop managers, and partially Gnome 3 and Unity.
  • Clicking on files in your file manager will open the file in a sandboxed application.

You can always check if your application was sandboxed by running firejail –list in a terminal. Or you can keep a terminal running firejail –top to track your sandboxes.

Monitoring sandboxes with “firejail –top”

Some users prefer desktop launchers for starting applications. A launcher is a regular text file with .desktop extension placed in Desktop directory. This is an example for Mozilla Firefox browser:

$ cat ~/Desktop/firefox.desktop
[Desktop Entry]
Type=Application
Name=Firefox
Icon=firefox.png
Exec=firejail firefox
Terminal=false
 

Security Profiles

We distribute Firejail with over 1000 security profiles, covering most common Linux applications. Profile files have a friendly syntax, and are stored in /etc/firejail directory.

Profiles build by users should be placed in ~/.config/firejail directory. Use include command to bring in the original profile file, then add your commands. For example, this is a profile for a VLC media player without network access:

$ cat ~/.config/firejail/vlc.profile
include /etc/firejail/vlc.profile
net none
 

For more information see Building Custom Profiles.

 

Managing Sandboxes

The relevant command line options are as follow:

  • firejal –list – list all running sandboxes
  • firejail –tree – list processes running in each sandbox
  • firejail –top – similar to Linux top command

If a sandbox is not responding and you need to shut it down, use –shutdown option. First, list the sandboxes,

$ firejail --list
3787:netblue:firejail --private
3860:netblue:firejail firefox
3963:root:firejail /etc/init.d/nginx start
 

and then shutdown the sandbox using the PID number from the list. In this example I shut down Firefox browser:

$ firejail --shutdown=3860
 

Use –join option if you need to join an already running sandbox. It works like a regular terminal login into the sandbox. The new shell session inherits all the sandbox restrictions:

$ firejail --join=3860
Switching to pid 3861, the first child process inside the sandbox

 

[netblue@debian ~]$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
netblue 1 12.1 4.5 996168 320576 ? Sl 07:33 1:59 firefox
netblue 77 2.5 0.0 20916 3716 pts/2 S 07:49 0:00 /bin/bash
netblue 120 0.0 0.0 16840 1256 pts/2 R+ 07:49 0:00 ps aux

[netblue@debian ~]$

 

Private Mode

Private mode is a quick way to hide all the files in your home directory from your program. Enable it using –private command line option:

$ firejail --private firefox
 

Firejail mounts a temporary filesystem (tmpfs) on top of /home/user directory. Any files created in this directory will be deleted when you close the sandbox. You can also use an existing directory as home for your sandbox. This allows you to have a persistent home for your application:

$ firejail --private=~/my_private_dir firefox
 

chroot

Most of the time I’m happy with the applications distributed by Debian stable, but occasionally I need a much newer version of a program or another. In this case, I build a Debian unstable chroot on my Debian stable system, and run my application (youtube-dl) using Firejail’s chroot feature. These are the steps:

Step 1: Build a basic Debian sid filesystem:

$ sudo mkdir /chroot-sid
$ sudo debootstrap --arch=amd64 sid /chroot-sid
 

Step 2: Add a regular user account and install the target application (youtube-dl in this example):

$ sudo firejail --noprofile --chroot=/chroot-sid
# adduser netblue
# apt-get install youtube-dl
# exit
 

Step 3: Run the application:

$ firejail --chroot=/chroot-sid
$ youtube-dl https://www.youtube.com/watch?v=Yk1HVPOeoTc
 

The setup also works for most GUI programs, you just have to bring them in:

$ sudo firejail --noprofile --chroot=/chroot-sid
# apt-get update
# apt-get upgrade
# apt-get install handbrake mpv
 

AppImage

The previous chroot trick will only get you so far. As more and more complex applications are built, new ways of distributing software emerged. My favorite is AppImage.

Here is a simple usage example: the latest and greatest Kdenlive video editor built and distributed by the developer.

Kdenlive AppImage running in Firejail
Kdenlive AppImage running in Firejail

I create a private home directory for this application and start the appimage in this directory:

$ mkdir ~/mykdenlive
$ firejail --private=~/mykdenlive --appimage ~/Downloads/Kdenlive-17.12.0d-x86_64.AppImage
Mounting appimage type 2
Reading profile /etc/firejail/kdenlive.profile
Reading profile /etc/firejail/disable-common.inc
Reading profile /etc/firejail/disable-devel.inc
Reading profile /etc/firejail/disable-exec.inc
Reading profile /etc/firejail/disable-interpreters.inc
Reading profile /etc/firejail/disable-programs.inc
firejail version 0.9.73

Parent pid 17670, child pid 17673
Dropping all Linux capabilities and enforcing default seccomp filter
Child process initialized in 60.82 ms
...

 

All the files I am editing are in mykdenlive directory, no other files in my home are visible in the sandbox. You can find more examples in our AppImage Support document.

 

AppArmor

Currently, AppArmor is enabled by default in Ubuntu and Debian kernels. On other distributions you’ll have to enable it yourself. These are the instructions for Arch Linux and Gentoo.

Like Firejail, AppArmor restricts programs’ capabilities with per-program profiles. If you have an AppArmor profile for your application, use it! There is some overlap between the two technologies: both of them restrict the same filesystem. In case one of them misses something important, hopefully the other one picks it up.

If you don’t have an AppArmor profile for your specific application, we give you one. The profile is placed in /etc/apparmor.d/firejail-default when you install Firejail. You would need to load it into the kernel by running the following command:

$ sudo aa-enforce firejail-default
 

or reboot the computer and Firejail AppArmor profile will be loaded automatically into the kernel.

When you start your application, use –apparmor command line option to enable AppArmor confinement inside your sandbox:

$ firejail --apparmor warzon2100
 

In your Firejail profile files, use apparmor command. This is the previous warzone2100 profile with AppArmor support:

$ cat ~/.config/firejail/warzone2100.profile
include /etc/firejail/warzone2100.profile
net none
apparmor

Note: more than half the profiles distributed with Firejail software already have AppArmor enabled.

 

EncFS and SSHFS

EncFS is an encrypted filesystem built on top of FUSE library. It is available on most Linux distributions, and it runs in user space. Integrating EncFS with Firejail brings up an interesting problem. Take a look at this paragraph in man encfs:

By default, all FUSE based filesystems are visible only to the user who mounted them. No other users (including root) can view the filesystem contents.

For various reasons, during sandbox setup Firejail handles EncFS filesystems as root user. FUSE will prevent the root access to user’s files and the sandbox will fail to start.

This problem affects all filesystems based on FUSE library. Quite popular among them is sshfs. The solution is to allow root user to access the filesystem using allow_root FUSE mount flag. On some distributions (Debian & friends) you might have to change FUSE config file in /etc/fuse.conf and uncomment user_allow_other line:

$ cat /etc/fuse.conf
# /etc/fuse.conf - Configuration file for Filesystem in Userspace (FUSE)

 

# Set the maximum number of FUSE mounts allowed to non-root users.
# The default is 1000.
#mount_max = 1000

# Allow non-root users to specify the allow_other or allow_root mount options.
user_allow_other

 

This is how to start a Firejail-friendly EncFS:

$ encfs -o allow_root ~/.crypt ~/crypt
 

And this is a SSHFS:

$ sshfs -o reconnect,allow_root netblue@192.168.1.25:/home/netblue/work work
 

After mounting your FUSE filesystem, start your sandboxes the regular way.

 

Network Namespace

A network namespace is a new, independent TCP/IP stack attached to the sandbox. The stack has its own routing table, firewall and set of interfaces. Apart from “net none” and an optional “netfilter”, we never configure networking features in the security profiles distributed with the sandbox software.

You can create a network namespace with –net command. We support the following type of interfaces:

  • –net=eth0 – regular wired Ethernet interfaces (replace eth0 with the name of your interface).
  • -net=wlan0 – wireless Ethernet interfaces
  • -net=br0 – bridge interfaces
  • –net=tap0 – tap interfaces used mainly to build VPN tunnels
 

Direct Network Setup

Run ip addr show to find the name of your wired/wiredless Ethernet interface (eth0 in my case):

$ ip addr show
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether e0:3f:4f:72:14:a9 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.50/24 brd 192.168.1.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::e23f:49ff:fe7a:1409/64 scope link
valid_lft forever preferred_lft forever
 

and start the sandbox

$ firejail --net=eth0 firefox
 

You can specify an IP address (–ip=192.168.1.207), a range of IP addresses (–iprange=192.168.1.100,192.168.1.240) to choose from, or you can let the sandbox find a random unused IP address on your network.

Because of the way macvlan kernel drivers are wired to the real Ethernet interface, it is impossible for the sandboxed application to access TCP/IP services running on the host, and the other way around. The sandbox and the host are totally disconnected, even if both of them are on the same network.

Direct network
Direct network

This is a Firefox profile adding network namespace support to the sandbox:

$ cat ~/.config/firejail/firefox-exr.profile
include /etc/firejail/firefox-esr.profile
net eth0
iprange 192.168.1.100,192.168.1.240
 

Similar, a profile for Transmission:

$ cat ~/.config/firejail/transmission-qt.profile
include /etc/firejail/transmission-qt.profile
net eth0
iprange 192.168.1.100,192.168.1.240
 

In the examples above, I let Firefox and Transmission fight for address in 192.168.1.100 – 192.168.1.240 range. Actually, all network clients on my home network are fighting for addresses in this range. To monitor the traffic use firejail –netstats.

Monitoring network traffic with “firejail –netstats”
 

Routed Network Setup

In a routed setup sandboxes are connected to a Linux bridge, and the bridge traffic is routed by the host. This setup works for both wired and wireless interfaces. Address translation needs to be enabled on the host in order for the sandbox traffic to go out on Internet:

routednet

Script for setting this up (I assume a wired eth0 interface for the system):

#!/bin/bash

 

#
# Routed network configuration script
#

# bridge setup
brctl addbr br0
ifconfig br0 10.10.20.1/24 up

# enable ipv4 forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward

# netfilter cleanup
iptables --flush
iptables -t nat -F
iptables -X
iptables -Z
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT

# netfilter network address translation
iptables -t nat -A POSTROUTING -o eth0 -s 10.10.20.0/24 -j MASQUERADE

 

Starting the sandbox:

$ firejail --net=br0 firefox
 

For running servers I replace network address translation with port forwarding in the script above:

# host port 80 forwarded to sandbox port 80
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 10.10.20.10:80
 

Traffic Shaping

Network bandwidth is an expensive resource shared among all sandboxes running on a system. Traffic shaping allows the user to increase network performance by controlling the amount of data that flows into and out of sandboxes. Firejail implements a simple rate-limiting shaper based on Linux tc command. The shaper works at sandbox level:

$ firejail --name=browser --net=eth0 firefox &
$ firejail --bandwidth=browser set eth0 80 20 &
 

In this example I set a bandwidth of 80 kilobytes per second on receive side and a bandwidth of 20 kilobytes per second on transmit side. As the sandbox is running, I can change the values or even reset them:

$ firejail --bandwidth=browser set eth0 40 10
$ firejail --bandwidth=browser clear eth0
 

X11 Sandboxing

If you don’t have Wayland running, the most reliable way to sandbox X11 with Firejail is Xephyr. Xephyr is a light X11 server you can run in parallel with the main xorg server on your machine. The software is part of X.Org.

In this example I use Firejail to sandbox two applications, Inkscape and Firefox, in a the same Xephyr window.

Step 1. Sandbox Xephyr

In order to be able to rearrange and resize windows, I start OpenBox window manager on top of Xephyr. Notice –net=none command.

$ firejail --x11=xephyr --net=none openbox&
 

Note: You can replace openbox with any other supported window manager. Currently we support openbox, fluxbox, blackbox, awesome and i3.

As a rule, whenever we are dealing with X11 we also need to install a new network namespace. This is the only way to block access to the abstract Unix socket opened by the main X11 server already running on your box. Every application sandboxed on this display server is required to install a network namespace, either –net=none or –net=eth0.

Step 2. Find the display number for the new server

Each X11 server server running on your box is identified by a unique display number. This number is used to connect X11 applications to a specific X11 server. Run firemon –x11 to find Xephyr’s display number:

$ firemon --x11
2377:netblue::/usr/bin/firejail /usr/bin/Xephyr -ac -br -noreset -screen 1024x
2394:netblue::firejail --net=none openbox
DISPLAY :265
 

The display number is 265. Notice how Xephyr and OpenBox are running in independent Firejal sandboxes. Let’s start some more sandboxes:

Step 3. Start your applications

$ DISPLAY=:265 firejail --net=eth0 firefox -no-remote &
$ DISPALY=:265 firejail --net=none inkscape &
 
Independent Inkscape and Firefox sandboxes running in a Xephyr X11 window
Independent Inkscape and Firefox sandboxes running in a Xephyr X11 window

In this moment I have 4 independent sandboxes, one for each program involved: Xephyr, OpenBox, Inkscape and Firefox.

X11 sandboxing using Xephyr
X11 sandboxing using Xephyr
 

Servers

Always use a new network namespace for server sandboxes in order to isolate services such as SSH, X11, DBus etc. running on your workstation. This is an Apache server example:

# firejail --net=eth0 --ip=192.168.1.244 /etc/init.d/apache2 start
 

The default server profile is /etc/firejail/server.profile. To further restrict your servers, here are some ideas:

# capabilities list for Apache server
caps.keep chown,sys_resource,net_bind_service,setuid,setgid

 

# capabilities list for nginx server
caps.keep chown,net_bind_service,setgid,setuid

# use a netfilter configuration
netfilter /etc/firejail/webserver.net

# instead of /var/www/html for webpages, use a different directory
bind /server/web1,/var/www/html

 

You can run thousands of webservers on a regular system, each one with its own IP address, webpages, and applications.

And this is a Bind 9 DNS server setup – you can find the profile used in the video on our blog here.

114 thoughts on “Firejail Usage

  1. Pingback: Install and run Zoom Client inside a sandbox ~ Ask Ubuntu ~ QnA World

  2. Pingback: Firejail/Network namespaces without sudo ~ Unix & Linux ~ QnA World

  3. Pingback: How to Getting Started with Firejail on GNU/Linux | tutorialforlinux.com

  4. Pingback: Firejail - безопасный запуск потенциально уязвимых приложений

  5. Rebecca Steinberg

    Hi there! I’m doing a summer research project and I have a general question. Given how complete seccomp filters are, are the namespace filters there to just manage whether a program can access system calls outside their namespace? And also if anyone knows, why would someone want to use capabilities and seccomp filters, if seccomp filters seem so complete? Thanks in advance!

    Like

    Reply
  6. Pingback: [server] wlan0을 eth0에 브리징 - 리뷰나라

  7. catalinux

    hi, i skip ”3. Create a special firejail group” because a get bash: /usr/bin/firejail: Permission denied

    Why?

    Like

    Reply
  8. catalinux

    Hi, i did step 3. Create a special firejail group.
    # addgroup firejail
    # chown root:firejail /usr/bin/firejail
    # chmod 4750 /usr/bin/firejail
    # ls -l /usr/bin/firejail
    -rwsr-x— 1 root firejail 466280 Jun 29 16:09 /usr/bin/firejail
    # usermod -a -G firejail myuser
    and i get this:
    myuser@myhost:~$ firejail
    bash: /usr/bin/firejail: Permission denied

    Like

    Reply
  9. firejail fan

    Sorry if this is not the right place to ask this but could you please add the ability to “runas” a limited user similar to what can be done with sudo? Such a feature would also limit the ability of programs to escape a firejail since the limited user could be excluded from firejail’s permitted users. As it is now I use sudo to accomplish this but it is not as secure as using firejail would be. As an example if I am user “prime” and I want to run a browser as user “limited” I would use the command: sudo -u $USR -nHi env HOME=/home/$USR env PWD=/home/$USR env XAUTHORITY=/home/$USR/.Xauthority
    Where USR=”limited” and note I copy prime’s ~/.Xauthority to limited’s home folder.
    The issue is sudo must be used to run firejail as the limited user and the limited user must be allowed to run firejail which is a security issue. If firejail could do the same as sudo the limited user could be denied access to using firejail allowing only the “prime” user to launch programs as limited. Hopefully that makes sense. I may add this ability myself soon but you know your program code better than I and you could probably add this feature in a jiffy. Thanks!

    Like

    Reply
  10. Thomas

    Hi!
    The force-nonewprivs setting in firejail.config is scripted as “# force-nonewprivs yes” (or no depending). The config file says simply to use “yes” or “no” to enable, but do we need to delete the # for these settings to be acknowledged? Normally the # causes configs to ignore the line. Thanks!

    Like

    Reply
      1. Thomas

        Thanks! I made the correction and noticed it is preventing some applications from functioning (VirtualBox, for example), so commented it back out. But at least I know the setting works if I need it!

        Like

  11. Pingback: How to monitor and manage ALL internet network activity

  12. Pingback: 유닉스 프로그램을 특정 네트워크 인터페이스에 바인딩 네트워크 인터페이스 (eth1 및 eth2)를 통해 액세스 - How IT

  13. fern

    hi noticed a typo

    2.5 Managing Sandboxes

    The relevant command line options are as follow:

    firejail –list – list all running sandboxes
    firejail –tree – list all running sandboxes and the processes running in each sandbox
    firejail –top – similar to Linux top command

    should be, firejail –top – similar to Linux list command …. i think???
    ———————————–
    trying to figure out how/why appimage starts but cant use it. More digging… it is all new to me and i am old!

    all the best.

    Like

    Reply
  14. zhoujuan

    Hi!
    How to configure firejail to achieve the file isolation? firejail will create a working directory /proc/[ID]/root when starting a application , I try to create a file through the application, expect when the application exits, the file will be deleted. However, Even after the application exits, the file remains in the root directory of the system. as follows:

    1. Open the lowriter app with firejail
    2. Create a file test.txt in the application
    3. Check the root directory of the working directory and the root directory of the system, Both directories have this file.
    zj@zj-virtual-machine:/chroot-sid$ firejail –list
    71895:zj:libreoffice:firejail lowriter
    zj@zj-virtual-machine:/chroot-sid$ sudo ls /proc/71895/root/home/zj/mytest/
    test.txt
    zj@zj-virtual-machine:/chroot-sid$ ls /home/zj/mytest/
    test.txt
    zj@zj-virtual-machine:/chroot-sid$

    4. After the application exits, files in the root directory are not deleted
    zj@zj-virtual-machine:/chroot-sid$ firejail –list
    zj@zj-virtual-machine:/chroot-sid$ sudo ls /proc/71895/root/home/zj/mytest/
    Ls: cannot access ‘/ proc / 71895 / root/home/what zj had/mytest/’ : the file or directory
    zj@zj-virtual-machine:/chroot-sid$ ls /home/zj/mytest/
    test.txt
    zj@zj-virtual-machine:/chroot-sid$

    Like

    Reply

Leave a comment