Lightweight, Flexible and Rule-Based Network Isolation
airjail provides lightweight, rootless and flexible rule-based network
isolation for Linux in order to remove or restrict network access for programs.
For example, it can be used to run npx, but restrict the network access to
only allow downloading packages:
$ airjail --allow registry.npmjs.org -- npx prettier --check .It follows these design principles:
- Only Network Isolation: The purpose of
airjailis only network isolation. All other isolation types are well served by tools such asfirejailorbubblewrapand both of these tools can be combined withairjailfor exhaustive sandboxing. The only exception inairjailis blocking access to Unix domain and vsock sockets, which is an opt-in feature intended to support the network isolation in certain scenarios. - Transparent:
airjailaims to act like a transparent shim that interferes with the execution of the program as little as possible. It is therefore designed to provide the same experience regarding foregrounding/backgrounding/signaling/TTY as if the program was started withoutairjail. - Unprivileged: No privileges or capabilities are required for
airjail. When existing capabilities permit direct network namespace creation, airjail preserves the caller's identity and permissions except for dangerous capabilities that could bypass isolation or compromise the kernel. Without namespace setup capabilities, the process only loses supplementary groups except for the primary user group, which should not matter in most cases. - Easy to Use:
airjailis a single dependency-free binary that can easily be (cross-)compiled as it does not depend oncgo.
Operating Modes:
It is possible to configure airjail on-the-fly with CLI arguments or with a
YAML config. It can be used in the modes:
- No network access: Without
alloworblockrules, it blocks all network traffic. - Allowlist: With only
allowrules, it blocks all traffic except to the configured hosts. - Blocklist: With only
blockrules, it allows any traffic except for the blocked hosts. - Mixed: Mixing rules restricts access to the allowed hosts, but it allows
blockrules to formulate exceptions to wildcards or CIDR networks (e.g.--allow '*.example.com'--block 'bad.example.com').
Destination Types:
Each rule can reference destinations in multiple ways:
- IP Address: References a single IP, for example
--allow 10.0.0.1. - CIDR Network: References an entire network, for example
--allow 10.0.0.1/8 - Hostname: Hostnames will be resolved and the rule will be applied for the
hostname itself as well as the IP addresses it resolves to. If the hostname
does not resolve,
airjailwill return an error, unless--allow-unresolved-rulesorallow_unresolved_rules: trueis set. - Wildcard: Hostnames can be specified with a wildcard
*. This can be used to reference all subdomains (--allow '*.example.com'). In this case, it matchessub.example.com, but notexample.com. Since wildcards cannot be resolved, these rules are not expanded to include the respective IP addresses. - Ports: Each of the aforementioned types of destinations can be specified with and without port. Omitting the port means all ports are matched.
Local Sockets:
Airjail can optionally deny creation of Unix domain and vsock sockets. While
Unix sockets are local IPC rather than network access, they can often be used to
circumvent network restrictions. Vsock can similarly reach host or hypervisor
services without traversing the network namespace. For example, when SSH is used
with the ControlMaster feature on the host, network isolated processes could
connect to the ControlMaster socket in order to SSH into machines through an
existing connection that was established outside of the network isolation. On
the other hand, Unix domain sockets are also used extensively for normal
purposes. As such, this feature remains opt-in. Alternatively, however,
airjail can be used together with firejail, bubblewrap or a container to
remove dangerous sockets from the filesystem.
Dangerous Capabilities:
In permission-preserving namespace mode, airjail drops CAP_SYS_ADMIN,
CAP_NET_ADMIN, CAP_SYS_PTRACE, CAP_SYS_MODULE, CAP_SYS_RAWIO, CAP_BPF,
CAP_PERFMON, and CAP_CHECKPOINT_RESTORE from the child and its capability
bounding set. A capability can be preserved explicitly with a repeatable unsafe
option:
airjail --keep-unsafe-capability CAP_SYS_ADMIN commandKeeping dangerous capabilities is only recommended when there is an additional
sandboxing layer such as firejail or bubblewrap that ensures a safe runtime
environment. Rootless namespace mode continues to drop all setup capabilities.
CLI and Config:
If both a config and CLI rules are provided, the CLI rules
extend (if applicable, e.g. for allow/block) or overwrite the config values.
All arguments after and including the first positional arguments belong to the
sandboxed program. Optionally, airjail arguments and program arguments can be
separated with -- for clarity. The following two invocations are identical:
$ airjail \
--allow "127.0.0.1/8" --allow "example.com" --allow '*.example.com' \
--block "bad.example.com" --block "127.0.0.1:53" \
--restrict-sockets \
program -flag-a arg-b
$ airjail --config airjail.yml -- program -flag-a arg-bWith airjail.yaml:
allow:
- "127.0.0.1/8"
- "example.com"
- "*.example.com"
block:
- "bad.example.com"
- "127.0.0.1:53"
restrict_sockets: true
allow_unresolved_rules: falseairjail does not require cgo and can be compiled or cross-compiled with the
following command:
GOOS=linux go build .The following command runs all tests but has to be executed on Linux:
go test ./...Airjail creates network isolation by launching a program in an empty network
namespace that only creates a private loopback device. Initially, this prevents
the program from establishing any incoming or outgoing network traffic. If the
caller does not have the capabilities CAP_SYS_ADMIN and CAP_NET_ADMIN,
creating the network namespace is only possible when combining it with a user
namespace. If this is the case, the uid and gid is mapped in order to
preserve user and group permissions, but permissions from supplementary groups
are lost. If airjail is invoked without any configuration, this is all it
does. However, if rules are present, it creates a SOCKS and an HTTP/HTTPS proxy
outside of the namespace that each listen on a Unix domain socket that only
proxy allowed traffic. Inside of the namespace, two TCP listeners are created,
that forward incoming traffic through the Unix domain socket to aforementioned
proxies. Then, the program is started with proxy environment variables to make
it aware of the proxies. Therefore, airjail only allows outbound traffic for
proxy aware programs. Another limitation is that the program is not able to
perform DNS queries as hostnames are only resolved through the proxies. However,
these limitations are surprisingly less of an issue that expected in practice.
Support for non-proxy-aware programs is still planned (see roadmap).
The opt-in feature to restrict local sockets loads seccomp BPF rules that
are assembled in pure Go. These rules restrict access to the syscalls socket
and socketpair when called with AF_UNIX or AF_VSOCK. It also restricts
io_uring_setup and the legacy syscall socketcall, as these could also be
used to establish domain socket connections. It also forbids 32-bit syscalls.
The reason for airjail's development was the frustration about certain aspects
of other available tools. Each of these tools works great, but does not fit all
use-cases. Therefore, airjail solves specific network isolation use-cases
while allowing to be combined with the other tools for more exhaustive
sandboxing.
firejail:
- Namespace Setup:
firejail's network isolation is not flexible enough for many use cases. While--net=noneworks great for complete isolation, selective access is harder because it requires either specifying an IP or performing DHCP on a bridged interface. Specifying an IP is fine for servers but hard for workstations that often switch networks or multiple sandboxed process that each need a different IP. DHCP introduces a significant startup delay and can exhaust the DHCP pool if many sandboxed processes are started. Also, some network-related option do not support IPv6. - Access Rules: Selective network access in
firejailworks by specifying andiptablesconfig file which applied to the bridged interface. Having to create a config file prevents flexible on-the-fly filtering and writingiptablesrules is way harder than specifying destinations with--allowor--denyand the additional firewall capabilities are rarely need for such use-cases. - Privileges: Firejail required
rootaccess and is therefore packaged as asuidbinary.
You can profit from all other sandboxing capabilities of firejail while
leaving the network sandboxing to airjail by combining both:
firejail --noprofile --private -- airjail --allow example.com -- bash -ibubblewrap:
In contrast to firejail and airjail, bubblewrap does not allow selective
networking at all. It either allows all traffic or no traffic at all. Therefore,
it's feature set only slightly overlaps with airjail. You can keep using
bubblewrap and add selective network filtering by combining it with airjail.
sandbox-runtime:
Apart from the fact that sandbox-runtime also performs filesystem sandboxing,
the network isolation works similar to airjail by using proxy servers through
Unix domain sockets for outbound raffic. For some use-cases, airjail's network
isolation may still be desired in order to avoid the following issues:
- Execution Artifacts:
sandbox-runtime's approach to prevent the creation of blocked files that did not exist before causes empty files to be created. While these are cleaned on exit, they remain ifsrtis killed and can affect programs at runtime while they still exist. This also happens when no filesystem rules are configured becausesrtstill applies mandatory rules. These artifacts are not acceptable for a use-case in which only network sandboxing is required. - Dependencies:
sandbox-runtimerequiresripgrep,fdto be installed. Another undocumented dependency iswhichwhich is not present in many containers. Ifwhichis not present,srtclaims thatripgrepandfdare also not installed even though they are. - Mandatory Config File:
sandbox-runtimehas to be configured with a config file and therefore it cannot be used to start network sandboxed programs with custom rules on-the-fly. - C-Based seccomp Loader: In order to apply
seccomprules,sandbox-runtimeuses a custom loader written in C. When runningsrt, it looks for the loader in itsnode_modulesand when it is not at the expected location (because its build command was not invoked), it silently skips applyingseccomprules. This can only be notices with debug logs.
- DNS, UDP and non-proxy-aware TCP traffic: Currently,
airjailallows outbound traffic through the SOCKS5 and HTTP/HTTPS proxies. It is planned to generalize outbound traffic to allow DNS, UDP and non-proxy-aware TCP traffic. This will be achieved using in-namespacenftablesrules that redirect the remaining traffic to a listener that asks the kernel for the original destination and routes the traffic through the SOCKS5 server, using ASSOCIATE for UDP traffic. - Inbound Traffic: Currently
airjailprevents other processes from accessing ports opened by the sandboxed process. An--exposeoption is planned that forwards out-of-namespace traffic into the sandbox.