# sysrc jail_enable="YES"
# sysrc jail_parallel_start="YES"
第 17 章 Jails 和容器
如果发现翻译错误,请直接 发起PR修改。
目录
17.1. 简介
由于系统管理是一项困难的任务,因此开发了许多工具来简化管理员的工作。这些工具通常可以增强系统的安装、配置和维护方式。其中一个可以用来增强 FreeBSD 系统安全性的工具是 jails。自 FreeBSD 4.X 以来,Jails 一直在其有用性、性能、可靠性和安全性方面得到改进。
Jails 是基于 chroot(2) 概念构建的,该概念用于更改一组进程的根目录。这样可以创建一个与系统其余部分分离的安全环境。在 chroot 环境中创建的进程无法访问其外部的文件或资源。因此,入侵 chroot 环境中运行的服务不应允许攻击者危害整个系统。
然而,chroot 有一些限制。它适用于不需要太多灵活性或复杂高级功能的简单任务。随着时间的推移,人们发现了许多逃离 chroot 环境的方法,使其成为不太理想的保护服务的解决方案。
Jails 在多个方面改进了传统 chroot 环境的概念。
在传统的 chroot 环境中,进程只能访问文件系统的一部分。其余的系统资源、系统用户、运行中的进程和网络子系统由 chroot 进程和主机系统的进程共享。Jails 通过虚拟化对文件系统、用户集和网络子系统的访问来扩展这个模型。可以使用更精细的控制来调整被监禁环境的访问权限。Jails 可以被看作是一种操作系统级别的虚拟化。
本章内容包括:
-
在 FreeBSD 安装中,jail 是什么以及它可能起到的作用。
-
不同类型的 jail。
-
配置 jail 网络的不同方法。
-
jail 配置文件。
-
如何创建不同类型的 jail。
-
如何启动、停止和重启一个 jail。
-
jail 管理的基础知识,包括 jail 内部和外部的管理。
-
如何升级不同类型的 jail。
-
一个不完整的 FreeBSD jail 管理器列表。
17.2. Jail 类型
一些管理员将 jail 分为不同类型,尽管底层技术是相同的。每个管理员都必须根据他们需要解决的问题来评估在每种情况下创建哪种类型的 jail。
下面是不同类型的列表,包括它们的特点和使用时需要考虑的事项。
17.2.1. 厚(Thick)Jails
厚 jail 是 FreeBSD jail 的一种传统形式。在厚 jail 中,基本系统的完整副本被复制到 jail 的环境中。这意味着 jail 拥有自己独立的 FreeBSD 基本系统实例,包括库、可执行文件和配置文件。可以将 jail 视为一个几乎完整的独立 FreeBSD 安装,但在主机系统的限制下运行。这种隔离确保 jail 内的进程与主机和其他 jail 中的进程保持分离。
厚 Jails 的优势:
-
高度隔离性:jail 内的进程与主机系统和其他 jail 之间是隔离的。
-
独立性:厚 jail 可以拥有与主机系统或其他 jail 不同版本的库、配置和软件。
-
安全性:由于 jail 包含了自己的基本系统,影响 jail 环境的漏洞或问题不会直接影响主机或其他 jail。
厚 Jails 的缺点:
-
资源开销:由于每个 jail 都维护着自己独立的基础系统,相比于薄 jail,厚 jail 消耗更多的资源。
-
维护:每个 jail 都需要对其基本系统组件进行维护和更新。
17.2.2. 薄(Thin)Jails
薄 jail 使用 OpenZFS 快照或 NullFS 挂载从模板共享基础系统。每个薄 jail 仅复制基础系统的最小子集,与厚 jail 相比,资源消耗更少。然而,这也意味着薄 jail 与厚 jail 相比具有较少的隔离性和独立性。共享组件的更改可能会同时影响多个薄 jail。
简而言之,FreeBSD 薄 Jail 是一种 FreeBSD Jail,它在隔离环境中复制了基本系统的大部分内容,但并非全部。
薄 Jails 的优势:
-
资源效率:与厚 jail 相比,薄 jail 在资源利用上更高效。由于它们共享大部分基础系统,所以占用的磁盘空间和内存较少。这使得在同一硬件上运行更多的 jail 成为可能,而不会消耗过多的资源。
-
更快的部署:创建和启动薄 jail 通常比创建和启动厚 jail 更快。当您需要快速部署多个实例时,这可能特别有优势。
-
统一维护:由于薄 jail 与主机系统共享大部分基础系统(如库和二进制文件),因此只需要在主机上进行一次更新和维护常见的基础系统组件。与为每个厚 jail 维护单独的基础系统相比,这简化了维护过程。
-
共享资源:薄 jail 可以更轻松地与主机系统共享常见的资源,如库和二进制文件。这可能会导致更高效的磁盘缓存和 jail 内应用程序的性能改善。
薄 Jails 的缺点:
-
降低的隔离性:薄 jail 的主要缺点是相比于厚 jail,它们提供的隔离性较低。由于它们共享模板基础系统的大部分内容,可能会同时影响多个 jail 的漏洞或问题。
-
安全问题:薄 jail 中减少的隔离性可能会带来安全风险,因为一个 jail 的妥协可能对其他 jail 或主机系统产生更大的影响潜力。
-
依赖冲突:如果多个独立的容器需要不同版本的相同库或软件,管理依赖关系可能会变得复杂。在某些情况下,这可能需要额外的努力来确保兼容性。
-
兼容性挑战:在一个薄 jail 中,应用程序可能会遇到兼容性问题,如果它们假设某个基本系统环境与模板提供的共享组件不同。
17.3. 主机配置
在主机系统上创建任何 jail 之前,需要进行一些配置并从主机系统中获取一些信息。
需要配置 jail(8) 实用程序,创建必要的目录来配置和安装 jails,从主机的网络获取信息,并检查主机是否使用 OpenZFS 或 UFS 作为其文件系统。
在 jail 中运行的 FreeBSD 版本不能比主机中运行的版本更新。 |
17.3.1. Jail 实用工具
jail(8) 实用程序用于管理 jails。
要在系统启动时启动 jails,请运行以下命令:
使用 |
17.3.2. 网络
FreeBSD jails 的网络配置有多种不同的方式:
- 主机网络模式(IP 共享)
-
在主机网络模式下,一个 jail 与主机系统共享相同的网络堆栈。当一个 jail 在主机网络模式下创建时,它使用相同的网络接口和 IP 地址。这意味着 jail 没有单独的 IP 地址,它的网络流量与主机的 IP 地址相关联。
- 虚拟网络(VNET)
-
虚拟网络是 FreeBSD jails 的一个特性,提供比主机网络等基本网络模式更高级和灵活的网络解决方案。VNET 允许为每个 jail 创建隔离的网络堆栈,为它们提供独立的 IP 地址、路由表和网络接口。这提供了更高级别的网络隔离,并允许 jails 像运行在独立的虚拟机上一样运行。
- netgraph 系统
-
netgraph(4) 是一个多功能的内核框架,用于创建自定义的网络配置。它可以用于定义网络流量在 jails 和主机系统之间以及不同 jails 之间的流动方式。
17.3.3. 设置 jail 目录树
没有特定的位置来放置 jail 的文件。
一些管理员使用 /jail
,其他人使用 /usr/jail
,还有一些人使用 /usr/local/jails
。在本章中,将使用 /usr/local/jails
。
除了 /usr/local/jails 目录之外,还会创建其他目录:
-
media 将包含已下载用户空间的压缩文件。
-
在使用薄 Jails 时,templates 文件夹将包含模板。
-
containers 将包含 jail 。
在使用 OpenZFS 时,执行以下命令为这些目录创建数据集:
# zfs create -o mountpoint=/usr/local/jails zroot/jails
# zfs create zroot/jails/media
# zfs create zroot/jails/templates
# zfs create zroot/jails/containers
在这种情况下, |
在使用 UFS 时,执行以下命令来创建目录:
# mkdir /usr/local/jails/
# mkdir /usr/local/jails/media
# mkdir /usr/local/jails/templates
# mkdir /usr/local/jails/containers
17.3.4. Jail 配置文件
有两种方法来配置 jails 。
第一种方法是在文件 /etc/jail.conf 中为每个 jail 添加一个条目。另一种选项是在目录 /etc/jail.conf.d/ 中为每个 jail 创建一个文件。
没有正确或错误的选择。每个管理员必须选择最适合他们需求的选项。
如果主机系统只有几个 jail,可以在文件 /etc/jail.conf 中为每个 jail 添加一个条目。如果主机系统有很多 jail,最好在 /etc/jail.conf.d/ 目录中为每个 jail 拥有一个配置文件。
一个典型的 jail 入口会是这样的:
jailname { (1) # STARTUP/LOGGING exec.start = "/bin/sh /etc/rc"; (2) exec.stop = "/bin/sh /etc/rc.shutdown"; (3) exec.consolelog = "/var/log/jail_console_${name}.log"; (4) # PERMISSIONS allow.raw_sockets; (5) exec.clean; (6) mount.devfs; (7) # HOSTNAME/PATH host.hostname = "${name}"; (8) path = "/usr/local/jails/containers/${name}"; (9) # NETWORK ip4.addr = 192.168.1.151; (10) ip6.addr = ::ffff:c0a8:197 (11) interface = em0; (12) }
1 | jailname - jail 的名称。 <.> exec.start - 创建 jail 时在 jail 环境中运行的命令。通常运行的命令是 "/bin/sh /etc/rc"。 <.> exec.stop - 删除 jail 之前在 jail 环境中运行的命令。通常运行的命令是 "/bin/sh /etc/rc.shutdown"。 <.> exec.consolelog - 将命令输出(stdout 和 stderr)重定向到的文件。 <.> allow.raw_sockets - 允许在 jail 内创建原始套接字。设置此参数允许像 ping(8) 和 traceroute(8) 这样的实用程序在 jail 内运行。 <.> exec.clean - 在一个干净的环境中运行命令。 <.> mount.devfs - 在 chrooted /dev 目录上挂载一个 devfs(5) 文件系统,并应用 devfs_ruleset 参数中的规则集来限制 jail 内可见的设备。 <.> host.hostname - jail 的主机名。 <.> path - jail 的根目录。在 jail 内运行的任何命令,无论是通过 jail 还是 jexec(8) 运行,都是从此目录开始的。 <.> ip4.addr - IPv4 地址。 IPv4 有两种配置可能性。第一种是像示例中所做的那样建立一个 IP 或 IP 列表。另一种是使用 ip4 替代,并将 inherit 值设置为继承主机的 IP 地址。 <.> ip6.addr - IPv6 地址。 IPv6 有两种配置可能性。第一种是像示例中所做的那样建立一个 IP 或 IP 列表。另一种是使用 ip6 替代,并将 inherit 值设置为继承主机的 IP 地址。 <.> interface - 添加 jail 的 IP 地址的网络接口。通常是主机接口。 |
有关配置变量的更多信息可以在 jail(8) 和 jail.conf(5) 中找到。
17.4. 经典 Jail(厚 Jail )
这些 jail 类似于真实的 FreeBSD 系统。它们可以像普通主机系统一样进行管理,并且可以独立更新。
17.4.1. 创建一个经典 Jail
原则上,一个 jail 只需要一个主机名、一个根目录、一个 IP 地址和一个用户空间。
可以从官方的 FreeBSD 下载服务器获取用于 jail 的用户空间。
执行以下命令以下载用户空间:
# fetch https://download.freebsd.org/ftp/releases/amd64/amd64/13.2-RELEASE/base.txz -o /usr/local/jails/media/13.2-RELEASE-base.txz
下载完成后,需要将内容解压到 jail 目录中。
执行以下命令将用户空间提取到 jail 目录中:
# mkdir -p /usr/local/jails/containers/classic
# tar -xf /usr/local/jails/media/13.2-RELEASE-base.txz -C /usr/local/jails/containers/classic --unlink
在 jail 目录中提取用户空间后,需要复制时区和 DNS 服务器文件:
# cp /etc/resolv.conf /usr/local/jails/containers/classic/etc/resolv.conf
# cp /etc/localtime /usr/local/jails/containers/classic/etc/localtime
在复制文件后,下一步是通过执行以下命令更新到最新的补丁级别:
# freebsd-update -b /usr/local/jails/containers/classic/ fetch install
最后一步是配置 jail。需要在配置文件 /etc/jail.conf 或 jail.conf.d 中添加一个条目,包含 jail 的参数。
一个例子如下:
classic { # STARTUP/LOGGING exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; # PERMISSIONS allow.raw_sockets; exec.clean; mount.devfs; # HOSTNAME/PATH host.hostname = "${name}"; path = "/usr/local/jails/containers/${name}"; # NETWORK ip4.addr = 192.168.1.151; interface = em0; }
执行以下命令以启动 jail :
# service jail start classic
有关如何管理 jails 的更多信息可以在 Jail 管理 部分找到。
17.5. 薄(Thin)Jails
尽管瘦 Jails 使用与胖 Jails 相同的技术,但创建过程是不同的。可以使用 OpenZFS 快照或使用模板和 NullFS 来创建瘦 jails。使用 OpenZFS 快照和使用 NullFS 的模板相比传统的 jails 具有一定的优势,例如可以更快地从快照创建它们,或者可以使用 NullFS 更新多个 jails。
17.5.1. 使用 OpenZFS 快照创建一个瘦 Jail
由于 FreeBSD 和 OpenZFS 之间的良好集成,使用 OpenZFS 快照创建新的瘦 Jails 非常容易。
使用 OpenZFS 快照创建瘦 Jail 的第一步是创建一个模板。
模板只用于创建新的 jail。因此,它们以“只读”模式创建,以便 jail 以不可变的基础创建。
要为模板创建数据集,请执行以下命令:
# zfs create -p zroot/jails/templates/13.2-RELEASE
然后执行以下命令来下载用户空间:
# fetch https://download.freebsd.org/ftp/releases/amd64/amd64/13.2-RELEASE/base.txz -o /usr/local/jails/media/13.2-RELEASE-base.txz
下载完成后,需要执行以下命令将内容解压到模板目录中:
# tar -xf /usr/local/jails/media/13.2-RELEASE-base.txz -C /usr/local/jails/templates/13.2-RELEASE --unlink
在模板目录中提取用户空间后,需要通过执行以下命令将时区和 DNS 服务器文件复制到模板目录中:
# cp /etc/resolv.conf /usr/local/jails/templates/13.2-RELEASE/etc/resolv.conf
# cp /etc/localtime /usr/local/jails/templates/13.2-RELEASE/etc/localtime
下一步要做的是通过执行以下命令更新到最新的补丁级别:
# freebsd-update -b /usr/local/jails/templates/13.2-RELEASE/ fetch install
一旦更新完成,模板就准备好了。
要从模板创建一个 OpenZFS 快照,请执行以下命令:
# zfs snapshot zroot/jails/templates/13.2-RELEASE@base
一旦创建了 OpenZFS 快照,就可以使用 OpenZFS 克隆功能创建无限个 jail。
要创建一个名为 thinjail
的薄 Jail,请执行以下命令:
# zfs clone zroot/jails/templates/13.2-RELEASE@base zroot/jails/containers/thinjail
最后一步是配置 jail。需要在配置文件 /etc/jail.conf 或 jail.conf.d 中添加一个条目,包含 jail 的参数。
一个例子如下:
thinjail { # STARTUP/LOGGING exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; # PERMISSIONS allow.raw_sockets; exec.clean; mount.devfs; # HOSTNAME/PATH host.hostname = "${name}"; path = "/usr/local/jails/containers/${name}"; # NETWORK ip4 = inherit; interface = em0; }
执行以下命令以启动 jail :
# service jail start thinjail
有关如何管理 jails 的更多信息可以在 Jail 管理 部分找到。
17.5.2. 使用 NullFS 创建一个薄 Jail
使用薄 Jail 技术和使用 NullFS 将特定目录从主机系统选择性地共享到 jail 中,可以减少系统文件的重复创建。
第一步是创建数据集以保存模板,如果使用 OpenZFS,请执行以下命令:
# zfs create -p zroot/jails/templates/13.2-RELEASE-base
如果使用 UFS,则使用以下命令:
# mkdir /usr/local/jails/templates/13.2-RELEASE-base
然后执行以下命令来下载用户空间:
# fetch https://download.freebsd.org/ftp/releases/amd64/amd64/13.2-RELEASE/base.txz -o /usr/local/jails/media/13.2-RELEASE-base.txz
下载完成后,需要执行以下命令将内容解压到模板目录中:
# tar -xf /usr/local/jails/media/13.2-RELEASE-base.txz -C /usr/local/jails/templates/13.2-RELEASE-base --unlink
一旦用户空间在模板目录中被提取出来,就需要通过执行以下命令将时区和 DNS 服务器文件复制到模板目录中:
# cp /etc/resolv.conf /usr/local/jails/templates/13.2-RELEASE-base/etc/resolv.conf
# cp /etc/localtime /usr/local/jails/templates/13.2-RELEASE-base/etc/localtime
将文件移动到模板后,下一步要做的是通过执行以下命令更新到最新的补丁级别:
# freebsd-update -b /usr/local/jails/templates/13.2-RELEASE-base/ fetch install
除了基本模板之外,还需要创建一个目录,用于存放 skeleton
。一些目录将从模板复制到 skeleton
中。
在使用 OpenZFS 的情况下,执行以下命令创建 skeleton
的数据集:
# zfs create -p zroot/jails/templates/13.2-RELEASE-skeleton
如果使用 UFS,则使用以下命令:
# mkdir /usr/local/jails/templates/13.2-RELEASE-skeleton
然后创建 skeleton
目录。 skeleton
目录将保存 jail 的本地目录。
执行以下命令创建目录:
# mkdir -p /usr/local/jails/templates/13.2-RELEASE-skeleton/home
# mkdir -p /usr/local/jails/templates/13.2-RELEASE-skeleton/usr
# mv /usr/local/jails/templates/13.2-RELEASE-base/etc /usr/local/jails/templates/13.2-RELEASE-skeleton/etc
# mv /usr/local/jails/templates/13.2-RELEASE-base/usr/local /usr/local/jails/templates/13.2-RELEASE-skeleton/usr/local
# mv /usr/local/jails/templates/13.2-RELEASE-base/tmp /usr/local/jails/templates/13.2-RELEASE-skeleton/tmp
# mv /usr/local/jails/templates/13.2-RELEASE-base/var /usr/local/jails/templates/13.2-RELEASE-skeleton/var
# mv /usr/local/jails/templates/13.2-RELEASE-base/root /usr/local/jails/templates/13.2-RELEASE-skeleton/root
下一步是通过执行以下命令创建到 skeleton
的符号链接:
# cd /usr/local/jails/templates/13.2-RELEASE-base/
# mkdir skeleton
# ln -s skeleton/etc etc
# ln -s skeleton/home home
# ln -s skeleton/root root
# ln -s skeleton/usr/local usr/local
# ln -s skeleton/tmp tmp
# ln -s skeleton/var var
准备好了 skeleton
之后,需要将数据复制到 jail 目录中。
如果使用 OpenZFS,可以使用 OpenZFS 快照通过执行以下命令轻松创建所需数量的 jails :
# zfs snapshot zroot/jails/templates/13.2-RELEASE-skeleton@base
# zfs clone zroot/jails/templates/13.2-RELEASE-skeleton@base zroot/jails/containers/thinjail
如果使用 UFS 文件系统,可以通过执行以下命令来使用 cp(1) 程序:
# mkdir /usr/local/jails/containers/thinjail
# cp -R /usr/local/jails/templates/13.2-RELEASE-skeleton /usr/local/jails/containers/thinjail
然后创建一个目录,用于挂载基本模板和 skeleton:
# mkdir -p /usr/local/jails/thinjail-nullfs-base
在 /etc/jail.conf 中添加一个 jail 条目,或者在 jail.conf.d 目录中添加一个文件,内容如下:
thinjail { # STARTUP/LOGGING exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; # PERMISSIONS allow.raw_sockets; exec.clean; mount.devfs; # HOSTNAME/PATH host.hostname = "${name}"; path = "/usr/local/jails/containers/${name}"; # NETWORK ip4.addr = 192.168.1.153; interface = em0; # MOUNT mount.fstab = "/usr/local/jails/thinjail-nullfs-base.fstab"; }
然后按照以下方式创建 /usr/local/jails/thinjail-nullfs-base.fstab 文件:
/usr/local/jails/templates/13.2-RELEASE-base /usr/local/jails/thinjail-nullfs-base/ nullfs ro 0 0 /usr/local/jails/containers/thinjail /usr/local/jails/thinjail-nullfs-base/skeleton nullfs rw 0 0
执行以下命令以启动 jail :
# service jail start thinjail
17.5.3. 创建一个 VNET Jail
FreeBSD VNET Jails 拥有独立的网络堆栈,包括接口、 IP 地址、路由表和防火墙规则。
创建 VNET jail 的第一步是通过执行以下命令创建 bridge(4) 。
# ifconfig bridge create
输出应该类似于以下内容:
bridge0
创建了 bridge
之后,需要通过执行以下命令将其附加到 em0
接口:
# ifconfig bridge0 addm em0
要使此设置在重新启动后保持不变,请将以下行添加到 /etc/rc.conf 文件中:
defaultrouter="192.168.1.1" cloned_interfaces="bridge0" ifconfig_bridge0="inet 192.168.1.150/24 addm em0 up"
下一步是按照上述所示创建 jail 。
可以使用 经典 Jail(厚 Jail ) 过程和 薄(Thin)Jails 过程。唯一需要更改的是 /etc/jail.conf 文件中的配置。
路径 /usr/local/jails/containers/vnet 将被用作创建的 jail 的示例。
以下是一个 VNET jail 的配置示例:
vnet { # STARTUP/LOGGING exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; # PERMISSIONS allow.raw_sockets; exec.clean; mount.devfs; devfs_ruleset = 5; # PATH/HOSTNAME path = "/usr/local/jails/containers/${name}"; host.hostname = "${name}"; # VNET/VIMAGE vnet; vnet.interface = "${epair}b"; # NETWORKS/INTERFACES $id = "154"; (1) $ip = "192.168.1.${id}/24"; $gateway = "192.168.1.1"; $bridge = "bridge0"; (2) $epair = "epair${id}"; # ADD TO bridge INTERFACE exec.prestart += "ifconfig ${epair} create up"; exec.prestart += "ifconfig ${epair}a up descr jail:${name}"; exec.prestart += "ifconfig ${bridge} addm ${epair}a up"; exec.start += "ifconfig ${epair}b ${ip} up"; exec.start += "route add default ${gateway}"; exec.poststop = "ifconfig ${bridge} deletem ${epair}a"; exec.poststop += "ifconfig ${epair}a destroy"; }
1 | 表示 Jail 的 IP 地址,它必须是 唯一的 。 <.> 指的是之前创建的桥接。 |
17.5.4. 创建一个 Linux Jail
FreeBSD 可以使用 Linux 二进制兼容性 和 debootstrap(8) 在 jail 中运行 Linux。jail 没有内核,它们在主机的内核上运行。因此,在主机系统中启用 Linux 二进制兼容性是必要的。
要在启动时启用 Linux ABI,请执行以下命令:
# sysrc linux_enable="YES"
一旦启用,可以通过执行以下命令来启动,无需重新启动:
# service linux start
下一步将是按照上述所示创建一个 jail ,例如在 使用 OpenZFS 快照创建一个瘦 Jail 中,但 不要 执行配置。FreeBSD Linux jail 需要特定的配置,将在下面详细说明。
一旦按照上述说明创建了 jail,执行以下命令进行所需的 jail 配置并启动它:
# jail -cm \
name=ubuntu \
host.hostname="ubuntu.example.com" \
path="/usr/local/jails/ubuntu" \
interface="em0" \
ip4.addr="192.168.1.150" \
exec.start="/bin/sh /etc/rc" \
exec.stop="/bin/sh /etc/rc.shutdown" \
mount.devfs \
devfs_ruleset=4 \
allow.mount \
allow.mount.devfs \
allow.mount.fdescfs \
allow.mount.procfs \
allow.mount.linprocfs \
allow.mount.linsysfs \
allow.mount.tmpfs \
enforce_statfs=1
要访问 jail ,需要安装 sysutils/debootstrap。
执行以下命令以访问 FreeBSD Linux jail:
# jexec -u root ubuntu
在 jail 内执行以下命令来安装 sysutils/debootstrap 并准备 Ubuntu 环境:
# pkg install debootstrap
# debootstrap jammy /compat/ubuntu
当进程完成并在控制台上显示 successfully
消息时,需要通过执行以下命令在主机系统上停止 jail:
# service jail ubuntu onestop
然后在 [/etc/jail.conf] 文件中添加一个 Linux jail 的条目:
ubuntu { # STARTUP/LOGGING exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; # PERMISSIONS allow.raw_sockets; exec.clean; mount.devfs; devfs_ruleset=4; # HOSTNAME/PATH host.hostname = "${name}"; path = "/usr/local/jails/containers/${name}"; # NETWORK ip4.addr = 192.168.1.155; interface = em0; # MOUNT mount += "devfs $path/compat/ubuntu/dev devfs rw 0 0"; mount += "tmpfs $path/compat/ubuntu/dev/shm tmpfs rw,size=1g,mode=1777 0 0"; mount += "fdescfs $path/compat/ubuntu/dev/fd fdescfs rw,linrdlnk 0 0"; mount += "linprocfs $path/compat/ubuntu/proc linprocfs rw 0 0"; mount += "linsysfs $path/compat/ubuntu/sys linsysfs rw 0 0"; mount += "/tmp $path/compat/ubuntu/tmp nullfs rw 0 0"; mount += "/home $path/compat/ubuntu/home nullfs rw 0 0"; }
然后可以使用以下命令正常启动 jail:
# service jail start ubuntu
可以使用以下命令访问 Ubuntu 环境:
# jexec ubuntu chroot /compat/ubuntu /bin/bash
更多信息可以在章节 Linux 二进制兼容性 中找到。
17.6. Jail 管理
一旦创建了 jail,就可以执行许多操作,比如启动、重启或删除 jail,安装软件等。本节将描述可以在主机上执行的不同 jail 操作。
17.6.1. 列出运行中的 Jails
要列出运行在主机系统上的 jails,可以使用命令 jls(8)。
# jls
输出应该类似于以下内容:
JID IP Address Hostname Path 1 192.168.250.70 classic /usr/local/jails/containers/classic
例如,执行以下命令以获取 JSON
输出:
# jls --libxo=json
输出应该类似于以下内容:
{"__version": "2", "jail-information": {"jail": [{"jid":1,"ipv4":"192.168.250.70","hostname":"classic","path":"/usr/local/jails/containers/classic"}]}}
17.6.2. 启动、重新启动和停止一个 Jail
service(8) 用于在主机上启动、重启或停止一个 jail。
例如,要启动一个 jail,请运行以下命令:
# service jail start jailname
将 start
参数更改为 restart
或 stop
以执行其他对 jail 的操作。
17.6.3. 销毁一个 jail
销毁一个 jail 并不像使用 service(8) 停止 jail 和删除 jail 目录以及 /etc/jail.conf 条目那样简单。
FreeBSD 非常重视系统安全。因此,有一些文件即使是 root 用户也无法删除。这种功能被称为文件标志。
第一步是停止所需的 jail 执行以下命令:
# service jail stop jailname
第二步是使用 chflags(1) 命令来移除这些标志,执行以下命令,其中 classic
是要移除的 jail 的名称:
# chflags -R 0 /usr/local/jails/classic
第三步是删除 jail 所在的目录:
# rm -rf /usr/local/jails/classic
最后,需要在 /etc/jail.conf 或 jail.conf.d 中删除 jail 条目。
17.6.4. 在 Jail 中处理软件包
pkg(8) 工具支持 -j
参数,以处理安装在 jail 内的软件包。
例如,在 jail 中安装 nginx-lite,可以从主机上执行以下命令:
# pkg -j classic install nginx-lite
有关在 FreeBSD 中使用软件包的更多信息,请参阅 “安装应用程序:软件包和 Ports”。
17.6.5. 访问一个 Jail
虽然上面已经提到最好从主机系统管理 jail,但可以使用 jexec(8) 进入 jail。
可以通过在主机上运行 jexec(8) 来进入 jail。
# jexec -u root jailname
当访问 jail 时,将显示在 motd(5) 中配置的消息。
17.6.6. 在 Jail 中执行命令
要在一个 jail 中从主机系统执行命令,可以使用 jexec(8) 命令。
例如,要停止在 jail 中运行的服务,将执行以下命令:
# jexec -l jailname service stop nginx
17.7. Jail 升级
升级 FreeBSD Jails 可以确保隔离环境保持安全、最新,并与 FreeBSD 生态系统中的最新功能和改进保持一致。
17.7.1. 使用 OpenZFS 快照升级经典 Jail 或薄 Jail
Jails 必须从主机操作系统进行更新。在 FreeBSD 中,默认行为是禁止在 jail 中使用 chflags(1) 命令。这将阻止对某些文件的更新,因此在 jail 内部进行更新将失败。
要将 jail 更新到运行的 FreeBSD 版本的最新补丁版本,请在主机上执行以下命令:
# freebsd-update -j classic fetch install
# service jail restart classic
要将 jail 升级到新的主要或次要版本,首先按照 “执行主要和次要版本升级” 中描述的方法升级主机系统。一旦主机升级并重新启动,就可以升级 jail。
如果从一个版本升级到另一个版本,创建一个新的 jail 比完全升级更容易。 |
例如,要从 13.1-RELEASE 升级到 13.2-RELEASE,请在主机上执行以下命令:
# freebsd-update -j classic -r 13.2-RELEASE upgrade
# freebsd-update -j classic install
# service jail restart classic
# freebsd-update -j classic install
# service jail restart classic
需要执行两次 |
然后,如果是一个主要版本的升级,重新安装所有已安装的软件包并重新启动 jail。这是必需的,因为在 FreeBSD 的主要版本之间升级时,ABI 版本会发生变化。
来自主机:
# pkg -j jailname upgrade -f
# service jail restart jailname
17.7.2. 使用 NullFS 升级薄 Jail
由于使用 NullFS 的薄 Jails 共享了大部分系统目录,因此它们非常容易更新。只需更新模板即可,这样可以同时更新多个 Jail。
要将模板更新到运行的 FreeBSD 版本的最新补丁版本,请在主机上执行以下命令:
# freebsd-update -b /usr/local/jails/templates/13.1-RELEASE-base/ fetch install
# service jail restart
要将模板升级到新的主要或次要版本,首先按照 “执行主要和次要版本升级” 中描述的方式升级主机系统。一旦主机升级并重新启动,然后可以升级模板。
例如,要从 13.1-RELEASE 升级到 13.2-RELEASE ,请在主机上执行以下命令:
# freebsd-update -b /usr/local/jails/templates/13.1-RELEASE-base/ -r 13.2-RELEASE upgrade
# freebsd-update -b /usr/local/jails/templates/13.1-RELEASE-base/ install
# service jail restart
# freebsd-update -b /usr/local/jails/templates/13.1-RELEASE-base/ install
# service jail restart
17.8. Jail 资源限制
系统管理员需要考虑从主机系统控制 jail 使用的资源的任务。
rctl(8) 允许您从主机系统管理 jail 可以使用的资源。
必须在 |
限制 jail 资源的语法如下:
rctl -a jail:<jailname>:resource:action=amount/percentage
例如,要限制一个 jail 可以访问的最大 RAM,运行以下命令:
# rctl -a jail:classic:memoryuse:deny=2G
为了使限制在主机系统重新启动后仍然有效,需要将规则添加到 /etc/rctl.conf 文件中,如下所示:
jail:classic:memoryuse:deny=2G/jail
有关资源限制的更多信息可以在安全章节中找到,具体请参考 “资源限制部分” 。
17.9. Jail 管理器和容器
如前所述,每种类型的 FreeBSD Jail 都可以手动创建和配置,但 FreeBSD 还有第三方工具可以使配置和管理更加简便。
下面是一个不完整的不同 FreeBSD Jail 管理器的列表:
名称 | 许可证 | 包 | 文档 |
---|---|---|---|
BastilleBSD |
BSD-3 |
||
pot |
BSD-3 |
||
cbsd |
BSD-2 |
||
AppJail |
BSD-3 |
sysutils/appjail, for devel sysutils/appjail-devel |
|
iocage |
BSD-2 |
||
ezjail |
上次修改时间: September 18, 2024 by fiercex