空jail有用途,只是用途不多。你几乎肯定想在你的jail上安装FreeBSD软件包。同样,未打补丁的FreeBSD安装也有其用途,但这些用途都是针对入侵者的。您必须在jail上安装安全更新!FreeBSD的打包和升级工具支持jails,iocage对包有特定的支持。
第五章:包和升级包pkg(8)
Iocage 包修补 Jails使用 freebsd-update
进行修补使用Iocage进行备份和修补升级 Jails使用 freebsd-update
升级使用Iocage升级
你会看到有很多方法来管理jail里的包。选择一种方法并坚持下去。不要在iocage包和基于主机的 pkg(8)
和基于jail的 pkg
之间来回切换。包管理工具可能略有不同,特别是如果jail运行的FreeBSD版本比主机旧。
使用 pkg(8)
从主机管理jail包与运行 jexec -l jailname pkg
不同。前者使用主机的包管理工具,而后者运行jail的包管理工具。
jail所有者可能希望在jail内使用标准的 pkg(8)
工具安装自己的软件包。这是完全合理的——毕竟,监狱有一个完整的FreeBSD用户区。仔细考虑是否希望特定用户安装软件包。记住,如果用户搞砸了,你会接到用户的电话。如果用户没有对其软件包应用安全更新,并且入侵者闯入jail,您将接到执法部门的电话。对于那些甚至不应该有shell访问权限的用户,更不用说他们自己的jail了,我用一个shell脚本替换了jail的 /usr/sbin/pkg ,该脚本打印指令,要求帮助台安装所有软件包,然后通过电子邮件警告我,我的特别朋友正在干预他不理解的事情。不过,如果用户有一定的能力,让他们像其他FreeBSD安装一样使用 pkg(8)
管理自己的软件包。
pkg(8)
jail是 pkg(8)
生态系统的一级公民。主机的包工具可以按名称识别正在运行的jail,并管理其安装的包。我通常建议从主机那里管理jail内的包,而不是在jail里。虽然基于主机的包管理使用主机的打包工具,但它将jail的包数据库存储在jail中,并使用jail的 pkg.conf 、证书等。这使得jail可以使用不同的存储库。
使用主机的 pkg(8)
管理jail的包需要 -j
标志和jail名称。此标志位于 pkg
之后,而不是子命令之后。下面,我告诉pkg在jail logdb上运行,并安装sudo软件包:
xxxxxxxxxx
# pkg -j logdb install sudo
第一次在主机上运行 pkg(8)
时,它会自动升级,安装存储库中可用的软件包数据库,并执行您要求的任何操作。在jail上运行主机的 pkg(8)
可以避免在jail中安装当前的pkg。pkg(8)
程序将检测主机和jail之间的版本差异,并发出警告。您可以放心地忽略这些警告。
除了 -j
和jail名称之外,从主机管理jail的包与在任何其他主机上管理包完全一样。
iocage将包管理集成到其命令行中。使用 iocage pkg
命令。给它指定jail的名称和要运行的 pkg(8)
命令。下面,我在监狱www1上安装了sudo:
xxxxxxxxxx
# iocage pkg www1 install sudo
iotage pkg
命令检查存储库的包数据库,如果需要,安装一个jail中的包数据库并安装sudo,就像我在主机上运行原始 pkg(8)
命令一样。只是语法略有不同。
为什么要使用 iocage pkg
而不是 pkg -j
?你的喜好。iocage的目标是成为一个完整的jail管理解决方案,并为iocage用户提供便利,仅此而已。
FreeBSD的二进制升级工具 freebsd-update(8)
支持jail。毕竟,jail只是安装在特定目录下的FreeBSD安装。虽然您需要对标准jail使用 freebsd-update
,但iocage提供了一个更简单的前端,并利用了ZFS快照。
freebsd-update
进行修补你不能在jail里可靠地使用 freebsd-update(8)
。这里的关键词是可靠的。我已经逃脱了jail升级的惩罚,但它不受支持,如果你把它变成一种常规做法,它最终会把尖牙伸进你的手臂。在主机上执行所有jail升级。
要更新或升级jail,freebsd-update(8)
必须知道jail中运行的FreeBSD版本和jail的base目录。在升级之前,一定要备份你的jail。如果升级失败,备份tarball或ZFS快照将为您免去痛苦。
修补或升级jail的要求与主机不同。您的jail需要不同的更新配置。
xxxxxxxxxx
# grep -v ^# /etc/freebsd-update.conf | grep -v ^$ > /etc/jail-update.conf
打开文件并开始编辑。你需要一台服务器和该服务器的KeyPrint,所以别管它们了。从组件行开始。jail没有内核,所以不要尝试更新它。大多数(不是全部)jail不包含系统源代码。您必须始终更新的唯一组件是world:
xxxxxxxxxx
# Components src world kernel
Components world
如果你愿意,你可以在jail里使用主机的入侵检测功能。
有些命令永远不应该在我的jail里运行,比如 pkg(8)
和 freebsd-update(8)
。我用shell脚本替换它们,提醒我不要使用它们。我也不关心 /etc/motd 等文件的更新。阻止freebsd-update
用 IgnorePaths
语句替换此类文件:
xxxxxxxxxx
IgnorePaths /usr/sbin/pkg /usr/sbin/freebsd-update /etc/motd
你需要在 /etc 中使用 MergeChanges
,但 /boot/device.hints 在jail中无关紧要。您可以修改 UpdateIfUnmodified
以适应您的配置。
freebsd-update(8)
命令检查内核,以确定它在哪个freebsd版本上运行,就像 uname -a
一样。jail在主机内核上运行,但jail的用户空间通常完全不同。在FreeBSD 13系统上运行的FreeBSD 12 jail将默认应用FreeBSD 13补丁。那太糟糕了。使用 freebsd-version(1)
来获取jail的当前补丁级别。
在这里,我的标准jail ldap1目前运行FreeBSD 11.1-RELEASE。我需要在其上安装当前的安全补丁。我正在主机上运行此补丁:
xxxxxxxxxx
# freebsd-update -f /etc/jail-update.conf -b /jail/ldap1 --currently-running `jexec -l ldap1 freebsd-version` fetch install
jail现在已经更新了二进制文件,正如 freebsd-version(1)
所证实的那样。
xxxxxxxxxx
# jexec -l ldap1 freebsd-version
11.1-RELEASE-p14
不过,当前运行的任何程序仍然是旧版本。最好重新启动整个jail。
xxxxxxxxxx
# service jail restart ldap1
你的jail现在升级了。
这是一个令人恼火的长命令行,但如果你的jail在一个以jail命名的目录中,那么它很容易编写脚本。这是我的脚本 jailpatch.sh 。它只需要一个参数,即要修补的jail的名称。
xxxxxxxxxx
freebsd-update -f /etc/jail-update.conf -b /jail/$1 --currently-running `jexec -l $1 freebsd-version` fetch install
service jail restart $1
运行此循环以修补并重新启动所有jail。
勇敢的人可以在脚本中间添加一个 pkg -j $1 upgrade -y
。
iocage的快照功能简化了升级前的备份。iocage snapshot
命令用于拍摄快照。为其指定jail名称,然后使用 -n
提供快照名称。在这里,我拍摄了jail www1的快照,并将其命名为“install”。如果你没有提供快照名称,iocage会根据当前日期和时间创建一个快照。
xxxxxxxxxx
# iocage snapshot -n install www1
使用iocage快照列表查看所有快照。添加jail名称。与大多数 iocage
命令一样,您可以使用 -h
选项来摆脱表格式和/或使用 -s
对列进行排序:
xxxxxxxxxx
# iocage snaplist www1
+--------------+-----------------------+-------+------+
| NAME | CREATED | RSIZE | USED |
+==============+=======================+=======+======+
| install | Thu Sep 20 17:34 2018 | 92K | 0 |
+--------------+-----------------------+-------+------+
| install/root | Thu Sep 20 17:36 2018 | 680M | 0 |
+--------------+-----------------------+-------+------+
在更新jail之前,一定要拍一张快照。
iocage使用 iocage update
命令简化了jail补丁。给一个参数,要修补的jail的名字:
xxxxxxxxxx
# iocage update www1
* Updating www1 to the latest patch level...
您将看到常见的freebsd-update消息。
如果升级出现严重错误,您可以使用 iocage rollback
命令还原升级。使用 -n
指定快照名称,然后指定jail名称:
xxxxxxxxxx
# iocage rollback -n install www1
This will destroy ALL data created including ALL snapshots taken after the snapshot install
Are you sure? [y/N]: y
Rolled back to: iocage/iocage/jails/www1
现在,当你的疼痛耐受性更高时,你可以再次尝试patch。
使用 iocage snapremove
删除快照。使用 -n
指定快照名称,然后指定jail名称。在几次成功升级后,安装时快照将永远不会被使用,因此您可以将其丢弃。
xxxxxxxxxx
# iocage snapremove -n install www1
这个特殊的jail运行FreeBSD 9.3。我真的不想修补它。我想将它升级到FreeBSD的支持版本。让我们讨论一下升级。
得益于 freebsd-update(8)
,在FreeBSD的主要(12.0到13.0)或次要(12.0至12.1)版本之间升级主机比以前容易得多。即便如此,如果你有一个自动化系统,比如Ansible或Puppet,使部署变得简单,我建议在新的FreeBSD版本上安装新的jail,而不是升级。自动化使服务器安装比升级更快、更安全。对于iocage来说尤其如此,因为默认的iocage jail是ZFS克隆,从12.2升级到13.0会大大增加磁盘空间的使用。
无论你如何升级你的jail,在开始之前一定要做好备份。
freebsd-update
升级修补jail的一切都适用于升级jail。您需要相同的jail特定 freebsd-update.conf
来升级jail。您必须向freebsd-update提供 jail的当前的FreeBSD版本和根目录。不过,一旦你设置好更新jail,升级也没什么不同。
jail ldap1运行FreeBSD 11.1补丁级别的东西。我想将其升级到完全修补的11.2。使用 -r
指定目标版本,并给出 upgrade
子命令:
xxxxxxxxxx
# freebsd-update -f /etc/jail-update.conf -b /jail/ldap1 --currently-running `jexec -l ldap1 freebsd-version` -r 11.2-RELEASE upgrade
系统会要求您确认哪些组件已安装,哪些未安装。检查系统并下载补丁后,您将看到要更新、添加和删除的文件列表。所有这些完成后,您需要将更新作为第二个命令安装:
xxxxxxxxxx
# freebsd-update -f /etc/jail-update.conf -b /jail/ldap1/ --currently-running `jexec-l ldap1 freebsd-version` -r 11.2-RELEASE install
Kernel updates have been installed. Please reboot and run "/usr/sbin/freebsd-update install" again to finish installing updates.
freebsd-update
修补了jail内核文件的副本,这很好,但这无关紧要。jail主机总是运行与任何jail相同或更新的FreeBSD。点击向上箭头重复该命令并安装新的用户区。
这是FreeBSD的新版本,所以你真的应该重新安装所有的软件包。使用 -f
标志强制重新安装,即使软件似乎没有更改:
xxxxxxxxxx
# pkg -j ldap1 upgrade -fy
现在重启jail:
xxxxxxxxxx
# service jail restart ldap1
与修补程序一样,这些升级非常适合脚本编写。此脚本接受一个参数,即要升级的jail,并将其升级到FreeBSD 11.2。当我升级一堆jail时,我会编辑脚本以更改版本号。你可以将FreeBSD版本作为脚本的参数,但这意味着命令行更长,我不会介意的。
xxxxxxxxxx
freebsd-update -f /etc/jail-update.conf -b /jail/$1 --currently-running `jexec -l $1 freebsd-version` -r 11.2-RELEASE upgrade
freebsd-update -f /etc/jail-update.conf -b /jail/$1 --currently-running `jexec -l $1 freebsd-version` -r 11.2-RELEASE install
pkg -j $1 upgrade -fy
service jail restart $1
如果您要跨主要版本进行升级,系统还会提示您合并 /etc/ 。
您可以将 freebsd-update(8)
与 iocage jails一起使用,但iocage在 iocage upgrade
命令中吸收了大量命令行。将jail的名称作为一个参数,并使用 -r
指定所需的升级目标。我的jail www1运行的是FreeBSD 9.3,我想将其升级到最新的FreeBSD 10:
xxxxxxxxxx
# iocage upgrade www1 -r 10.4-RELEASE
您将看到熟悉的“检查系统”和“准备下载文件”消息。这个特殊的升级需要35266个补丁和50864个文件,所以现在是检查Mastodon提要的好时机。
一旦所有这些完成,你就可以将 /etc 更改合并到你的jail中。iocage会自动更新您未更改的所有文件。iocage会自动处理完成升级所需的freebsd-update的重复运行。
跨主要版本升级iocage jail是不明智的。除非另有说明,否则iocage会将jail创建为ZFS克隆。ZFS克隆仅使用的磁盘空间量等于从中克隆的快照与磁盘上的当前文件之间的差异。即使是小版本的升级也会占用半GB的磁盘,而大版本的修订会占用完整FreeBSD安装的空间。
xxxxxxxxxx
# zfs list -rt snap iocage/iocage/jails/www1
NAME USED AVAIL REFER MOUNTPOINT
iocage/iocage/jails/www1@install 56K - 92K -
iocage/iocage/jails/www1/root@install 0 - 680M -
将这个jail从9.3升级到10.4使用了额外的680 MB磁盘空间。这不是一个杀手,但与完整的10.4安装相比,它肯定不会节省空间。
幸运的是,您可以在升级过程中以节省磁盘的方式配置jail。我们将在下一章中看到其中的一些。