Bubblewrap/示例
dhcpcd
创建一个简单的 dhcpcd 沙盒
- 确定可用的内核命名空间
$ ls /proc/self/ns cgroup ipc mnt net pid uts
user
表示内核构建时使用了 CONFIG_USER_NS=n
或者用户命名空间受限。- 将整个主机的
/
目录以读写方式绑定到沙盒中的/
- 在沙盒中的
/dev
挂载一个新的 devtmpfs 文件系统 - 创建新的 IPC 和 控制组 命名空间
- 创建一个新的 UTS 命名空间并将主机名设置为
dhcpcd
# /usr/bin/bwrap --bind / / --dev /dev --unshare-ipc --unshare-cgroup --unshare-uts --hostname dhcpcd /usr/bin/dhcpcd -q -b
Unbound
创建一个更精细和复杂的 Unbound 沙盒
- 将系统
/usr
目录以只读方式绑定到沙盒中的/usr
- 在沙盒中创建从系统
/usr/lib
目录到/lib64
的符号链接 - 将系统
/etc
目录以只读方式绑定到沙盒中的/etc
- 在沙盒中创建空的
/var
和/run
目录 - 在沙盒中的
/dev
挂载一个新的 devtmpfs 文件系统 - 创建新的 IPC 和 PID 以及控制组命名空间
- 创建一个新的 UTS 命名空间并将主机名设置为
unbound
# /usr/bin/bwrap --ro-bind /usr /usr --symlink usr/lib /lib64 --ro-bind /etc /etc --dir /var --dir /run --dev /dev --unshare-ipc --unshare-pid --unshare-cgroup --unshare-uts --hostname unbound /usr/bin/unbound -d
unbound.service
)的 bubblewrap 封装MuPDF
bwrap 的强大功能和灵活性在使用 shell 包装器创建环境时得到最佳体现
- 将主机
/usr/bin
目录以只读方式绑定到沙盒中的/usr/bin
- 将主机
/usr/lib
目录以只读方式绑定到沙盒中的/usr/lib
- 在沙盒中创建从系统
/usr/lib
目录到/lib64
的符号链接 - 在沙盒中创建一个覆盖
/usr/lib/gcc
的 tmpfs 文件系统- 这有效地将
/usr/lib/gcc
的内容列入黑名单,使其不会出现在沙盒中
- 这有效地将
- 在沙盒中创建一个新的 tmpfs 文件系统作为
$HOME
目录 - 将
.Xauthority
文件和 Documents 目录以只读方式绑定到沙盒中- 这有效地将
.Xauthority
文件和 Documents 目录递归地列入白名单
- 这有效地将
- 在沙盒中创建一个新的 tmpfs 文件系统作为
/tmp
目录 - 通过将 X11 套接字以只读方式绑定到沙盒中,将其列入白名单
- 克隆并为正在运行的内核支持的所有命名空间创建私有容器
- 如果内核不支持非特权用户命名空间,则跳过其创建并继续
- 不要将网络组件放入私有命名空间
- 这允许网络访问以跟踪 URI 超链接
#!/bin/sh #~/bwrap/mupdf.sh (exec bwrap \ --ro-bind /usr/bin /usr/bin \ --ro-bind /usr/lib /usr/lib \ --symlink usr/lib /lib64 \ --tmpfs /usr/lib/gcc \ --tmpfs $HOME \ --ro-bind $HOME/.Xauthority $HOME/.Xauthority \ --ro-bind $HOME/Documents $HOME/Documents \ --tmpfs /tmp \ --ro-bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X0 \ --unshare-all \ --share-net \ /usr/bin/mupdf "$@")
$ bwrap \ --ro-bind /usr/bin /usr/bin \ --ro-bind /usr/lib /usr/lib \ --symlink usr/lib /lib64 \ --tmpfs /usr/lib/gcc \ --tmpfs $HOME \ --ro-bind $HOME/.Xauthority $HOME/.Xauthority \ --ro-bind $HOME/Desktop $HOME/Desktop \ --tmpfs /tmp \ --ro-bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X0 \ --unshare-all \ --share-net \ /usr/bin/sh bash-4.4$ ls -AF .Xauthority Documents/
构建 bubblewrap 文件系统时要考虑的最重要的规则可能是命令按照它们出现的顺序执行。 来自上面的 MuPDF 示例
- 创建一个 tmpfs 系统,然后绑定挂载
.Xauthority
文件和 Documents 目录
--tmpfs $HOME \ --ro-bind $HOME/.Xauthority $HOME/.Xauthority \ --ro-bind $HOME/Documents $HOME/Documents \
bash-4.4$ ls -a . .. .Xauthority Desktop
- 在绑定挂载
.Xauthority
之后创建了一个 tmpfs 文件系统并覆盖它,因此只有 Documents 目录在沙盒中可见
--ro-bind $HOME/.Xauthority $HOME/.Xauthority \ --tmpfs $HOME \ --ro-bind $HOME/Desktop $HOME/Desktop \
bash-4.4$ ls -a . .. Desktop
p7zip
尚未针对 已知漏洞 打补丁的应用程序是 bubblewrap 的首选
- 将主机
/usr/bin/7za
可执行文件路径以只读方式绑定到沙盒 - 在沙盒中创建从系统
/usr/lib
目录到/lib64
的符号链接 - 使用 tmpfs 覆盖将沙盒化的
/usr/lib/modules
和/usr/lib/systemd
内容列入黑名单 - 在沙盒中的
/dev
挂载一个新的 devtmpfs 文件系统 - 将主机
/sandbox
目录以读写方式绑定到沙盒中的/sandbox
目录- 从 shell 包装器调用时,7za 将仅在主机
/sandbox
目录和/或其子目录中运行
- 从 shell 包装器调用时,7za 将仅在主机
- 为应用程序及其进程创建新的 cgroup/IPC/网络/PID/UTS 命名空间
- 如果内核不支持非特权用户命名空间,则跳过其创建并继续
- 创建新的网络命名空间会阻止沙盒获取网络访问权限
- 向沙盒添加自定义或任意 主机名,例如
p7zip
- 取消设置
XAUTHORITY
环境变量 以隐藏 X11 连接 cookie 的位置- 7za 不需要连接到 X11 显示服务器即可正常运行
- 启动新的终端会话以防止键盘输入逃逸沙盒
#!/bin/sh #~/bwrap/pz7ip.sh (exec bwrap \ --ro-bind /usr/bin/7za /usr/bin/7za \ --symlink usr/lib /lib64 \ --tmpfs /usr/lib/modules \ --tmpfs /usr/lib/systemd \ --dev /dev \ --bind /sandbox /sandbox \ --unshare-all \ --hostname p7zip \ --unsetenv XAUTHORITY \ --new-session \ /usr/bin/7za "$@")
bwrap \ --ro-bind /usr/bin/7za /usr/bin/7za \ --ro-bind /usr/bin/ls /usr/bin/ls \ --ro-bind /usr/bin/sh /usr/bin/sh \ --symlink usr/lib /lib64 \ --tmpfs /usr/lib/modules \ --tmpfs /usr/lib/systemd \ --dev /dev \ --bind /sandbox /sandbox \ --unshare-all \ --hostname p7zip \ --unsetenv XAUTHORITY \ --new-session \ /usr/bin/sh bash: no job control in this shell bash-4.4$ ls -AF dev/ lib64@ usr/ bash-4.4$ ls -l /usr/lib/modules total 0 bash-4.4$ ls -l /usr/lib/systemd total 0 bash-4.4$ ls -AF /dev console full null ptmx@ pts/ random shm/ stderr@ stdin@ stdout@ tty urandom zero bash-4.4$ ls -A /usr/bin 7za ls sh
Firefox
具有较大攻击面的面向网络的应用程序也是 bubblewrap 的理想候选者
- 沙盒中包含 Transmission,用于通过 magnet 和 torrent 链接启动
- 示例包装器支持在 GNOME (Wayland) 下的音频 (PulseAudio) 和打印 (CUPS/Avahi)
~/.config/transmission/settings.json
中的路径应反映--setenv HOME
变量
- 使用完整路径是为了允许在不支持变量扩展的环境中进行键盘绑定。
- 包含 WebRenderer 和硬件(加速)合成支持
bwrap \ --symlink usr/lib /lib \ --symlink usr/lib64 /lib64 \ --symlink usr/bin /bin \ --symlink usr/bin /sbin \ --ro-bind /usr/lib /usr/lib \ --ro-bind /usr/lib64 /usr/lib64 \ --ro-bind /usr/bin /usr/bin \ --ro-bind /usr/lib/firefox /usr/lib/firefox \ --ro-bind /usr/share/applications /usr/share/applications \ --ro-bind /usr/share/gtk-3.0 /usr/share/gtk-3.0 \ --ro-bind /usr/share/fontconfig /usr/share/fontconfig \ --ro-bind /usr/share/icu /usr/share/icu \ --ro-bind /usr/share/drirc.d /usr/share/drirc.d \ --ro-bind /usr/share/fonts /usr/share/fonts \ --ro-bind /usr/share/glib-2.0 /usr/share/glib-2.0 \ --ro-bind /usr/share/glvnd /usr/share/glvnd \ --ro-bind /usr/share/icons /usr/share/icons \ --ro-bind /usr/share/libdrm /usr/share/libdrm \ --ro-bind /usr/share/mime /usr/share/mime \ --ro-bind /usr/share/X11/xkb /usr/share/X11/xkb \ --ro-bind /usr/share/icons /usr/share/icons \ --ro-bind /usr/share/mime /usr/share/mime \ --ro-bind /etc/fonts /etc/fonts \ --ro-bind /etc/resolv.conf /etc/resolv.conf \ --ro-bind /usr/share/ca-certificates /usr/share/ca-certificates \ --ro-bind /etc/ssl /etc/ssl \ --ro-bind /etc/ca-certificates /etc/ca-certificates \ --dir "$XDG_RUNTIME_DIR" \ --ro-bind "$XDG_RUNTIME_DIR/pulse" "$XDG_RUNTIME_DIR/pulse" \ --ro-bind "$XDG_RUNTIME_DIR/wayland-1" "$XDG_RUNTIME_DIR/wayland-1" \ --dev /dev \ --dev-bind /dev/dri /dev/dri \ --ro-bind /sys/dev/char /sys/dev/char \ --ro-bind /sys/devices/pci0000:00 /sys/devices/pci0000:00 \ --proc /proc \ --tmpfs /tmp \ --bind /home/example/.mozilla /home/example/.mozilla \ --bind /home/example/.config/transmission /home/example/.config/transmission \ --bind /home/example/Downloads /home/example/Downloads \ --setenv HOME /home/example \ --setenv GTK_THEME Adwaita:dark \ --setenv MOZ_ENABLE_WAYLAND 1 \ --setenv PATH /usr/bin \ --hostname RESTRICTED \ --unshare-all \ --share-net \ --die-with-parent \ --new-session \ /usr/bin/firefox
增强隐私
- 可以通过删除特定条目来进一步限制
- 删除以下条目以删除音频支持
--ro-bind "$XDG_RUNTIME_DIR/pulse" "$XDG_RUNTIME_DIR/pulse" \
/sandbox
表示用户定义的任意位置,用于保存所需的配置文件信息- 这允许使用通过脚本/cron 任务或手动复制到
/sandbox
中的 清理后的配置文件,例如
- 这允许使用通过脚本/cron 任务或手动复制到
$ cp -pR ~/.mozilla /sandbox/
该位置可以是网络共享、USB 挂载点或本地文件系统或 ramfs/tmpfs 位置
- 设置
/home/r
以模糊实际的/home/example
- 设置新的用户 ID 和组 ID 值
/etc/passwd
和 /etc/groups
中列出的现有值冲突。bwrap \ .... --bind /sandbox/.mozilla /home/r/.mozilla \ --bind /sandbox/Downloads /home/r/Downloads \ ... --setenv HOME /home/r \ ... --uid 200 --gid 400 \ ... /usr/bin/firefox --no-remote --private-window
Chromium
一个简单的 chromium 沙盒,在 wayland 上并使用 pipewire
bwrap \ --symlink usr/lib /lib \ --symlink usr/lib64 /lib64 \ --symlink usr/bin /bin \ --symlink usr/bin /sbin \ --ro-bind /usr/lib /usr/lib \ --ro-bind /usr/lib64 /usr/lib64 \ --ro-bind /usr/bin /usr/bin \ --ro-bind /etc /etc \ --ro-bind /usr/lib/chromium /usr/lib/chromium \ --ro-bind /usr/share /usr/share \ --dev /dev \ --dev-bind /dev/dri /dev/dri \ --proc /proc \ --ro-bind /sys/dev/char /sys/dev/char \ --ro-bind /sys/devices /sys/devices \ --ro-bind /run/dbus /run/dbus \ --dir "$XDG_RUNTIME_DIR" \ --ro-bind "$XDG_RUNTIME_DIR/wayland-1" "$XDG_RUNTIME_DIR/wayland-1" \ --ro-bind "$XDG_RUNTIME_DIR/pipewire-0" "$XDG_RUNTIME_DIR/pipewire-0" \ --ro-bind "$XDG_RUNTIME_DIR/pulse" "$XDG_RUNTIME_DIR/pulse" \ --tmpfs /tmp \ --dir $HOME/.cache \ --bind $HOME/.config/chromium $HOME/.config/chromium \ --bind $HOME/Downloads $HOME/Downloads \ /usr/bin/chromium --enable-features=UseOzonePlatform --ozone-platform=wayland
kernel.unprivileged_userns_clone
sysctl 设置为 0,您将无法使用 bubblewrap 沙盒化 chromium。 您可以将其设置为 1,但是,不建议这样做 FS#36969。一种替代解决方案是让 chromium 使用 bubblewrap 创建的命名空间。 这可以通过 zypakAUR 实现,flatpak 也使用它在额外的命名空间内运行基于 electron 的应用程序。 演示如何将 zypak 与 chromium/electron 一起使用的示例代码可以在 这里 找到
- PipeWire:
--ro-bind "$XDG_RUNTIME_DIR/pipewire-0" "$XDG_RUNTIME_DIR/pipewire-0" \
- 如果您不使用 pipewire,请随意删除此行
--bind $HOME/.config/chromium $HOME/.config/chromium \
将您的 chromium 配置目录以可读写方式挂载到沙盒中--bind $HOME/Downloads $HOME/Downloads \
将您的 ~/Downloads 目录以可读写方式挂载到沙盒中- 此示例可以进一步改进以获得更好的隔离。
Skype for Linux
以下示例提供这些功能
env -i
确保所有环境变量都未设置。- 网络与主机共享 (
--share-net
),/etc/resolv.conf
被绑定挂载。 - Xorg 访问:绑定
/tmp/.X11-unix/X0
套接字,设置$DISPLAY
。 - D-Bus:绑定
$XDG_RUNTIME_DIR/bus
套接字,设置$DBUS_SESSION_BUS_ADDRESS
。 - 音频:绑定 PulseAudio 套接字。
- 视频:dev-bind
/dev/video0
设备。
主机上要保留 Skype 配置文件的目录可以使用 $HOST_PROFILE_PATH
进行配置。
env -i bwrap \ --ro-bind /usr /usr \ --dir /home/r \ --dir /tmp \ --dir /var \ --dir "$XDG_RUNTIME_DIR" \ --proc /proc \ --dev /dev \ --symlink usr/lib /lib \ --symlink usr/lib64 /lib64 \ --symlink usr/bin /bin \ --symlink usr/sbin /sbin \ --symlink ../tmp /var/tmp \ --bind "$HOST_PROFILE_PATH" /home/r/.config/skypeforlinux \ --ro-bind /etc/resolv.conf /etc/resolv.conf \ --ro-bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X0 \ --ro-bind "$XDG_RUNTIME_DIR/bus" "$XDG_RUNTIME_DIR/bus" \ --ro-bind "$XDG_RUNTIME_DIR/pulse" "$XDG_RUNTIME_DIR/pulse" \ --dev-bind /dev/video0 /dev/video0 \ --chdir / \ --unshare-all \ --share-net \ --hostname RESTRICTED \ --die-with-parent \ --new-session \ --setenv PATH /usr/bin \ --setenv HOME /home/r \ --setenv XDG_RUNTIME_DIR "$XDG_RUNTIME_DIR" \ --setenv DISPLAY "$DISPLAY" \ --setenv DBUS_SESSION_BUS_ADDRESS "unix:path=$XDG_RUNTIME_DIR/bus" \ /usr/bin/skypeforlinux
Steam
一个简单的 Steam 沙盒
#!/usr/bin/bash set -e STEAM_HOME="$HOME/.local/share/steam_sandbox" RUN_USER="$XDG_RUNTIME_DIR" mkdir -p "$STEAM_HOME" _bind() { _bind_arg=$1 shift for _path in "$@"; do args+=("$_bind_arg" "$_path" "$_path") done } bind() { _bind --bind-try "$@" } robind() { _bind --ro-bind-try "$@" } devbind() { _bind --dev-bind-try "$@" } args=( --tmpfs /tmp --proc /proc --dev /dev --dir /etc --dir /var --dir "$RUN_USER" --bind "$STEAM_HOME" "$HOME" --dir "$HOME" --dir "$XDG_CONFIG_HOME" --dir "$XDG_CACHE_HOME" --dir "$XDG_DATA_HOME" --dir "$XDG_STATE_HOME" --symlink /usr/lib /lib --symlink /usr/lib /lib64 --symlink /usr/bin /bin --symlink /usr/bin /sbin --symlink /run /var/run --setenv XAUTHORITY "$XAUTHORITY" ) robind \ /usr \ /etc \ /opt \ /sys \ /var/empty \ /var/lib/alsa \ /var/lib/dbus \ "$RUN_USER/systemd/resolve" devbind \ /dev/dri \ /dev/nvidia* \ /dev/input \ /dev/uinput # steam bind \ "$XAUTHORITY" \ "$HOME/.local/bin/proton" \ "$HOME/.pki" \ "$HOME/.steam" \ "$HOME/.steampath" \ "$HOME/.steampid" \ "$HOME/Downloads" \ "$RUN_USER"/.mutter-X* \ "$RUN_USER"/ICE* \ "$RUN_USER"/dbus* \ "$RUN_USER"/gnome* \ "$RUN_USER"/pipewire* \ "$RUN_USER"/pulse* \ "$RUN_USER"/wayland* \ "$RUN_USER/at-spi" \ "$RUN_USER/bus" \ "$RUN_USER/dconf" \ "$RUN_USER/systemd" \ "$XDG_CACHE_HOME/mesa_shader_cache" \ "$XDG_CACHE_HOME/nv" \ "$XDG_CACHE_HOME/nvidia" \ "$XDG_CACHE_HOME/radv_builtin_shaders64" \ "$XDG_CONFIG_HOME/Epic" \ "$XDG_CONFIG_HOME/Loop_Hero" \ "$XDG_CONFIG_HOME/MangoHud" \ "$XDG_CONFIG_HOME/ModTheSpire" \ "$XDG_CONFIG_HOME/RogueLegacy" \ "$XDG_CONFIG_HOME/RogueLegacyStorageContainer" \ "$XDG_CONFIG_HOME/cef_user_data" \ "$XDG_CONFIG_HOME/proton" \ "$XDG_CONFIG_HOME/pulse" \ "$XDG_CONFIG_HOME/unity3d" \ "$XDG_DATA_HOME/3909/PapersPlease" \ "$XDG_DATA_HOME/Colossal Order" \ "$XDG_DATA_HOME/Dredmor" \ "$XDG_DATA_HOME/FasterThanLight" \ "$XDG_DATA_HOME/HotlineMiami" \ "$XDG_DATA_HOME/IntoTheBreach" \ "$XDG_DATA_HOME/Paradox Interactive" \ "$XDG_DATA_HOME/PillarsOfEternity" \ "$XDG_DATA_HOME/RogueLegacy" \ "$XDG_DATA_HOME/RogueLegacyStorageContainer" \ "$XDG_DATA_HOME/Steam" \ "$XDG_DATA_HOME/SuperHexagon" \ "$XDG_DATA_HOME/Terraria" \ "$XDG_DATA_HOME/applications" \ "$XDG_DATA_HOME/aspyr-media" \ "$XDG_DATA_HOME/bohemiainteractive" \ "$XDG_DATA_HOME/cdprojektred" \ "$XDG_DATA_HOME/feral-interactive" \ "$XDG_DATA_HOME/frictionalgames" \ "$XDG_DATA_HOME/icons" \ "$XDG_DATA_HOME/proton" \ "$XDG_DATA_HOME/vpltd" \ "$XDG_DATA_HOME/vulkan" \ "/var/lib/bluetooth" \ /run/systemd \ /tmp/.ICE-unix \ /tmp/.X11-unix exec bwrap "${args[@]}" /usr/lib/steam/steam "$@"
NPM, Node Version Manager (NVM), Maven Java
为了能够在项目根目录中运行 npm,您可以使用以下命令。
它与 Angular、Cypress 和 Maven Java 结合使用。 顶部包含 X11 和 wayland 是因为 Cypress 启动了一个基于 electron 的 GUI。
它允许完全文件访问从其运行的当前目录。 假设您在当前项目根目录中执行 npm install
,其中 npm 需要写入 node_modules
、package.json
等。 还允许访问全局 npm 安装目录和 nvm (npm -g install ...
)。 此外,带有 cypress 的 X11 也能够运行,甚至 wayland 应用程序。
bwrap_arguments=( # no zombies --die-with-parent # network required for dependencies --unshare-all --share-net # create environment for a properly running shell --tmpfs / --tmpfs /run --dir /tmp --dev /dev --proc /proc --ro-bind /bin /bin --ro-bind /sbin /sbin --ro-bind /usr /usr --ro-bind /etc /etc --ro-bind /lib /lib --ro-bind /lib64 /lib64 --ro-bind /sys /sys --ro-bind /var /var # systemd-resolve for dns --ro-bind /run/systemd/resolve /run/systemd/resolve # git is used by npm to init repos, config necessary for email username --ro-bind $XDG_CONFIG_HOME/git/config $XDG_CONFIG_HOME/git/config # zsh has to look everywhere cool --ro-bind $XDG_CONFIG_HOME/zsh/.zshrc $XDG_CONFIG_HOME/zsh/.zshrc --ro-bind $XDG_CONFIG_HOME/zsh/.zshenv $XDG_CONFIG_HOME/zsh/.zshenv --ro-bind $HOME/.zshenv $HOME/.zshenv # Maven --ro-bind /opt/maven /opt/maven --ro-bind $HOME/.m2 $HOME/.m2 # NPM --bind "$XDG_DATA_HOME/npm" "$XDG_DATA_HOME/npm" # cache is needed by many programs like npm, cypress, nvm, maven --bind "$XDG_CACHE_HOME" "$XDG_CACHE_HOME" # x11, needed for cypress --ro-bind "$XAUTHORITY" "$XAUTHORITY" # wayland, might be useful --ro-bind "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" # current dir is assumed to be project dir and full access is allowed --bind "$(pwd)" "$(pwd)" ) # run bwrap with the arguments specified above and with the command provided by the user: zsh, npm install, etc $ bwrap "${bwrap_arguments[@]}" "$@"