Firejail

From NixOS Wiki
Revision as of 03:20, 3 August 2023 by imported>Ljlapierre (I wrote a small section on my solution for getting app icons working with Firejail)

Firejail is an easy to use SUID sandbox program that reduces the risk of security breaches by restricting the running environment of untrusted applications using Linux namespaces, seccomp-bpf and Linux capabilities.

Installation

Add the following line to your system configuration to install and enable Firejail globally

programs.firejail.enable = true;

Usage

To start an application in a sandboxed enviroment use Firejail like this

firejail bash

For a graphical application like Firefox web browser, it is recommended to also use a profile

firejail --profile=$(nix --extra-experimental-features nix-command --extra-experimental-features flakes eval -f '<nixpkgs>' --raw 'firejail')/etc/firejail/firefox.profile firefox

Configuration

You can also use the Firejail NixOS module for a persistent usage of specific applications which should always run in Firejail. The following example wraps the browser Librewolf and the messenger Signal in a Firejail environment. The usual program path to librewolf and signal-desktop will be overwritten by the Firejail-wrapper.

programs.firejail = {
  enable = true;
  wrappedBinaries = {
    librewolf = {
      executable = "${pkgs.librewolf}/bin/librewolf";
      profile = "${pkgs.firejail}/etc/firejail/librewolf.profile";
      extraArgs = [
        # Required for U2F USB stick
        "--ignore=private-dev"
        # Enforce dark mode
        "--env=GTK_THEME=Adwaita:dark"
        # Enable system notifications
        "--dbus-user.talk=org.freedesktop.Notifications"
      ];
    };
    signal-desktop = {
      executable = "${pkgs.signal-desktop}/bin/signal-desktop --enable-features=UseOzonePlatform --ozone-platform=wayland";
      profile = "${pkgs.firejail}/etc/firejail/signal-desktop.profile";
      extraArgs = [ "--env=LC_ALL=C" "--env=GTK_THEME=Adwaita:dark" ];
    };
  };
};

Tips & tricks

Torify application traffic

Note: Parts of this instruction are not yet stable and will be available in the upcoming NixOS 23.05 release.

The following example configuration creates a virtual network bridge which can be used in Firejail as an isolated network namespace. All traffic originating from this interface will be routed through a local Tor service which will therefore anonymize your internet traffic.

services.tor = {
  enable = true;
  openFirewall = true;
  settings = {
    TransPort = [ 9040 ];
    DNSPort = 5353;
    VirtualAddrNetworkIPv4 = "172.30.0.0/16";
  };
};

networking = {
  useNetworkd = true;
  bridges."tornet".interfaces = [];
  nftables = {
    enable = true;
    ruleset = ''
      table ip nat {
        chain PREROUTING {
          type nat hook prerouting priority dstnat; policy accept;
          iifname "tornet" meta l4proto tcp dnat to 127.0.0.1:9040
          iifname "tornet" udp dport 53 dnat to 127.0.0.1:5353
        }
      }
    '';
  };
  nat = {
    internalInterfaces = [ "tornet " ];
    forwardPorts = [
      {
        destination = "127.0.0.1:5353";
        proto = "udp";
        sourcePort = 53;
      }
    ];
  };
  firewall = {
    enable = true;
    interfaces.tornet = {
      allowedTCPPorts = [ 9040 ];
      allowedUDPPorts = [ 5353 ];
    };
  };
};

systemd.network = {
  enable = true;
  networks.tornet = {
    matchConfig.Name = "tornet";
    DHCP = "no";
    networkConfig = {
      ConfigureWithoutCarrier = true;
      Address = "10.100.100.1/24";
    };
    linkConfig.ActivationPolicy = "always-up";
  };
};

boot.kernel.sysctl = {
  "net.ipv4.conf.tornet.route_localnet" = 1;
};

Run your preferred application inside the isolated Tor network

firejail --net=tornet --dns=46.182.19.48 --profile=$(nix --extra-experimental-features nix-command --extra-experimental-features flakes eval -f '<nixpkgs>' --raw 'firejail')/etc/firejail/firefox.profile firefox

You can use a custom DNS server if you don't want to use the one of your system. In this example, it's a server by the German privacy NGO Digitalcourage.

Using networkd-dispatcher it is possible to restart the Tor daemon every time network reconnect is performaed. This avoids having to wait for Tor network timeouts and reastablishes a new connection faster.

For a detailed explanation on this setup refer the original guide. Please note that this is a experimental setup which doesn't guarantee anonymity or security in any circumstances.

Add Desktop Icons to Firejailed Apps

I wanted to use Firejail to lock down Google Chrome. It worked well, however, I wanted a pretty icon for the application.

There are probably better ways to do this, but I accomplished it using Home Manager to symlink Chrome's actual icon set into your local icon directory.

## Firejail Config
programs.firejail = {
  enable = true;
  wrappedBinaries = {
    google-chrome-stable = {
      executable = "${pkgs.google-chrome}/bin/google-chrome-stable";
      profile = "${pkgs.firejail}/etc/firejail/google-chrome.profile";
      desktop = "${pkgs.google-chrome}/share/applications/google-chrome.desktop";
    };
  };
};

## Home Manager Config
home.file.".local/share/icons/hicolor/16x16/apps/google-chrome.png".source = "${pkgs.google-chrome}/share/icons/hicolor/16x16/apps/google-chrome.png";
home.file.".local/share/icons/hicolor/24x24/apps/google-chrome.png".source = "${pkgs.google-chrome}/share/icons/hicolor/24x24/apps/google-chrome.png";
home.file.".local/share/icons/hicolor/32x32/apps/google-chrome.png".source = "${pkgs.google-chrome}/share/icons/hicolor/32x32/apps/google-chrome.png";
home.file.".local/share/icons/hicolor/48x48/apps/google-chrome.png".source = "${pkgs.google-chrome}/share/icons/hicolor/48x48/apps/google-chrome.png";
home.file.".local/share/icons/hicolor/64x64/apps/google-chrome.png".source = "${pkgs.google-chrome}/share/icons/hicolor/64x64/apps/google-chrome.png";
home.file.".local/share/icons/hicolor/128x128/apps/google-chrome.png".source = "${pkgs.google-chrome}/share/icons/hicolor/128x128/apps/google-chrome.png";
home.file.".local/share/icons/hicolor/256x256/apps/google-chrome.png".source = "${pkgs.google-chrome}/share/icons/hicolor/256x256/apps/google-chrome.png";