Bubblewrap

来自 ArchWiki

Bubblewrap 是一个轻量级的沙盒应用,被 Flatpak 和其他容器工具使用。它安装体积小,资源需求极低。虽然软件包名为 bubblewrap,但实际的命令行界面是 bwrap(1)。值得注意的功能包括支持 cgroup/IPC/mount/network/PID/user/UTS 命名空间seccomp 过滤。请注意,bubblewrap 会丢弃沙盒内的所有 capabilities,并且子任务无法获得比其父任务更高的权限。值得注意的功能排除包括缺乏对黑名单/白名单文件路径的显式支持。

警告: Bubblewrap 是一个提供沙盒技术的工具,如命名空间和 seccomp 过滤器。默认情况下,它不提供完整的沙盒,以隔离诸如 X11 窗口系统之类的弱点(参见 #沙盒化 X11)。运行不受信任的代码永远是不安全的,沙盒化无法改变这一点。

安装

安装 bubblewrapbubblewrap-gitAUR

注意

配置

Bubblewrap 可以直接从命令行调用,也可以在 shell 脚本 中作为 复杂包装器 的一部分调用。与 Firejail 等应用程序不同,后者会自动将沙盒内的 /var/etc 设置为只读,Bubblewrap 没有做这样的操作假设。用户需要根据要沙盒化的应用程序确定要传递哪些配置选项。当使用 setuid 权限运行时,Bubblewrap 不会自动创建用户命名空间,并且可以适应典型的环境变量,包括 $HOME$USER

强烈建议您下载 strace,以查看您尝试沙盒化的程序需要访问哪些文件。

bubblewrap 的配置管理器

可以使用配置管理器而不是手动设置参数,配置管理器可以从更简单的配置中自动配置 bubblewrap。

  • Bubblejail — 基于 Bubblewrap 的沙盒,具有基于资源的权限模型(提供 GUI 来调整权限)。
https://github.com/igo95862/bubblejail || bubblejailAUR
  • portableAUR:易于使用的沙盒框架,包括 D-Bus 代理过滤、数据隔离、访问控制等。

使用示例

请参阅 /Examples 以获取有关如何使用 bubblewrap 的示例。或者,有许多项目演示了如何将 bubblewrap 用于常见应用程序

无操作

无操作的 bubblewrap 调用如下所示

$ bwrap --dev-bind / / bash

这将产生一个 Bash 进程,在大多数情况下,它的行为应该与在沙盒外完全相同。如果沙盒程序行为异常,您可能需要从上面的无操作调用开始,并逐步改进到更安全的配置。

注意: 如果所有者或组不是当前用户,此操作会将所有者和组修改为 nobody,这意味着运行 sudo 之类的程序将无法正常工作。

Bash

创建一个简单的 Bash 沙盒

  • 确定可用的内核命名空间
$ ls /proc/self/ns
cgroup  ipc  mnt  net  pid  user uts
注意: user 的存在表明内核已通过 CONFIG_USER_NS=y 公开了对用户命名空间的支持
  • 将整个主机 / 目录作为只读绑定到沙盒中的 /
  • 创建一个新的用户命名空间,并将 用户 ID 设置为 256,将 组 ID 设置为 512
$ bwrap --ro-bind / / --unshare-user --uid 256 --gid 512 bash
bash-4.4$ id
uid=256 gid=512 groups=512,65534(nobody)
bash-4.4$ ls -l /usr/bin/bash
-rwxr-xr-x 1 nobody nobody 811752 2017-01-01 04:20 /usr/bin/bash

桌面条目

桌面条目 中利用 Bubblewrap

  • 将整个主机 / 目录作为读写绑定到沙盒中的 /
  • /var/etc 目录在沙盒中重新绑定为只读
  • 在沙盒中的 /dev 上挂载一个新的 devtmpfs 文件系统
  • 在沙盒化的 /run 目录上创建一个 tmpfs 文件系统
  • 通过创建新的网络命名空间来禁用网络访问
[Desktop Entry]
Name=nano Editor
Exec=bwrap --bind / / --dev /dev --tmpfs /run --unshare-net  st -e nano -o . %f
Type=Application
MimeType=text/plain;
注意: 需要 --dev /dev 才能写入 /dev/pty
  • 包含 mupdf.sh shell 包装器的 MuPDF 桌面条目示例
[Desktop Entry]
Name=MuPDF
Exec=mupdf.sh %f
Icon=application-pdf.svg
Type=Application
MimeType=application/pdf;application/x-pdf;
注意: 确保 mupdf.sh 位于您的可执行 PATH 中,例如 PATH=$PATH:$HOME/bwrap

文件系统隔离

警告: bubblewrap 用户有责任定期更新文件系统树。

为了进一步隐藏文件系统的内容(例如 /var/usr/bin/usr/lib 中的内容)并沙盒化软件安装,可以使 pacman 将 Arch 软件包安装到隔离的文件系统树中。

为了使用 pacman 将软件安装到文件系统树中,您需要安装 fakerootfakechroot

假设您想使用 pacman 将 xterm 软件包安装到隔离的文件系统树中。您应该像这样准备您的树

$ MYPACKAGE=xterm
$ mkdir -p ~/sandboxes/${MYPACKAGE}/files/var/lib/pacman
$ mkdir -p ~/sandboxes/${MYPACKAGE}/files/etc
$ cp /etc/pacman.conf ~/sandboxes/${MYPACKAGE}/files/etc/pacman.conf

您可能想要编辑 ~/sandboxes/${MYPACKAGE}/files/etc/pacman.conf 并调整使用的 pacman 配置

  • 删除任何不需要的自定义存储库以及仅主机系统需要的 IgnorePkgIgnoreGroupNoUpgradeNoExtract 设置。
  • 您可能需要删除 CheckSpace 选项,这样 pacman 就不会抱怨找不到根文件系统来检查磁盘空间而报错。

然后将 base 组以及所需的 fakeroot 安装到隔离的文件系统树中

$ fakechroot fakeroot pacman -Syu \
    --root ~/sandboxes/${MYPACKAGE}/files \
    --dbpath ~/sandboxes/${MYPACKAGE}/files/var/lib/pacman \
    --config ~/sandboxes/${MYPACKAGE}/files/etc/pacman.conf \
    base fakeroot

由于您将重复使用相同的选项调用 bubblewrap,因此创建一个别名

$ alias bw-install='bwrap                        \
     --bind ~/sandboxes/${MYPACKAGE}/files/ /    \
     --ro-bind /etc/resolv.conf /etc/resolv.conf \
     --tmpfs /tmp                                \
     --proc /proc                                \
     --dev /dev                                  \
     --chdir /                                   '

您将需要通过 编辑 ~/sandboxes/${MYPACKAGE}/files/etc/locale.gen 并运行以下命令来设置 locale

$ bw-install locale-gen

然后设置 pacman 的密钥环

$ bw-install fakeroot pacman-key --init
$ bw-install fakeroot pacman-key --populate

现在您可以安装所需的 xterm 软件包。

$ bw-install fakeroot pacman -S ${MYPACKAGE}

如果 pacman 命令在此处失败,请尝试再次运行用于填充密钥环的命令。

恭喜。您现在有了一个包含 xterm 的隔离文件系统树。您可以再次使用 bw-install 来升级您的文件系统树。

您现在可以使用 bubblewrap 运行您的软件。在这种情况下,command 应该是 xterm

$ bwrap                                          \
     --ro-bind ~/sandboxes/${MYPACKAGE}/files/ / \
     --ro-bind /etc/resolv.conf /etc/resolv.conf \
     --tmpfs /tmp                                \
     --proc /proc                                \
     --dev /dev                                  \
     --chdir /                                   \
     command

请注意,某些文件可以在软件包之间共享。您可以硬链接到现有父文件系统树的所有文件,以便在新树中重用它们

$ cp -al ~/sandboxes/${MYPARENTPACKAGE} ~/sandboxes/${MYPACKAGE}

然后像往常一样继续安装,从 bw-install fakechroot fakeroot pacman ... 调用 pacman。

故障排除

使用 X11

将主机 X11 套接字绑定挂载到备用 X11 套接字可能不起作用

--bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X8 --setenv DISPLAY :8

一种解决方法是将主机 X11 套接字绑定挂载到沙盒内的同一套接字

--bind /tmp/.X11-unix/X0 /tmp/.X11-unix/X0 --setenv DISPLAY :0

沙盒化 X11

虽然 bwrap 为沙盒应用程序提供了一些非常好的隔离,但只要可以访问 X11 套接字,就很容易逃脱。X11 不包含应用程序之间的隔离,并且完全不安全。唯一的解决方案是切换到 Wayland 合成器,并且从沙盒中无法访问 Xserver。

但是,有一些使用 xpraxephyr 在新的 X11 环境中运行的解决方法。这也可以与 bwrap 一起使用。

要测试 X11 隔离,请运行 xinput test id(键盘 id 可以使用 xinput list 找到)。在没有额外的 X11 隔离的情况下运行时,这将表明任何具有 X11 访问权限的应用程序都可以捕获任何其他应用程序的键盘输入,这基本上是键盘记录器会做的事情。

消除 X11 弱点的最佳解决方案是切换到 Wayland 合成器。

使用 portal

本文或章节候选合并至 XDG Desktop Portal

注意: 有一个专门的页面。(在 Talk:Bubblewrap 中讨论)
警告: 这利用了一些解决方法,这些解决方法“欺骗” xdg-desktop-poral 认为沙盒程序是 Flatpak。提醒一下,运行不受信任的代码永远是不安全的,即使在沙盒中,即使使用 Portal 也是如此

通过一些解决方法,可以使用 XDG Desktop Portal 对程序进行沙盒化。主要优点是文件系统 portal,因为它使得可以在不给程序访问主目录的情况下仍然能够访问文件。出于安全原因,但是,使用 portal 需要欺骗 xdg-desktop-portal 认为沙盒程序是 Flatpak 的一部分。这可以通过向沙盒的根文件系统添加 .flatpak-info 文件来完成。

此外,还需要运行 xdg-dbus-proxy 以更精细地控制可以访问哪些 portal。这应该在沙盒环境中运行,因此也需要 .flatpak-info 文件。至少,代理需要具有与 org.freedesktop.portal.Flatpak 通信的访问权限。可以在 Flatpak 文档 中找到其他 portal。

一个常见的用例是允许限制程序对主目录的 100% 访问权限,而是仅授予对用户在文件选择器中选择的文件和文件夹的访问权限。为了实现这一点,可以使用以下参数启动 xdg-dbus-proxy

--talk=org.freedesktop.portal.Documents
--talk=org.freedesktop.portal.Flatpak
--talk=org.freedesktop.portal.Desktop
--talk=org.freedesktop.portal.FileChooser

完整示例

APP_NAME=app.application.Name
APP_FOLDER="$XDG_RUNTIME_DIR/app/$APP_NAME"
mkdir -p "$APP_FOLDER"
set_up_dbus_proxy() {
 bwrap \
   --new-session \
   --symlink /usr/lib64 /lib64 \
   --ro-bind /usr/lib /usr/lib \
   --ro-bind /usr/lib64 /usr/lib64 \
   --ro-bind /usr/bin /usr/bin \
   --bind "$XDG_RUNTIME_DIR" "$XDG_RUNTIME_DIR" \
   --ro-bind-data 3 "/.flatpak-info" \
   --die-with-parent \
   -- \
   env -i xdg-dbus-proxy \
   "$DBUS_SESSION_BUS_ADDRESS" \
   "$APP_FOLDER/bus" \
   --filter \
   --log \
   --talk=org.freedesktop.portal.Flatpak \
   --call="org.freedesktop.portal.Desktop=org.freedesktop.portal.Settings.Read@/org/freedesktop/portal/desktop" \
   --broadcast="org.freedesktop.portal.Desktop=org.freedesktop.portal.Settings.SettingChanged@/org/freedesktop/portal/desktop" 3<<EOF
[Application]
name=$APP_NAME
EOF
}

set_up_dbus_proxy &
sleep 0.1

bwrap \
  ...
  --ro-bind-data 3 /.flatpak-info \
  ...
  3<<EOF
[Application]
name=$APP_NAME
EOF

从包装的应用打开 URL

当包装的 IRC 或电子邮件客户端尝试打开 URL 时,它通常会尝试启动浏览器进程,该进程将在与包装的应用程序相同的沙盒中运行。对于包装良好的应用程序,这可能无法正常工作。Firejail 使用的方法是 也授予包装的应用程序浏览器的所有权限,但这暗示了大量的权限蔓延。

解决此问题的更好方法是将打开的 URL 传递到沙盒外部。这可以使用 snapd-xdg-open 完成,如下所示

  1. 安装 snapd-xdg-open-gitAUR
  2. 在您的 bwrap 命令行中,添加
$ bwrap ... \
  --ro-bind /run/user/$UID/bus /run/user/$UID/bus \
  --ro-bind /usr/lib/snapd-xdg-open/xdg-open /usr/bin/xdg-open \
  --ro-bind /usr/lib/snapd-xdg-open/xdg-open /usr/bin/chromium \
  ...

/usr/bin/chromium 绑定仅对于不使用 XDG 约定的程序是必需的,例如 Mozilla Thunderbird。

新会话

TIOCSTI 存在安全问题 (CVE-2017-5226),这允许沙盒逃逸。为了防止这种情况,bubblewrap 引入了新的选项“--new-session”,它调用 setsid()。但是,这会导致一些行为问题,在某些情况下很难处理。例如,它使 shell 作业控制对于 bwrap 命令不起作用。

如果可能,建议使用此选项,但如果不能,开发人员建议以其他方式消除此问题,例如使用 SECCOMP,这正是 flatpak 所做的:https://github.com/flatpak/flatpak/commit/902fb713990a8f968ea4350c7c2a27ff46f1a6c4

嵌套命名空间

某些应用程序(例如 Chromium)已经使用 suid 辅助文件实现了自己的沙盒环境。当它们在 bubblewrap 容器内执行时,此机制将被阻止。

一种解决方案是让应用程序使用由 bubblewrap 创建的命名空间。这可以通过 zypakAUR 实现,flatpak 也使用 zypak 在额外的命名空间内运行基于 electron 的应用程序。可以在 [1] 找到演示如何将 zypak 与 Chromium/Electron 一起使用的示例代码。

无声音输出

本文或章节需要语言、wiki 语法或风格方面的改进。请参阅 Help:Style 以供参考。

原因: 诸如 “某些程序” 之类的短语没有用处。请参阅 Help:Style#语言风格。(在 Talk:Bubblewrap 中讨论)

对于使用 ALSA 声音系统的某些程序,请添加

--dev-bind /dev/snd /dev/snd

以播放声音。

参见