强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Bubblewrap 容器入门教程 / 第 2 章 - 安装与环境配置

第 2 章:安装与环境配置

本章详细介绍 Bubblewrap 在各主流 Linux 发行版上的安装方法、内核配置要求、命名空间支持检测以及常见问题排查。


2.1 包管理器安装

各发行版安装命令

发行版包名安装命令
Fedora / RHELbubblewrapsudo dnf install bubblewrap
Debian / Ubuntububblewrapsudo apt install bubblewrap
Arch Linuxbubblewrapsudo pacman -S bubblewrap
openSUSEbubblewrapsudo zypper install bubblewrap
Gentoosys-apps/bubblewrapsudo emerge sys-apps/bubblewrap
Alpinebubblewrapsudo apk add bubblewrap
Void Linuxbubblewrapsudo xbps-install -S bubblewrap
NixOSbubblewrapenvironment.systemPackages 中添加

验证安装

# 检查版本
bwrap --version
# bubblewrap 0.9.0

# 查看帮助
bwrap --help

2.2 从源码编译安装

当包管理器提供的版本过旧,或需要最新特性时,可以从源码编译。

依赖项

依赖用途安装(Debian/Ubuntu)
libcapLinux 权能操作libcap-dev
libseccompseccomp 系统调用过滤libseccomp-dev(可选)
meson构建系统meson
ninja构建后端ninja-build
docbook-xsl文档生成docbook-xsl(可选)
gcc / clangC 编译器gccclang

编译步骤

# 1. 安装构建依赖(Debian/Ubuntu)
sudo apt install -y meson ninja-build libcap-dev libseccomp-dev docbook-xsl xsltproc

# 2. 克隆仓库
git clone https://github.com/containers/bubblewrap.git
cd bubblewrap

# 3. 查看可用的版本标签
git tag -l | sort -V | tail -5
# v0.8.0
# v0.9.0
# v0.10.0

# 4. 切换到稳定版本(可选)
git checkout v0.10.0

# 5. 配置构建
meson setup builddir \
  -Drequire-userns=true \
  -Dman=enabled \
  -Ddocs=disabled

# 6. 编译
ninja -C builddir

# 7. 测试(可选)
ninja -C builddir test

# 8. 安装
sudo ninja -C builddir install

# 9. 验证
which bwrap
# /usr/local/bin/bwrap

Meson 构建选项

选项默认值说明
require-usernsfalse是否要求 user namespace 支持
manauto是否生成 man page
docsdisabled是否生成文档
selinuxauto是否启用 SELinux 支持

Fedora 特殊编译选项

Fedora 默认使用 setuid 模式安装 bwrap(需要 suid 位),以兼容不支持 user namespace 的场景:

# Fedora 默认编译(带 setuid 支持)
meson setup builddir -Drequire-userns=false

# 安装后需要设置 setuid
sudo chmod u+s /usr/bin/bwrap

2.3 内核要求

最低内核版本

功能最低内核版本说明
基本运行2.6.x(setuid 模式)不推荐,安全性差
User Namespace3.8非特权模式的基本要求
Mount Namespace2.4.19文件系统隔离
PID Namespace2.6.19进程隔离
Network Namespace2.6.29网络隔离
UTS Namespace2.6.19主机名隔离
Cgroup Namespace4.6cgroup 视图隔离
seccomp-BPF3.5系统调用过滤
推荐内核>= 5.x完整功能支持

检查当前内核版本

uname -r
# 6.1.0-23-amd64

# 查看内核编译配置中命名空间的支持情况
cat /proc/config.gz | gunzip | grep NAMESPACE
# 或
grep NAMESPACE /boot/config-$(uname -r)

2.4 命名空间支持检测

检测 User Namespace 支持

# 方法 1: 检查内核配置
grep CONFIG_USER_NS /boot/config-$(uname -r)
# CONFIG_USER_NS=y

# 方法 2: 直接测试
unshare --user --map-root-user echo "User namespace works"
# User namespace works

# 方法 3: 查看系统参数
cat /proc/sys/kernel/unprivileged_userns_clone
# 1 (表示允许非特权用户创建 user namespace)

检测所有命名空间支持

#!/bin/bash
# check-ns-support.sh - 检测命名空间支持

declare -A NAMESPACES=(
    [user]="unshare --user echo OK"
    [mount]="unshare --mount echo OK"
    [pid]="unshare --pid --fork echo OK"
    [net]="unshare --net echo OK"
    [uts]="unshare --uts echo OK"
    [cgroup]="unshare --cgroup echo OK"
    [ipc]="unshare --ipc echo OK"
)

