第十七章 Jails和容器17.1. 简介17.2. Jail 类型17.2.1. 厚 Jails17.2.2. 瘦 Jails17.2.3. 服务 Jails17.2.4. VNET Jails17.2.5. Linux Jails17.3. 主机配置17.3.1. Jail 实用程序17.3.2. 网络17.3.3. 设置Jail目录树17.3.4. Jail 配置文件17.4. 经典 Jail(厚 Jail)17.4.1. 创建一个经典Jail17.5. 瘦 Jails17.5.1. 使用OpenZFS快照创建瘦Jail17.5.2. 使用NullFS创建瘦Jail17.5.3. 创建VNET Jail17.5.4. 创建一个Linux Jail17.5.5. 配置服务Jails17.6. Jail 管理17.6.1. 列出运行中的jails17.6.2. 开始、重启和停止Jail17.6.3. 销毁Jail17.6.4. 在Jail中处理包17.6.5. 访问Jail17.6.6. 在Jail中执行命令17.7. Jail升级17.7.1. 使用OpenZFS快照升级经典Jail或瘦Jail17.7.2. 使用NullFS升级瘦Jail17.8. Jail资源限制17.9. Jail管理器和容器
由于系统管理是一项艰巨的任务,因此开发了许多工具,使管理员的生活更轻松。这些工具通常会增强系统的安装、配置和维护方式。jails 是可用于增强FreeBSD系统安全性的工具之一。Jails从FreeBSD 4.X开始就可以使用,并且在实用性、性能、可靠性和安全性方面都在不断增强。
Jails基于 chroot(2) 概念构建,该概念用于更改一组进程的根目录。这创造了一个安全的环境,与系统的其他部分分开。在chrooted环境中创建的进程无法访问其外部的文件或资源。因此,破坏在chroote环境中运行的服务不应允许攻击者破坏整个系统。
然而,chroot有几个局限性。它适用于不需要太多灵活性或复杂高级功能的简单任务。随着时间的推移,人们发现了许多逃离chrooted环境的方法,使其成为保护服务的不太理想的解决方案。
Jails在几个方面改进了传统chroot环境的概念。
在传统的chroot环境中,进程仅限于它们可以访问的文件系统部分。其余的系统资源、系统用户、正在运行的进程和网络子系统由chrooted进程和主机系统的进程共享。jails通过虚拟化对文件系统、用户集和网络子系统的访问来扩展这种模式。更细粒度的控制可用于调整jails环境的访问。jails可以被视为一种操作系统级的虚拟化。
本章涵盖:
•什么是jail,它在FreeBSD安装中有什么作用。 •不同类型的jail。 •为jail配置网络的不同方法。 •jail配置文件。 •如何创建不同类型的jail。 •如何启动、停止和重新启动jail。 •jail内外的jail管理基础知识。 •如何升级不同类型的jail。 •不同FreeBSD jail管理者的不完整列表。
一些管理员将jail分为不同类型,尽管底层技术是相同的。每个管理员都必须根据他们必须解决的问题,评估在每种情况下创建哪种类型的jail。
下面列出了不同类型、它们的特点和使用注意事项。
Tick Jails —— 厚jail,是FreeBSDjail的一种传统形式。在一个厚jail里,基础系统的完整副本被复制到jail的环境中。这意味着jail有自己独立的FreeBSD基础系统实例,包括库、可执行文件和配置文件。jail可以被认为是一个几乎完整的独立FreeBSD安装,但在主机系统的范围内运行。这种隔离确保了jail内的进程与主机和其他jail的进程分开。
厚jail的优点:
厚jail的缺点:
瘦jail使用OpenZFS快照或模板中的NullFS挂载共享基础系统。每个瘦jail只复制基本系统的一小部分,与厚jail相比,资源消耗更少。然而,这也意味着与厚jail相比,瘦jail的隔离性和独立性较低。共享组件的更改可能会同时影响多个瘦jail。
总之,FreeBSD瘦jail是一种FreeBSDjail,它在隔离环境中复制了基础系统的大部分,但不是全部。
瘦 Jails的优点:
瘦 Jails的缺点:
serivice jails —— 服务jails,直接与主机共享完整的文件系统树(jail根路径为/),因此可以访问和修改主机上的任何文件,并与主机共享相同的用户帐户。默认情况下,它无法访问网络或jail中限制的其他资源,但可以将其配置为重新使用主机的网络并删除一些jail限制。服务jail的用例是以最小的配置将服务/守护进程自动限制在jail内,并且不知道此类服务/守护程序所需的文件。服务jail自FreeBSD 15以来就存在。
服务 Jails的优点:
服务jail的缺点:
服务jail不需要下文讨论的大多数jail配置。要了解jail是如何工作的,建议了解这些配置的可能性。有关配置服务jail所需内容的详细信息,请参阅【17.5.5. 配置服务jail】。
FreeBSD VNET jail是一个虚拟化环境,允许隔离和控制其中运行的进程的网络资源。它通过为jail内的进程创建单独的网络堆栈来提供高级别的网络分段和安全性,确保jail中的网络流量与主机系统和其他jail隔离。
本质上,FreeBSD VNETjail增加了一种网络配置机制。这意味着VNETjail可以创建为厚jail或瘦jail。
FreeBSD Linux Jail是FreeBSD操作系统中的一项功能,它允许在FreeBSD Jail中使用Linux二进制文件和应用程序。此功能是通过包含一个兼容层来实现的,该兼容层允许在FreeBSD内核上翻译和执行某些Linux系统调用和库。Linux Jail的目的是方便在FreeBSD系统上执行Linux软件,而不需要单独的Linux虚拟机或环境。
在主机系统上创建任何jail之前,有必要执行某些配置并从主机系统获取一些信息。
需要配置 jail(8) 实用程序,创建配置和安装jail所需的目录,从主机的网络获取信息,并检查主机是使用OpenZFS还是UFS作为其文件系统。
xxxxxxxxxx在jail中运行的FreeBSD版本不能比在主机中运行的版本更新。jail(8) 实用程序管理jails。
要在系统启动时启动jail,请运行以下命令:
xxxxxxxxxx# sysrc jail_enable="YES"# sysrc jail_parallel_start="YES"xxxxxxxxxx使用jail_parallel_start,所有配置的jails都将在后台启动。FreeBSD jail的网络可以通过几种不同的方式配置:
主机网络模式(Host Networking Mode,IP共享)
在主机网络模式下,jail与主机系统共享相同的网络堆栈。当在主机网络模式下创建jail时,它使用相同的网络接口和IP地址。这意味着jail没有单独的IP地址,其网络流量与主机的IP相关联。
虚拟网络(VNET)
虚拟网络是FreeBSD jail的一个特性,它提供了比主机网络等基本网络模式更先进、更灵活的网络解决方案。VNET允许为每个jail创建隔离的网络堆栈,为它们提供自己的单独IP地址、路由表和网络接口。这提供了更高级别的网络隔离,并允许jail像在单独的虚拟机上运行一样运行。
网络图系统(The netgraph system)
netgraph(4) 是一个用于创建自定义网络配置的通用内核框架。它可用于定义网络流量如何在jail和主机系统之间以及不同jails之间流动。
没有具体的地方可以存放jails的文件。
一些管理员使用 /jail ,另一些使用 /usr/jail ,还有一些使用 /usr/local/jail 。本章将使用 /usr/local/jail 。
除了 /usr/local/jail 之外,还将创建其他目录:
使用OpenZFS时,执行以下命令为这些目录创建数据集:
xxxxxxxxxx# zfs create -o mountpoint=/usr/local/jails zroot/jails# zfs create zroot/jails/media# zfs create zroot/jails/templates# zfs create zroot/jails/containersxxxxxxxxxx在这种情况下,zroot用于父数据集,但也可以使用其他数据集。使用UFS时,执行以下命令以创建目录:
xxxxxxxxxx# mkdir /usr/local/jails/# mkdir /usr/local/jails/media# mkdir /usr/local/jails/templates# mkdir /usr/local/jails/containers有两种方法可以配置jails。
第一种方法是在 /etc/jail.conf 文件中为每个jail添加一个条目。另一种方法是为 /etc/jail.conf.d/ 目录中的每个jail创建一个文件。
如果主机系统的jail很少,可以在 /etc/jail.conf 文件中为每个jail添加一个条目。如果主机系统有很多jail,最好在 /etc/jail.conf.d/ 目录中为每个jail设置一个配置文件。
/etc/jail.conf.d/ 中的文件必须以 .conf 作为扩展名,并且必须包含在 /etc/jail.conf 中:
xxxxxxxxxx.include "/etc/jail.conf.d/*.conf";一个典型的jail条目看起来像这样:
xxxxxxxxxxjailname { ① exec.start = "/bin/sh /etc/rc"; ② exec.stop = "/bin/sh /etc/rc.shutdown"; ③ exec.consolelog = "/var/log/jail_console_${name}.log"; ④ allow.raw_sockets; ⑤ exec.clean; ⑥ mount.devfs; ⑦ host.hostname = "${name}"; ⑧ path = "/usr/local/jails/containers/${name}"; ⑨ ip4.addr = 192.168.1.151; ⑩ ip6.addr = ::ffff:c0a8:197 ⑪ interface = em0; ⑫} ① 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) 中找到。
这些jail类似于真正的FreeBSD系统。它们可以或多或少地像普通主机系统一样进行管理,并独立更新。
原则上,jail只需要一个主机名、根目录、IP地址和用户空间(userland)。
jail的用户空间可以从官方FreeBSD下载服务器获得。
执行以下命令下载用户空间:
xxxxxxxxxx# fetch https://download.freebsd.org/ftp/releases/amd64/amd64/14.2-RELEASE/base.txz -o /usr/local/jails/media/14.2-RELEASE-base.txz下载完成后,需要将内容提取到jail目录中。
执行以下命令将用户区提取到jail的目录中:
xxxxxxxxxx# mkdir -p /usr/local/jails/containers/classic# tar -xf /usr/local/jails/media/14.2-RELEASE-base.txz -C /usr/local/jails/containers/classic --unlink在jail目录中提取用户空间后,有必要复制时区和DNS服务器文件:
xxxxxxxxxx# cp /etc/resolv.conf /usr/local/jails/containers/classic/etc/resolv.conf# cp /etc/localtime /usr/local/jails/containers/classic/etc/localtime复制文件后,下一步要做的是通过执行以下命令更新到最新补丁级别:
xxxxxxxxxx# freebsd-update -b /usr/local/jails/containers/classic/ fetch install最后一步是配置jail。有必要在配置文件 /etc/jail.conf 或 jail.conf.d 中添加一个包含jail参数的条目。
示例如下:
xxxxxxxxxxclassic { exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; allow.raw_sockets; exec.clean; mount.devfs; host.hostname = "${name}"; path = "/usr/local/jails/containers/${name}"; ip4.addr = 192.168.1.151; interface = em0;}运行以下命令启动此jail:
xxxxxxxxxx# service jail start classic有关如何管理jails的更多信息,请参阅【17.6. Jail管理】一节。
虽然瘦Jails使用与厚Jails相同的技术,但创建过程不同。瘦Jail可以使用OpenZFS快照或使用模板和NullFS创建。使用NullFS的OpenZFS快照和模板比经典jail具有某些优势,例如能够从快照中更快地创建它们,或者能够使用NullFS更新多个jail。
由于FreeBSD和OpenZFS之间的良好集成,使用OpenZFS快照创建新的瘦Jails非常容易。
要使用OpenZFS快照创建瘦Jail,第一步是按照【17.3.3. 设置Jail目录树】中的说明创建Jail目录树。
接下来,创建一个模板。模板仅用于创建新jails。出于这个原因,它们是以“只读”模式创建的,因此jail是以不可变的基础创建的。
要为模板创建数据集,请执行以下命令:
xxxxxxxxxx# zfs create -p zroot/jails/templates/14.2-RELEASE然后执行以下命令下载用户空间:
xxxxxxxxxx# fetch https://download.freebsd.org/ftp/releases/amd64/amd64/14.2-RELEASE/base.txz -o /usr/local/jails/media/14.2-RELEASE-base.txz下载完成后,需要通过执行以下命令提取模板目录中的内容:
xxxxxxxxxx# tar -xf /usr/local/jails/media/14.2-RELEASE-base.txz -C /usr/local/jails/templates/14.2-RELEASE --unlink在模板目录中提取用户空间后,有必要通过执行以下命令将时区和DNS服务器文件复制到模板目录中:
xxxxxxxxxx# cp /etc/resolv.conf /usr/local/jails/templates/14.2-RELEASE/etc/resolv.conf# cp /etc/localtime /usr/local/jails/templates/14.2-RELEASE/etc/localtime接下来要做的是通过执行以下命令更新到最新补丁级别:
xxxxxxxxxx# freebsd-update -b /usr/local/jails/templates/14.2-RELEASE/ fetch install更新完成后,模板就准备好了。
要从模板创建OpenZFS快照,请执行以下命令:
xxxxxxxxxx# zfs snapshot zroot/jails/templates/14.2-RELEASE@base一旦创建了OpenZFS快照,就可以使用OpenZFS 克隆函数创建无限jails。
要创建名为 thinjail 的瘦 Jail,请执行以下命令:
xxxxxxxxxx# zfs clone zroot/jails/templates/14.2-RELEASE@base zroot/jails/containers/thinjail最后一步是配置jail。有必要在配置文件 /etc/jail.conf 或 jail.conf.d 中添加一个包含jail参数的条目。
示例如下:
xxxxxxxxxxthinjail { exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; allow.raw_sockets; exec.clean; mount.devfs; host.hostname = "${name}"; path = "/usr/local/jails/containers/${name}"; ip4 = inherit; interface = em0;}执行以下命令启动jail:
xxxxxxxxxx# service jail start thinjail有关如何管理jails的更多信息,请参阅【17.6. Jail管理】一节。
通过使用瘦Jail技术和使用NullFS选择性地将特定目录从主机系统共享到jail中,可以创建jail,减少系统文件的重复。
第一步是创建数据集以保存模板,如果使用OpenZFS,请执行以下命令:
xxxxxxxxxx# zfs create -p zroot/jails/templates/14.2-RELEASE-base或者,如果使用UFS:
xxxxxxxxxx# mkdir /usr/local/jails/templates/14.2-RELEASE-base然后执行以下命令下载用户空间:
xxxxxxxxxx# fetch https://download.freebsd.org/ftp/releases/amd64/amd64/14.2-RELEASE/base.txz -o /usr/local/jails/media/14.2-RELEASE-base.txz下载完成后,需要通过执行以下命令提取模板目录中的内容:
xxxxxxxxxx# tar -xf /usr/local/jails/media/14.2-RELEASE-base.txz -C /usr/local/jails/templates/14.2-RELEASE-base --unlink一旦在模板目录中提取了用户空间,就需要通过执行以下命令将时区和DNS服务器文件复制到模板目录中:
xxxxxxxxxx# cp /etc/resolv.conf /usr/local/jails/templates/14.2-RELEASE-base/etc/resolv.conf# cp /etc/localtime /usr/local/jails/templates/14.2-RELEASE-base/etc/localtime将文件移动到模板后,下一步要做的就是通过执行以下命令更新到最新的补丁级别:
xxxxxxxxxx# freebsd-update -b /usr/local/jails/templates/14.2-RELEASE-base/ fetch install除了基础模板外,还需要创建一个 skeleton (骨架)所在的目录。一些目录将从模板复制到 skeleton 。
如果使用OpenZFS,请执行以下命令为 skeleton 创建数据集:
xxxxxxxxxx# zfs create -p zroot/jails/templates/14.2-RELEASE-skeleton或者在使用UFS的情况下:
xxxxxxxxxx# mkdir /usr/local/jails/templates/14.2-RELEASE-skeleton然后创建 skeleton 目录。 skeleton 目录将保存监狱的本地目录。
执行以下命令以创建目录:
xxxxxxxxxx# mkdir -p /usr/local/jails/templates/14.2-RELEASE-skeleton/home# mkdir -p /usr/local/jails/templates/14.2-RELEASE-skeleton/usr# mv /usr/local/jails/templates/14.2-RELEASE-base/etc /usr/local/jails/templates/14.2-RELEASE-skeleton/etc# mv /usr/local/jails/templates/14.2-RELEASE-base/usr/local /usr/local/jails/templates/14.2-RELEASE-skeleton/usr/local# mv /usr/local/jails/templates/14.2-RELEASE-base/tmp /usr/local/jails/templates/14.2-RELEASE-skeleton/tmp# mv /usr/local/jails/templates/14.2-RELEASE-base/var /usr/local/jails/templates/14.2-RELEASE-skeleton/var# mv /usr/local/jails/templates/14.2-RELEASE-base/root /usr/local/jails/templates/14.2-RELEASE-skeleton/root下一步是通过执行以下命令创建指向 skeleton 的符号链接:
xxxxxxxxxx# cd /usr/local/jails/templates/14.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 varskeleton 准备就绪后,有必要将数据复制到jail目录。
在使用OpenZFS的情况下,OpenZFS快照可用于通过执行以下命令轻松创建所需数量的jails:
xxxxxxxxxx# zfs snapshot zroot/jails/templates/14.2-RELEASE-skeleton@base# zfs clone zroot/jails/templates/14.2-RELEASE-skeleton@base zroot/jails/containers/thinjail如果使用UFS,可以通过执行以下命令来使用 cp(1) 程序:
xxxxxxxxxx# cp -R /usr/local/jails/templates/14.2-RELEASE-skeleton /usr/local/jails/containers/thinjail然后创建安装基础模板和骨架的目录:
xxxxxxxxxx# mkdir -p /usr/local/jails/thinjail-nullfs-base在 /etc/jail.conf 中添加jail条目或在 jail.conf.d 中添加文件,如下所示:
xxxxxxxxxxthinjail { exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; allow.raw_sockets; exec.clean; mount.devfs; host.hostname = "${name}"; path = "/usr/local/jails/${name}-nullfs-base"; ip4.addr = 192.168.1.153; interface = em0; mount.fstab = "/usr/local/jails/${name}-nullfs-base.fstab";}然后创建 /usr/local/jails/thinjail-nullfs-base.fstab 文件,如下所示:
xxxxxxxxxx/usr/local/jails/templates/14.2-RELEASE-base /usr/local/jails/thinjail-nullfs-base/ nullfs ro 0 0/usr/local/jails/containers/thinjail /usr/local/jails/thinjail-nullfsbase/ skeleton nullfs rw 0 0执行以下命令启动jail:
xxxxxxxxxx# service jail start thinjailFreeBSD VNET Jails有自己独特的网络堆栈,包括接口、IP地址、路由表和防火墙规则。
创建VNET jail的第一步是通过执行以下命令创建 bridge(4) :
xxxxxxxxxx# ifconfig bridge createbridge0创建网桥后,有必要将其连接到 em0 接口,并通过执行以下命令将两者都打开:
xxxxxxxxxx# ifconfig bridge0 addm em0 up# ifconfig em0 up要使此设置在重新启动后仍然有效,请在 /etc/rc.conf 中添加以下行:
xxxxxxxxxxdefaultrouter="192.168.1.1"cloned_interfaces="bridge0"ifconfig_bridge0="inet 192.168.1.150/24 addm em0 up"ifconfig_em0="up"有关桥接的更多信息,请参阅【34.8. 网络桥接】。
下一步是创建如上所述的jail。
可以使用【17.4. 经典Jail(厚Jail)】程序和【17.5. 瘦Jails】程序。唯一会改变的是 /etc/jail.conf 文件中的配置。
路径 /usr/local/jails/containers/vnet 将用作创建的jail的示例。
以下是VNET jail 的示例配置:
xxxxxxxxxxvnet { exec.consolelog = "/var/log/jail_console_${name}.log"; allow.raw_sockets; exec.clean; mount.devfs; devfs_ruleset = 5; path = "/usr/local/jails/containers/${name}"; host.hostname = "${name}"; vnet; vnet.interface = "${epair}b"; $id = "154"; ① $ip = "192.168.1.${id}/24"; $gateway = "192.168.1.1"; $bridge = "bridge0"; ② $epair = "epair${id}"; exec.prestart = "/sbin/ifconfig ${epair} create up"; exec.prestart += "/sbin/ifconfig ${epair}a up descr jail:${name}"; exec.prestart += "/sbin/ifconfig ${bridge} addm ${epair}a up"; exec.start += "/sbin/ifconfig ${epair}b ${ip} up"; exec.start += "/sbin/route add default ${gateway}"; exec.start += "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.poststop = "/sbin/ifconfig ${bridge} deletem ${epair}a"; exec.poststop += "/sbin/ifconfig ${epair}a destroy";}① 代表jail的IP,它必须是唯一的。 ② 指之前创建的网桥。
FreeBSD可以使用【12. Linux二进制兼容性】和 deboottrap(8) 在jail中运行Linux。Jails没有内核。它们在主机的内核上运行。因此,有必要在主机系统中启用Linux二进制兼容性。
要在启动时启用Linux ABI,请执行以下命令:
xxxxxxxxxx# sysrc linux_enable="YES"启用后,可以通过执行以下命令在不重新启动的情况下启动它:
xxxxxxxxxx# service linux start下一步将是创建如上所述的jail,例如在【17.5.1. 使用OpenZFS快照创建瘦Jail】中,但不执行配置。FreeBSD Linux Jail需要一个特定的配置,下面将详细介绍。
如上所述创建jail后,执行以下命令以执行jail所需的配置并启动它:
xxxxxxxxxx# 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:
xxxxxxxxxx# jexec -u root ubuntu在jail中,执行以下命令安装sysutils/deboottrap并准备Ubuntu环境:
xxxxxxxxxx# pkg install debootstrap# debootstrap jammy /compat/ubuntu当进程完成并且控制台上显示消息“Base system installed successful”时,有必要通过执行以下命令从主机系统停止jail:
xxxxxxxxxx# service jail onestop ubuntu然后在 /etc/jail.conf 中为Linux jail添加一个条目:
xubuntu { exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; allow.raw_sockets; exec.clean; mount.devfs; devfs_ruleset = 4; host.hostname = "${name}"; path = "/usr/local/jails/containers/${name}"; ip4.addr = 192.168.1.155; interface = em0; 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:
xxxxxxxxxx# service jail start ubuntu可以使用以下命令访问Ubuntu环境:
xxxxxxxxxx# jexec ubuntu chroot /compat/ubuntu /bin/bash
更多信息可以在【12. Linux二进制兼容性】一章中找到。
服务jail完全通过 /etc/rc.conf 或 sysrc(8) 配置。基础系统服务已准备就绪。它们包含一个配置行,可以启用网络或解除jail的其他限制。在jail中运行没有意义的基本系统服务被配置为不作为服务jail启动,即使在 /etc/rc.conf 中启用。此类服务的一些示例是希望在start-of-stop方法中挂载或卸载某些内容的服务,或者只配置路由、防火墙等。
第三方服务可能会也可能不会为jail服务。要检查服务是否已准备就绪,可以使用以下命令:
xxxxxxxxxx# grep _svcj_options /path/to/rc.d/servicename如果没有输出,则服务未准备好服务jail,或者不需要任何额外的权限,例如网络访问。
如果服务没有准备好服务jail,需要网络访问,可以通过在 /etc/rc.conf 中添加必要的配置来准备好:
xxxxxxxxxx# sysrc servicename_svcj_options=net_basic有关所有可能的 _svcj_options ,请参阅 rc.conf(5) 手册页。
要为给定的服务启用服务jail,需要停止该服务,并将 servicename_svcj 变量设置为 YES 。要将 syslogd(8) 放入服务jail,请使用以下命令序列:
xxxxxxxxxx# service syslogd stop# sysrc syslogd_svcj=YES# service syslogd start如果 servicename_svcj 变量被更改,则需要在更改之前停止服务。如果不停止,rc框架将无法检测到服务的正确状态,也无法执行所请求的操作。
服务jail仅通过 rc.conf(5)/sysrc(8) 和 service(8) 命令进行管理。jail实用程序,如【17.6. Jail管理】中描述的 jls(8) ,可用于调查该行动,但 jail(8) 命令不应用于管理它们。
一旦创建了jail,就可以执行许多操作,如启动、重新启动或删除jail、在其中安装软件等。本节将介绍主机对jail可以采取的不同行动。
要列出主机系统上运行的jails,可以使用命令 jls(8) :
xxxxxxxxxx# jls JID IP Address Hostname Path 1 192.168.250.70 classic /usr/local/jails/containers/classicjls(8) 支持 --libxo 参数,该参数通过 libxo(3) 库允许显示其他类型的格式,如JSON、HTML等。
例如,执行以下命令以获取JSON输出:
xxxxxxxxxx# jls --libxo=json{"__version": "2", "jail-information": {"jail": [{"jid":1,"ipv4":"192.168.250.70","hostname":"classic","path":"/usr/local/jails/containers/classic"}]}}service(8) 用于启动、重新启动或停止主机上的jail。
例如,要启动jail,请运行以下命令:
xxxxxxxxxx# service jail start jailname更改 start 参数以重新启动或停止对jail执行其他操作。
销毁jail并不像使用 service(8) 停止jail并删除监狱目录和 /etc/jail.conf 条目那么简单。
FreeBSD非常重视系统安全。因此,有些文件即使是root用户也无法删除。此功能称为文件标志。
第一步是停止所需的jail执行以下命令:
xxxxxxxxxx# service jail stop jailname第二步是通过执行以下命令,使用 chflags(1) 删除这些标志,其中 classic 是要删除的jail的名称:
xxxxxxxxxx# chflags -R 0 /usr/local/jails/containers/classic第三步是删除jail所在的目录:
xxxxxxxxxx# rm -rf /usr/local/jails/containers/classic最后,需要删除 /etc/jail.conf 或 jail.conf.d 中的jail条目。
pkg(8) 工具支持 -j 参数,以便处理安装在jail中的包。
例如,要在jail中安装 www/nginx-lite ,可以从主机执行下一个命令:
xxxxxxxxxx# pkg -j classic install nginx-lite有关在FreeBSD中使用软件包的更多信息,请参阅【4. 安装应用程序:软件包和Ports】。
虽然上面已经说过最好从主机系统管理jail,但可以使用 jexec(8) 进入jail。
通过从主机运行 jexec(8) 可以进入监狱:
xxxxxxxxxx# jexec -u root jailname当进入jail时,将显示 motd(5) 中配置的消息。
要从jail中的主机系统执行命令,可以使用 jexec(8) 。
例如,要停止jail内运行的服务,将执行以下命令:
xxxxxxxxxx# jexec -l jailname service nginx stop升级FreeBSD Jails可确保隔离环境保持安全、最新,并符合FreeBSD生态系统中可用的最新功能和改进。
Jails必须从主机操作系统更新。FreeBSD的默认行为是禁止在jail中使用 chflags(1) 。这将阻止某些文件的更新,因此从jail内部进行更新将失败。
要将jail更新到它正在运行的FreeBSD版本的最新补丁版本,请在主机上执行以下命令:
xxxxxxxxxx# freebsd-update -j classic fetch install# service jail restart classic要将jail升级到新的主要或次要版本,请首先按照【26.2.3. 执行主要和次要版本升级】中的说明升级主机系统。一旦主机升级并重新启动,jail就可以升级。
xxxxxxxxxx如果从一个版本升级到另一个版本,创建一个新的监狱比完全升级更容易。例如,要从13.1-RELEASE升级到13.2-RELEASE,请在主机上执行以下命令:
xxxxxxxxxx# 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 classicxxxxxxxxxx必须执行两次安装步骤。第一个升级内核,第二个升级其余组件。然后,如果是主要版本升级,请重新安装所有已安装的软件包,然后重新启动jail。这是必需的,因为在FreeBSD的主要版本之间升级时,ABI版本会发生变化。
来自主机:
xxxxxxxxxx# pkg -j jailname upgrade -f# service jail restart jailname由于使用NullFS的瘦Jail共享大部分系统目录,因此它们很容易更新。更新模板就足够了。这允许同时更新多个jail。
要将模板更新到它正在运行的FreeBSD版本的最新补丁版本,请在主机上执行以下命令:
xxxxxxxxxx# freebsd-update -b /usr/local/jails/templates/13.1-RELEASE-base/ fetch install# service jail restart要将模板升级到新的主要或次要版本,请首先按照【26.2.3. 执行主要和次要版本升级】中的说明升级主机系统。一旦主机升级并重新启动,就可以升级模板。
例如,要从13.1-RELEASE升级到13.2-RELEASE,请在主机上执行以下命令:
xxxxxxxxxx# 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
控制jail从主机系统使用的资源是系统管理员需要考虑的任务。
使用 rctl(8) 管理jail可以从主机系统使用的资源。
xxxxxxxxxx必须在/boot/loader.conf中启用kern.racct.enable可调参数。限制jail资源的语法如下:
xxxxxxxxxxrctl -a jail:<jailname>:resource:action=amount/percentage例如,要限制jail可以访问的最大RAM,请运行以下命令:
xxxxxxxxxx# rctl -a jail:classic:memoryuse:deny=2G为了使限制在主机系统重新启动时持续存在,有必要将规则添加到 /etc/rctl.conf 文件中,如下所示:
xxxxxxxxxxjail:classic:memoryuse:deny=2G/jail有关资源限制的更多信息,请参阅【16.14. 资源限制】部分的安全章节。
如前所述,每种类型的FreeBSD Jail都可以手动创建和配置,但FreeBSD也有第三方实用程序,使配置和管理更容易。
以下是不同FreeBSD Jail管理器的不完整列表:
表31. Jail管理器
| 名称 | 许可证 | 包 | 文档 |
|---|---|---|---|
| BastilleBSD | BSD-3 | sysutils/bastille | 文档 |
| pot | BSD-3 | sysutils/pot | 文档 |
| cbsd | BSD-3 | sysutils/cbsd | 文档 |
| AppJail | BSD-3 | sysutils/appjail, 开发版: sysutils/appjaildevel | 文档 |
| iocage | BSD-2 | sysutils/iocage | 文档 |
| ezjail | Beer Ware | sysutils/ezjail | 文档 |