11.4 Linux Jail
准备工作
本文将所有 jail 绑定到虚拟网络接口 lo1,使其相当于位于 FreeBSD 系统下的一个局域网,其中 FreeBSD 主机充当该局域网的网关。
所有 jail 的网络流量必须通过网络接口 lo1,因此需要启用网络转发,本节使用 pf 防火墙实现此功能。
注意
配置 pf 防火墙是实现网络访问的关键步骤。
准备网络接口
# sysrc cloned_interfaces+="lo1" # 添加一个克隆网络接口 lo1
# service netif cloneup # 启用克隆网络接口准备 pf 防火墙
这里提供两种方式进行配置,请按需选用。
方案一
编辑 /etc/pf.conf,加入:
table <jails> persist
nat pass on em0 inet from <jails> to any -> em0在 pf 防火墙中建立名为 jails 的表,并指定 persist 标志,使防火墙始终保留该表(即使没有相关规则引用它)。
“表”是 pf 防火墙的一种命名结构,可保存地址和网络的集合。jails 表中的地址可以通过 NAT 访问网络。
可以使用 pfctl 对 jails 表进行添加或删除操作,以控制网络访问。例如:
pfctl -t jails -T add 192.168.5.1将192.168.5.1加入 jails 表使其可以访问网络pfctl -t jails -T delete 192.168.5.1将192.168.5.1移出 jails 表使其无法访问网络。
这种方法的特点是手动管理较为繁琐,但具有较高灵活性。
方案二
直接在 /etc/pf.conf 中写下规则:
此方法允许 192.168.5.1 访问网络,其特点是规则固化在配置文件中,对于没有特殊需求的场景比较方便。
启用 pf 防火墙
警告
无论你想不想使用防火墙,不这样设置你在 Jail 中都没有网络。
加载必要的 Linux 兼容层内核模块
这种方式可以自动加载 Linux 兼容层所需的各个内核模块。
准备目录
创建 debian Jail
下载基本系统
这里以 Debian 12(bookworm) 为例:
构建 Ubuntu/Debian 基本系统:
示例输出,如下:
注意
输出末尾可能出现错误提示信息,可忽略。
创建 debian Jail 实例
现在用 Debian 12 基本系统创建 jail 实例,命名为 Debian。
实例的基本配置
创建 /etc/fstab.debian,内容如下:
在 /etc/jail.conf 中,加入以下内容(若无则新建):
exec.start指定启动 jail 时运行的命令。
在 FreeBSD 中创建 jail 时,一般使用 exec.start = 'sh /etc/rc' 来调用 FreeBSD 的 rc 系统启动服务。
Debian 使用 systemd 作为初始化系统,而 jail 中无法使用 systemd,因此无法直接运行相应命令(但 service 命令仍可使用)。此处使用 /bin/true 安全返回 true(成功状态),不执行任何操作。
例如,在 debian Jail 中启用 sshd 服务后(执行 service ssh start),重启 jail 时 sshd 服务不会随 jail 自动启动。此时可以设置 exec.start = 'service ssh start',以确保启动 jail 时自动启动 sshd 服务。
如果要启用更多的服务,则可以编写如下。
在 jail 启动时顺序启动 SSH 和 D-Bus 服务:
exec.stop停止 jail 时运行的命令。
如果是 FreeBSD jail,通常使用 sh /etc/rc.shutdown jail。
同样由于 systemd 的限制,此处使用 /bin/true 安全返回 true 即可。
启用实例,允许网络访问
启动 jail
停止 jail
在 pf 防火墙中的
jails表中加入 jail 的地址,以允许 jail 访问网络:
更新系统
执行:
或者使用
至此,一个基于 Debian 12 的 Linux jail 已成功建立,同样的方法可用于创建基于不同版本的 Debian 或 Ubuntu 的多个 jail。
jail 开机自启
开机时启动 jail 服务:
默认情况下会启动 /etc/jail.conf 中配置的所有 jail。
另外可以在 /etc/rc.conf 中用 jail_list 变量指定在开机时启动的 jail 的名字,编辑 /etc/rc.conf 写入:
或执行
如果 jail_list 变量为空,则会启动所有在 /etc/jail.conf 中配置的 jail。
创建 Ubuntu jail
Ubuntu jail 的建立方法与 Debian 相同,这里以 Ubuntu 22.04(Jammy)为例。
构建基本系统并配置
创建 /etc/fstab.ubuntu,内容如下:
在 /etc/jail.conf 中写入 Ubuntu 的配置,如下:
启用实例并允许网络访问
如果已经在 /etc/rc.conf 中设置过 jail_enable=YES,也可以用:
开机启动可以参考 debian Jail,执行以下命令启动名为 ubuntu 的 jail:
在 pf 防火墙中的 jails 表中加入 jail 的地址,以允许 jail 访问网络:
更新系统
或者使用
过程和 debian Jail 相同。
创建 antiX Linux jail
antiX Linux 基于 Debian,不使用 systemd 初始化系统。
下载镜像文件并解压
先安装 squashfs-tools,用以解压 AntiX Linux 文件系统镜像。
使用 pkg 安装:
antiX Linux 提供了四款镜像版本:full、base、core 和 net,本示例下载 core 版本:
配置 antiX jail
创建 /etc/fstab.antix,内容如下:
在 /etc/jail.conf 中写入 (这里只展示 antiX 相关部分)
此处将 exec.start 设置为 /etc/init.d/rc 3。
如前文 debian Jail 所述,Debian 使用 systemd 作为初始化系统,而在 jail 中无法使用。因此在 debian Jail 中使用 /bin/true 启动,以安全返回 true 并不执行任何操作。
antiX 不使用 systemd 作为初始化系统,而是使用 rc 进行初始化。此处 /etc/init.d/rc 3 指定 antiX jail 启动时使用 rc 在运行级别 3 初始化 jail,因此 debian Jail 中遇到的服务启动问题在这里不存在,可直接在 jail 启动时运行服务(如 sshd)。
更新系统
设置开机自启,然后启动
在 pf 中允许网络访问,方法同上。
现在进入 jail:
创建 Alpine jail
构建基本系统
创建
/etc/fstab.alpine,内容如下:
在
/etc/jail.conf中写入,
设置开机启动,然后启动
在 pf 中允许网络访问,方法同上。
现在进入 jail:
修改
/etc/jail.conf中 Alpine 的配置:
重启 alpine jail:
jail 中的 GUI
本文示例环境为 Windows 10 物理机,运行 VirtualBox 安装的 FreeBSD 13.1 虚拟机。
在 FreeBSD 虚拟机中已部署了 4 个 jail,如下。其中有一个 FreeBSD jail,为区分 VirtualBox 中的 FreeBSD 虚拟机,称其为 freebsd-jail:
Windows 10 物理机 ⇨ FreeBSD 13.1 虚拟机 ⇨ FreeBSD Jail(freebsd-jail) + debian Jail + Ubuntu Jail + Alpine Jail。
在这 4 个 jail 中分别安装 xclock、firefox、chrome、jwm 这几款软件。
在 freebsd-jail、Debian、Ubuntu 和 Alpine(Alpine 使用 VNC 方法不成功,其它方法如 xclock、xterm 可运行,Firefox 和 Chrome 未成功)中均已成功安装,其中 jwm 用于美化界面。
技巧
不用安装 xorg。
其中,在 Ubuntu 22.04,Firefox、Chrome 要求用 snap 安装,snap 需要 systemd,不能使用,所以使用 deb 包安装。方法如下:
带 X Server 的终端
这里使用 MobaXterm。MobaXterm 默认配置,无多余配置。