echo "命名空间支持检测:"
echo "=================="

for ns in "${!NAMESPACES[@]}"; do
    if eval "${NAMESPACES[$ns]}" &>/dev/null; then
        printf "  %-10s: ✅ 支持\n" "$ns"
    else
        printf "  %-10s: ❌ 不支持\n" "$ns"
    fi
done

运行输出:

命名空间支持检测:
==================
  user      : ✅ 支持
  mount     : ✅ 支持
  pid       : ✅ 支持
  net       : ✅ 支持
  uts       : ✅ 支持
  cgroup    : ✅ 支持
  ipc       : ✅ 支持

2.5 权限配置

模式对比

Bubblewrap 有两种运行模式:

模式原理安全性要求
User Namespace 模式利用 user namespace 创建隔离较高(无特权提升)内核支持 unprivileged userns
Setuid 模式bwrap 以 root 身份运行较低(存在提权风险)chmod u+s /usr/bin/bwrap

启用 Unprivileged User Namespace

某些发行版默认禁用了非特权 user namespace,需要手动启用:

Debian / Ubuntu

# 检查当前设置
cat /proc/sys/kernel/unprivileged_userns_clone
# 0 表示禁用

# 临时启用
sudo sysctl kernel.unprivileged_userns_clone=1

# 永久启用
echo "kernel.unprivileged_userns_clone=1" | sudo tee /etc/sysctl.d/00-local-userns.conf
sudo sysctl --system

RHEL / CentOS / Fedora

# 检查当前设置
cat /proc/sys/user/max_user_namespaces
# 0 表示禁用

# 临时启用
sudo sysctl user.max_user_namespaces=28633

# 永久启用
echo "user.max_user_namespaces=28633" | sudo tee /etc/sysctl.d/userns.conf
sudo sysctl --system

Arch Linux

# Arch 默认启用 user namespace,无需额外配置
# 如果使用 hardened 内核,可能需要:
sudo sysctl kernel.unprivileged_userns_clone=1

使用 sysctl 安全模块限制

# 通过 sysctl 配置文件
cat /etc/sysctl.d/99-bubblewrap.conf
# 允许非特权 user namespace
kernel.unprivileged_userns_clone = 1
# 设置最大 user namespace 数量
user.max_user_namespaces = 28633

Setuid 模式配置

当 user namespace 不可用时,需要使用 setuid 模式:

# 安装 setuid 版本(通常由发行版打包完成)
sudo chmod u+s /usr/bin/bwrap

# 验证
ls -la /usr/bin/bwrap
# -rwsr-xr-x 1 root root 123456 ... /usr/bin/bwrap

⚠️ 安全警告:setuid 模式意味着 bwrap 以 root 权限运行,如果 bwrap 存在漏洞,可能导致本地提权。强烈推荐使用 user namespace 模式。


2.6 发行版特定注意事项

Fedora

# Fedora 默认使用 setuid bwrap,因为其 user namespace 策略较保守
# 检查 bwrap 是否为 setuid
stat -c '%a %U' /usr/bin/bwrap
# 4755 root

# 可选:切换到 user namespace 模式
# 1. 取消 setuid
sudo chmod u-s /usr/bin/bwrap
# 2. 启用 user namespace
sudo sysctl user.max_user_namespaces=28633
# 3. 测试
bwrap --ro-bind / / --unshare-user echo "It works"

Ubuntu(AppArmor 冲突)

Ubuntu 使用 AppArmor 对 bwrap 进行限制,可能会导致某些操作失败:

# 查看 AppArmor 对 bwrap 的策略
sudo aa-status | grep bwrap

# 如果遇到 AppArmor 拒绝(denied),可以临时切换到 complain 模式
sudo aa-complain /usr/bin/bwrap

# 或者调整 AppArmor 策略
cat /etc/apparmor.d/bwrap

Debian

# Debian 12+ 默认启用 user namespace
# 如遇到权限问题,检查:
cat /proc/sys/kernel/unprivileged_userns_clone
# 应为 1

NixOS

# configuration.nix 中添加
{ pkgs, ... }:
{
  # 启用 user namespace
  security.unprivilegedUsernsClone = true;

  # 安装 bubblewrap
  environment.systemPackages = [ pkgs.bubblewrap ];

  # NixOS 特殊:需要配置 bwrap wrapper
  programs.bwrap = {
    enable = true;
  };
}

2.7 安装验证测试

安装完成后,运行以下测试确认一切正常:

基本功能测试

