RootlessKit Documentation

repository·master·Indexed 23 days ago

https://github.com/rootless-containers/rootlesskit

A Linux-native implementation of 'fake root' using user namespaces that allows unprivileged users to run container engines like Docker and Kubernetes in Rootless mode. It provides tools for spawning processes in isolated namespaces (User, Mount, PID, UTS, IPC), managing network namespaces via drivers like slirp4netns, and isolating filesystems using the --copy-up flag. Includes the rootlessctl CLI for managing ports and retrieving instance information via a Unix domain socket.

Tokens
11.1K
Snippets
22
Records
63
Agent score
78%

What's inside RootlessKit

  1. Overview of RootlessKit Network Drivers

    master

    RootlessKit provides several drivers to manage network connectivity and isolation within user namespaces. The choice of driver affects performance, security, and feature support (like IPv6 or ICMP/ping).

    Available Drivers

    • --net=host: Uses the host network namespace (default). No isolation.
    • --net=slirp4netns: Uses slirp4netns for usermode networking (recommended).
    • --net=pasta: Uses pasta (experimental).
    • --net=vpnkit: Uses VPNKit.
    • --net=lxc-user-nic: Uses lxc-user-nic (experimental).
    • --net=gvisor-tap-vsock: Uses gvisor-tap-vsock (experimental).

    Performance Comparison (iperf3)

    DriverMTU=1500MTU=65520
    slirp4netns1.69 Gbps8.11 Gbps
    vpnkit0.14 Gbps(Unsupported)
    pasta0.24 Gbps31.9 Gbps
    gvisor-tap-vsock2.46 Gbps8.75 Gbps
    lxc-user-nic49.1 Gbps50.7 Gbps
  2. How RootlessKit parent and child processes communicate

    master

    RootlessKit uses a specific handshake sequence to coordinate the initialization of namespaces and drivers between the parent process and the child process. The sequence ensures that the environment is correctly set up before the user's application runs.

    The initialization sequence follows this order:

    1. Handshake: Parent sends ParentHello $\rightarrow$ Child responds with ChildHello.
    2. User Namespace: Parent signals ParentInitIdmapCompleted $\rightarrow$ Child responds with ChildInitUserNSCompleted.
    3. Network Driver: Parent signals ParentInitNetworkDriverCompleted.
    4. Port Driver: Parent signals ParentInitPortDriverCompleted.
  3. Understand the RootlessKit state directory structure

    master

    When RootlessKit is running, it creates a state directory containing several files used for synchronization, communication, and networking. Understanding these files is useful for debugging or managing the lifecycle of RootlessKit processes.

    Common files in the state directory:

    • lock: A lock file used for synchronization.
    • child_pid: Contains the PID of the child process.
    • api.sock: A Unix domain socket used for the RootlessKit API.
    • netns: A detached network namespace file.

    Driver-specific files:

    • If using the slirp4netns network driver, you will find .s4nn.sock.
    • If using the builtin port driver, you will find .bp.sock and .bp-ready.pipe.
  4. Configure subuid and subgid for RootlessKit

    master

    RootlessKit requires newuidmap and newgidmap (usually provided by the uidmap package) to be installed on the host. Additionally, /etc/subuid and /etc/subgid must be configured to provide more than 65536 sub-IDs for your user.

    Example verification:

    $ id -u
    1001
    $ whoami
    penguin
    $ grep "^$(whoami):" /etc/subuid
    penguin:231072:65536
    $ grep "^$(whoami):" /etc/subgid
    penguin:231072:65536
    $ id -u
    1001
    $ whoami
    penguin
    $ grep "^$(whoami):" /etc/subuid
    penguin:231072:65536
    $ grep "^$(whoami):" /etc/subgid
    penguin:231072:65536
  5. Configure mount propagation in RootlessKit

    master

    By default, the mount namespace created by RootlessKit uses rprivate propagation.

    Starting from v0.9.0, you can change this behavior using the --propagation flag:

    • --propagation=rslave: Sets propagation to rslave.
    • --propagation=rshared: Sets propagation to rshared. Note: This mode is known to be incompatible with --copy-up.

    Important Requirement: Both rslave and rshared modes require the host root filesystem to be mounted with shared propagation to function correctly. You can verify your host's root mount propagation status using the following command:

  6. Use the recommended `slirp4netns` network driver

    master

    The --net=slirp4netns driver isolates the network namespace using slirp4netns for usermode networking. It is the recommended driver for most users.

    Pros:

    • Supports network-namespaced operations (iptables, tcpdump).
    • Supports ping (if ping_group_range is configured).
    • Supports hardening via mount namespace and seccomp using --slirp4netns-sandbox=auto and --slirp4netns-seccomp=auto.
    • Supports IPv6 via the --ipv6 flag.

    Cons:

    • Extra performance overhead.
    • Supports only TCP, UDP, and ICMP Echo.

    Requirements: Install slirp4netns v0.4.0 or later via your package manager (dnf or apt) or from source.

    Best Practices:

    • Use --copy-up=/etc to ensure /etc/resolv.conf is correctly handled.
    • Use --disable-host-loopback to prevent host 127.0.0.1 ports from being accessible as 10.0.2.2 in the namespace.
    • Use --cidr=<CIDR> to change the default network configuration (e.g., --cidr=10.0.3.0/24).
    $ rootlesskit --net=slirp4netns --copy-up=/etc --disable-host-loopback bash
  7. Perform Cgroup2 evacuation in RootlessKit

    master

    Since v0.13.0, RootlessKit supports Cgroup2 evacuation via the --evacuate-cgroup2 flag. This is used to move processes from a current cgroup group to a new evacuation group.

    For example, if the current process is in the /foo group and the evacuation group name is bar:

    1. All processes in /foo are moved to /foo/bar by writing their PIDs into /sys/fs/cgroup/foo/bar/cgroup.procs.
    2. RootlessKit attempts to enable as many controllers as possible for the /foo/* groups by writing to /sys/fs/cgroup/foo/cgroup.subtree_control.

    Example usage with systemd-run: systemd-run -p Delegate=yes --user -t rootlesskit --cgroupns --pidns --evacuate-cgroup2=evac --net=slirp4netns bash

    systemd-run -p Delegate=yes --user -t rootlesskit --cgroupns --pidns --evacuate-cgroup2=evac --net=slirp4netns bash
  8. Use the experimental `gvisor-tap-vsock` network driver

    master

    The --net=gvisor-tap-vsock driver uses gvisor-tap-vsock for usermode networking.

    Pros:

    • Supports network-namespaced operations.

    Cons:

    • Supports only TCP, UDP, and ICMP Echo.
    • Does not support IPv6 routing (--ipv6).
    • ICMP Echo replies are forged.
    • Port-forward throughput is currently slower than other drivers when used with the gvisor-tap-vsock port driver.

    Best Practices:

    • Use --copy-up=/etc and --disable-host-loopback.
    $ rootlesskit --net=gvisor-tap-vsock --copy-up=/etc --disable-host-loopback bash
  9. Use the experimental `pasta` network driver

    master

    The --net=pasta driver (experimental since v2.0) uses pasta (passt).

    Pros:

    • Supports network-namespaced operations.
    • Supports ping (if ping_group_range is configured).
    • Very fast TCP port forwarding when used with --port-driver=implicit.
    • Can retain source IP addresses with --port-driver=implicit.

    Cons:

    • Lacks an API for explicit port forwarding (via rootlessctl).

    Requirements:

    • Requires pasta version 2023_06_25.32660ce or later (later versions highly recommended).
    • Note for Ubuntu users: Some versions of the passt package may require setting kernel.apparmor_restrict_unprivileged_userns to 0 due to missing AppArmor profiles.
  10. Expose privileged ports (< 1024)

    master

    By default, unprivileged users cannot bind to ports below 1024. To allow RootlessKit to expose these ports, use one of the following methods:

    Add net.ipv4.ip_unprivileged_port_start=0 to /etc/sysctl.conf (or a file in /etc/sysctl.d/) and apply the changes with:

    sudo sysctl --system

    Method 2: Capability-based (Only for builtin driver)

    If you are using the builtin port driver, you can avoid changing system-wide sysctl settings by granting the CAP_NET_BIND_SERVICE capability to the rootlesskit binary:

    sudo setcap cap_net_bind_service=ep $(pwd rootlesskit)
  11. Use the static subid source

    master

    The static source (--subid-source=static) reads subids directly from the /etc/subuid and /etc/subgid files.

    For RootlessKit to function correctly, these files must contain more than 65,536 sub-IDs for the current user. A typical entry looks like username:start_id:count (e.g., penguin:231072:65536).

    --subid-source=static