确保 X server 已经启用,记下 DISPLAY 值,格式是 hostname:displaynumber.screennumber 这里是 192.168.56.1:0.0
登录 jail(不限方式,可以是 SSH,可以是 jexec;不限用户,可以是普通用户,不一定是 root、wheel 组成员)

4 个 xclock 可独立显示在 Windows 10 桌面上,效果比较理想。
内嵌 X Server
X Server 里的 X Server,这里使用 Xnest/Xephyr,对 X11 应用来说是 X Server,对宿主 X Server 来说是 X Client。
FreeBSD 虚拟机里安装 Xnest 或 Xephyr。两者择其一即可:
或者
在 FreeBSD 中启用
参数说明:
:1即上面提到了DISPLAY值中的displaynumber。FreeBSD 系统 IP 为10.0.2.15,所以完整的DISPLAY值为10.0.2.15:1.0。因为 FreeBSD 系统 X Server 的displaynumber值为0,所以从1开始-listen tcp侦听 TCP 端口在 4 个 jail 中,采取上面相同的方法
四个 jail 可以同时在 FreeBSD 开启的一个 Xnest/Xephyr 窗口中打开 xclock。但是此时的 xclock 因为没有窗口管理器,界面丑,且连最基本的拖动都做不到。可以在执行 xclock 前先执行 jwm,如下。
这里注意 jwm & 执行一次够了,不需要每个 jail 都去执行。此处使用 jwm 是因为其轻量级,Xfce 等桌面环境也可使用,可根据需要尝试。
共享主机 socket 方式
先在 FreeBSD 系统上执行
关闭访问控制:
然后在 jail 的 fstab 中加入下面内容,这里以 ubuntu jail 的 fstab 为例,其它 jail 参照修改即可。
必要时先 mkdir -p /usr/jails/ubuntu/tmp/.X11-unix,确保有挂载点。
重启 jail 后,在 jail 中执行:
上文提到 fstab 文件中有下面这样一行
虽然许多教程中有类似写法,但这不安全,因此注释掉。如果采用该写法,FreeBSD 的 /tmp 目录将暴露在 jail 中,并且可读写,使 jail 内可修改宿主机 /tmp,破坏隔离性。而仅挂载 /tmp/.X11-unix 可显著提高安全性。
X Server TCP 侦听加 xhost 连接管理
此处使用 SDDM 桌面管理器,如使用其它桌面管理器,请参考相应文档,原理相同。
在 FreeBSD 内新建 /usr/local/etc/sddm.conf(如果没有的话),修改 ServerArguments 内容如下:
重启后,FreeBSD 上用下面方式加入 jail IP 以允许访问 (无需 root 权限):
然后在 jail 中,执行:
这里将
DISPLAY设为:0.0、127.0.0.1:0.0、10.0.2.15:0.0都成功了,上面几种方法也可以一一尝试。
VNC
在 jail 中安装 vnc server,可以用 tightvnc-server,也可以用 tigervnc-server,这里以 debian Jail 为例,在 jail 中执行
使用 vnc 客户端登录



备注
宿主机 X Server TCP 侦听加 xhost 连接管理的方式是安全性最差的一种,是 TCP 侦听默认关闭原因之一。
共享宿主机 Socket 的方式注意上面提到的两点安全性还是有保障的。
前四种方法算是“回字的 4 种写法”(回、囘、囬、𡇌),均为 X Server 连接的变体。除了带 X Server 的终端和共享 Socket 方式外,其他方法建议在 jail 内再配置桌面环境。
带 X Server 的终端、共享主机 Socket、VNC 这三种方式比较推荐。无论采用哪种方式,Linux jail 中不应要求每个 X 应用都能运行,这几乎无法实现,因为兼容层无法做到完全兼容,而 FreeBSD jail 的兼容性更好。
除共享宿主机 Socket 的方法外,其他方法同样可在非 jail 环境中使用。
参考资料
https://wiki.freebsd.org/LinuxApps,更多可运行的软件及方法
最后更新于
这有帮助吗?