#!/bin/bash
# test-bwrap-install.sh

echo "=== Bubblewrap 安装验证 ==="
echo ""

# 1. 版本检查
echo "1. 版本信息:"
bwrap --version
echo ""

# 2. 基本沙箱测试
echo "2. 基本沙箱测试:"
if bwrap --ro-bind / / --unshare-user --unshare-pid --fork echo "Sandbox OK" 2>/dev/null; then
    echo "   ✅ 基本沙箱运行正常"
else
    echo "   ❌ 基本沙箱运行失败"
fi

# 3. 文件系统隔离测试
echo "3. 文件系统隔离测试:"
SANDBOX_HOSTNAME=$(bwrap --ro-bind / / --unshare-uts -- hostname 2>/dev/null)
HOST_HOSTNAME=$(hostname)
if [ "$SANDBOX_HOSTNAME" = "$HOST_HOSTNAME" ]; then
    # UTS namespace 在只读绑定下可能共享主机名,这是正常的
    echo "   ✅ UTS 命名空间可用"
else
    echo "   ✅ UTS 命名空间已隔离: 沙箱=$SANDBOX_HOSTNAME, 宿主=$HOST_HOSTNAME"
fi

# 4. 隔离完整性测试
echo "4. 隔离完整性测试:"
if bwrap --ro-bind / / --unshare-all --proc /proc --dev /dev \
   bash -c 'echo "PID namespace: $(echo $$)"' 2>/dev/null; then
    echo "   ✅ 完整隔离测试通过"
else
    echo "   ⚠️ 部分隔离功能可能不可用"
fi

# 5. tmpfs 测试
echo "5. tmpfs 测试:"
if bwrap --ro-bind / / --tmpfs /tmp bash -c \
   'echo "test" > /tmp/sandbox_test && cat /tmp/sandbox_test && rm /tmp/sandbox_test' 2>/dev/null; then
    echo "   ✅ tmpfs 可写"
else
    echo "   ❌ tmpfs 测试失败"
fi

echo ""
echo "=== 验证完成 ==="

预期输出

=== Bubblewrap 安装验证 ===

1. 版本信息:
bubblewrap 0.9.0

2. 基本沙箱测试:
   ✅ 基本沙箱运行正常

3. 文件系统隔离测试:
   ✅ UTS 命名空间可用

4. 隔离完整性测试:
   ✅ 完整隔离测试通过

5. tmpfs 测试:
   ✅ tmpfs 可写

=== 验证完成 ===

2.8 常见问题排查

问题 1:Operation not permitted

bwrap: Creating new namespace failed: Operation not permitted

原因:user namespace 被禁用或不支持。

解决

# 检查并启用 user namespace
sudo sysctl kernel.unprivileged_userns_clone=1

# 或检查是否为 setuid 模式
ls -la /usr/bin/bwrap
# 如果没有 setuid 位且 user namespace 被禁用:
sudo chmod u+s /usr/bin/bwrap

问题 2:No space left on device

bwrap: Can't mkdir /tmp/sandbox: No space left on device

原因:tmpfs 空间不足。

解决

# 使用 --tmpfs 时指定大小
bwrap --tmpfs /tmp --size 512 ...

问题 3:AppArmor DENIED

kernel: audit: type=1400 audit(...): apparmor="DENIED" operation="..."

解决

# 查看 AppArmor 日志
sudo journalctl -k | grep apparmor | grep bwrap

# 切换 AppArmor 到 complain 模式
sudo aa-complain /usr/bin/bwrap

问题 4:mount failed

bwrap: Can't mount proc on /newroot/proc: Permission denied

解决

# 确保使用 --proc 参数而非手动 mount
bwrap --ro-bind / / --proc /proc ...

# 或检查是否存在 AppArmor/SELinux 限制
getenforce  # SELinux
sudo aa-status  # AppArmor

2.9 注意事项

⚠️ 重要提醒

  1. 不要同时使用 setuid 和 user namespace 模式:这可能产生安全风险。选择一种模式并保持一致。

  2. 发行版策略差异:不同发行版对 user namespace 的默认策略不同。Fedora 倾向于 setuid,Ubuntu 倾向于 user namespace + AppArmor。

  3. 更新内核:如果遇到命名空间相关的奇怪错误,优先考虑升级内核。

  4. Docker 中的 bwrap:在 Docker 容器内使用 bwrap 需要特殊配置(详见第 9 章)。


2.10 扩展阅读


上一章:第 1 章 - Bubblewrap 概述 | 下一章:第 3 章 - 基本用法