虚拟化是伟大的,但即使有嵌套的虚拟机层,最终你也会遇到安装在物理硬件上的操作系统。是的,现代系统的许多组件都运行自己的内部操作系统,但我们称之为BIOS、固件和UEFI,并拼命忽略它们。安装和配置您的主机,使其能够最容易地运行jail,这将为您节省大量以后的麻烦。
破解主机的入侵者可以控制该主机上运行的所有jail。从一开始就计划在主机上运行零个不必要的服务。如果不是绝对需要它来管理主机,那就把它关进jail。jail主机需要SSH和计时,所以在不暴露于互联网的网络接口上运行它们。Web、数据库和应用服务器?不可信的动物,他们很多。把他们都关进jail。拒绝潜在的入侵者,即使是破坏宿主的最小机会。 如果你想在jail中使用虚拟网络,我强烈建议使用FreeBSD 12或更高版本。你可以用FreeBSD的早期版本进行虚拟网络,但它相当可怕,要么需要编译一个自定义内核,要么需要将一堆虚拟接口粘在一起。这是可以做到的,但FreeBSD 12中的vnet极大地简化和稳定了虚拟网络。
我们将从存储开始,接着进行网络连接,然后查看主机服务和内核的详细配置。
jail都是关于存储的。是的,他们需要流程管理和网络以及所有这些,但这些都可以重新配置,而无需剥离所有内容并重新开始。如果可能的话,将您的jail数据与主机数据分开。在具有多个硬盘的主机上,将几个硬盘专用于您的操作系统,其余的专用于jail。如果在小型操作系统安装中使用多个数TB的驱动器感觉浪费,请购买一块带有几个直接连接的高耐久性闪存驱动器的主板。无论哪种方式,都可以使用 geom_mirror(8)
或ZFS镜像操作系统驱动器。让你的jail存储也变成冗余的。
你的文件系统需要支持标准的Unix文件系统功能,如所有者和权限等。不要试图在FAT文件系统上构建jail,除非你想用新的有趣的失败场景来娱乐自己。使用UFS或ZFS。如果你的主机可以支持ZFS,我建议你选择它。Jails出现在UFS是FreeBSD中唯一严肃的文件系统选项的时候,但ZFS有额外的功能来放大和扩展Jails,比如完全将数据集委托给jail。
两个似乎是jail的明显选择的文件系统是nullfs和unionfs。我们将大量使用nullfs,但不止一位FreeBSD开发人员将unionfs描述为“一篮子恐慌(a basket of panic)”。手册页警告人们不要使用它。有些人无视这一警告并报告了出色的结果,而另一些人则遭受了无尽的痛苦。如果你使用unionfs并喜欢它,那对你来说是件好事——但这本书没有建议,我也不会推荐。
NFS或AFS等网络文件系统呢?任何网络文件系统都会带来挑战,从通常的性能问题到只影响您的精确配置的奇怪边缘情况,以及一个孤独的系统管理员的环境,他在1994年向Usenet发布了一份绝望的详细求助请求,但没有得到答复,也再也没有消息。如果你愿意在最不方便的时候处理这些问题,你可以让jail在网络文件系统上工作。NFSv4所需的nfsuserd(8)
守护进程与jail不能很好地互操作,因此您可能应该使用NFSv3或更早的版本。
记住,网络文件系统与网络磁盘不同。用于将磁盘连接到主机的机制无关紧要。光纤通道和iSCSI不是网络文件系统,而是网络磁盘。他们很好。没有人利用光纤通道越狱。
您将看到一些文档,声明您应该运行 lsvfs(1)
来查看内核支持的文件系统,并且只使用标记有jail标志的文件系统。这表示可以从jail内安全管理的文件系统,而不是主机可以用来为jail提供存储的文件系统。我们将在第8章讨论在jail内管理文件系统。
这本书中手工制作的标准jail的例子都放在 /jail 文件系统中。理想情况下,这是一组与操作系统不同的物理介质。它可以使用UFS或ZFS。根据定义,在UFS上运行的任何示例都是标准jail,并出现在 /jail 中。
iocage仅适用于ZFS。我将我的池称为iocage专用池,挂载在 /iocage 。根据定义,/iocage 下的任何示例都使用iocage。
Python使用 fdescfs(5)
来提高性能。如果您正在使用iocage,请在主机上使用 /etc/fstab 条目启用fdescfs:
xxxxxxxxxx
fdescfs /dev/fd fdescfs rw 0 0
每个jail可以有几个挂载点。预计会有一大堆文件系统表文件,如 /etc/fstab 。
评论一切都很好。要么记录下来,要么后悔。
TCP/IP的规则声明一次只能有一个进程监听IP地址和端口的组合。您可以将jail附加到主机上的任何IP地址和端口,但如果主机上的进程或另一个jail已经附加到该端口和地址,则jail将无法正常工作。最明显的例子是SSH服务器 sshd(8)
。SSH通常连接到主机上所有IP地址的端口22。如果您的主机垄断了所有jail地址上的端口22,则没有一个jail可以在端口22上使用SSH。它们必须使用不同的端口,这增加了复杂性。“主机使用端口22,而jail使用端口23”是那种让人们密谋报复系统管理员的说法。
当您第一次了解jail时,请使用具有单个网络接口但具有多个IP地址的简单主机。为主机专门分配一个IP。将主机的所有服务绑定到该IP。一旦你了解了jail的基本知识,你就可以在一个生产主机上开始,该主机具有连接到不同网络、VLAN和所有有趣的东西的多个接口,但要保持初始测试环境的简单。我们将在第9章讨论更复杂的网络设置。
如果你没有多个IP地址的奢侈,你必须跟踪哪些jail中的守护进程绑定到哪些IP地址和端口,可能是在加密签名的巨型电子表格的多个分布式副本上。这会告诉用户“将61000添加到所有端口号中,以找到jail 61的服务。是的,如61022、61443等。”
虽然jail通常依赖于主机的网络堆栈,但FreeBSD的 vnet(9)
虚拟网络堆栈允许您为每个jail分配一个虚拟网络堆栈和自己的路由表。每个jail都可以有一个完全不同的路由表。我们将在第9章讨论这个问题。
通过尽可能减少主机的网络配置文件来保护您的主机。使用 sockstat(1)
或 netstat(1)
标识开放端口。记住,您在主机上运行的任何服务也是入侵者的潜在攻击向量。新的FreeBSD安装默认有三个守护进程监听网络:syslogd(8)
、ntpd(8)
和 sshd(8)
。
FreeBSD的日志记录器 syslogd(8)
主动绑定到每个可用IP上的UDP端口514,以便它可以向其他主机发送日志消息。如果您不需要远程日志记录,或者您的远程日志记录解决方案不使用syslogd(8),请使用-ss禁用syslogd的网络访问:(这可能是FreeBSD 13的默认设置。)
xxxxxxxxxx
# sysrc syslogd_flags="-ss"
安全敏感组织几乎肯定需要远程日志记录。使用-b标志将syslogd锁定到主机的管理IP:
xxxxxxxxxx
# sysrc syslogd_flags="-b 192.0.2.2"
这释放了jail其他地址上的syslogd端口。
所有的jaio都占用了host的时间。FreeBSD的计时器守护进程 ntpd(8)
监听所有可用的IP地址。使用stock ntpd无法限制这一点——您可以将ntpd绑定到单个接口,但不能绑定到单个地址。在这种情况下,我会告诉你不要担心,运行ntpd。
Jails不能改变内核的时间。即使你在jail里运行ntpd,它实际上也无法改变主机时间。任何在jail中运行的程序,只要连接到UDP端口123或从UDP端口123连接,就像ntpd一样,几乎肯定会试图偷偷通过数据包过滤器。没有理由让这个小把戏变得更容易。让主机独占UDP端口123。
如果您仍然担心,请禁用基本系统的 ntpd(8)
并安装OpenNTPd。OpenNTPd有特权分离作为奖励。
每个人都使用 sshd(8)
管理Unix主机。你的用户会想通过SSH进入他们的jail,强迫他们使用备用端口会惹恼他们。如果您的所有jail都使用相同的IP,这将无济于事,但在我们的理想情况下,每个jail都有自己的IP世界,您将把主机的SSH守护进程限制为单个IP。使用 /etc/ssh/sshd_config 中的 ListenAddress
关键字来限制OpenSSH的 sshd(8)
使用哪个地址。
xxxxxxxxxx
ListenAddress 192.0.2.2
理想情况下,此地址只能从您的管理网络访问。
第9章将带你深入jail网络,但这应该让你开始。
FreeBSD内置了启动和停止jail的脚本。脚本读取配置文件 /etc/jail.conf 并将结果馈送到 jail(8)
。虽然可以使用 jail
命令在命令行上完全配置、启动和停止jail,正如我们将在第3章中看到的那样,但随着jail数量的增加,这些命令变得乏味。您最好使用配置文件并通过 service(8)
启用jail管理。
xxxxxxxxxx
# service jail enable
iocage使用存储在每个单独jail中的配置文件。当iocage启动时,它会读取自己的配置文件,并启动 jail(8)
来创建和启动您标记为自动启动的所有jail。告诉FreeBSD在启动时启动iocage,并启用服务iocage。
您可以同时使用这两个jail管理系统。jail.conf 中配置的jail与iocage管理的jail本身并不冲突。毕竟,这两个系统都只是jail的前端。它们可能存在管理冲突,例如两者都试图绑定到相同的IP地址和端口,但这两个系统是独立工作的。iocage可以管理数百种最常见的jail类型,让你可以痛苦地维护几座溃烂的手工制作的工匠(artisan) jail,这些jail需要自己的异国情调(exotic weirdness)。
首先,iocage需要ZFS。如果你没有ZFS,不要尝试使用iocage。使用 pkg search iocage
查找当前的iocage包,或从github获取最新版本。不过,一旦你做到了这一点,iocage就需要特定的区域设置。将以下内容添加到 $HOME/.login.conf 中:
xxxxxxxxxx
me:\
:charset=UTF-8:\
:lang=en_US.UTF-8:\
:setenv=LC_COLLATE=C:
注销并重新登录以激活这些区域设置。
第一次运行任何iocage命令时,它会自动在根池上创建iocage数据集。如果你有一个单独的iocage jail池,在iocage spams你的根池之前告诉它。使用 iocage activate
命令将iocage指向您的池。在这里,我将 iocage 池奉献给iocage jails:
xxxxxxxxxx
# iocage activate iocage
ZFS池 iocage 成功激活。
iocage文件被挂载到 /poolname/iocage 。如果你使用默认安装和默认根池,就像没有人做的那样,所有iocage文件都会出现在 /zroot/iocage 下。使用名为iocage的池,iocage文件将放在 /iocage/iocage 下。为了简洁起见,并避免在本书中散布像 $POOL/iocage 这样的可怕文件名,所有示例都使用 /iocage 。
如果你错误地告诉iocage将自己设置在错误的池上,请使用 iocage clean -a
销毁所有这些数据集。对于旧版本的iocage,您必须使用 zfs destroy -r
命令来销毁包含iocage文件的任何数据集。
第一次运行iocage时,它会为downloads、jails、templates和所有其他iocage函数创建数据集。如果你提前创建了你的第一个jail,iocage会自动提示你选择一个版本,下载它,并为你设置jail。或者,您可以运行 iocage list
来显示您所有的iocage jail,而您还没有。我们将在本书中解释所有这些数据集。
iocage具有实验性的颜色输出。我在这里不使用颜色,因为这本书将以黑白打印,但如果你想在终端中使用颜色,请将环境变量 IOCAGE_COLOR
设置为 TRUE
。
重新启动主机,以验证所有内容是否如您所想的那样安全,以及主机是否按预期重新启动。一旦你确认了一切,你就可以开始添加jail了。