第零章:介绍

当我第一次成为系统管理员时,操作系统安装至关重要。服务器的成本高达数万美元,而一个中型办公室只有一两台。初始安装是高级系统管理员自己执行的罕见事件,这是有充分理由的,因为每个人都忍受了这些决定五到十年。我们对磁盘进行了精简分区,以平衡性能和空间利用率。我们调整甚至重建了内核,为我们宝贵的应用程序囤积了每一块内存。我们今天所说的例行更新和升级是棘手、危险的事件,需要细致的计划、几次会议和数小时或数天的计划停机时间。

如今,操作系统安装就像打喷嚏一样普遍,种类也几乎一样多。虚拟化比任何其他技术都更彻底地改变了系统管理。我们自动部署虚拟系统以支持增加的负载,并在需要时自动销毁它们。我负责的操作系统安装数量之多,会让二十世纪的我感到震惊。

第零章:介绍虚拟化和 JailsJails 对比 Chroots什么是 JailsJail 安全文件和历史先决条件Jails 和 ZFSJail管理工具本书内容第1章,Jail 主机第2章,Jail要点第3章,Jail管理第4章,jail 文件系统第5章,包和升级第6章,空间优化第7章,活在jail中第8章,jail功能和控制第9章,网络第10章,极端jail第11章,资源限制和移除第12章,iocage奖金

虚拟化和 Jails

虚拟化(virtualization)将操作系统安装与底层硬件分离,允许您将操作系统实例堆叠在一起。直接安装在计算机上的操作系统实例称为主机。主机上运行的虚拟化软件为进一步的操作系统安装提供虚拟硬件,称为虚拟机(virtual machines)或客户机(guests)。

完全虚拟化创建了一个虚拟机,从BIOS或UEFI开始,用于操作系统安装。虚拟化系统提供键盘、鼠标和远程控制台(通常通过VNC或类似协议)。虚拟机获得一块磁盘空间,要么在主机的文件系统之上,要么传递到磁盘分区。主机内存的一个子集被预留给虚拟机。完全虚拟化允许您在一台主机上同时运行许多截然不同的操作系统。FreeBSD的全虚拟化服务器bhyve允许您在FreeBSD主机上运行从Linux到Microsoft Windows的任何东西。

轻量级虚拟化使用自己的用户区程序,但在主机的内核上运行。轻量级虚拟机没有私有磁盘,而是使用主机文件系统的一部分。主机提供任何网络连接。主机的内核指导轻量级虚拟机的内存、处理器时间和网络。同一主机上的轻量级虚拟机可以彼此共享文件系统。虽然轻量级虚拟机无法访问主机,但主机通常可以访问轻量级虚拟机。

FreeBSD的jails是开源Unix中第一个轻量级的虚拟化系统。自2000年推出以来,它们的能力不断增强。今天的jails可以运行自己的网络堆栈和数据包过滤器,拥有私有的ZFS数据集,除了运行不同的内核之外,可以做任何事情。现代FreeBSD内核支持从FreeBSD版本到FreeBSD 4的二进制接口,以及某些版本的Linux。这种兼容性是抛弃可怕的旧硬件,同时保持重要应用程序运行的好方法。

任何时候你看到“host”这个词,它都是指提供jail服务的操作系统安装。主机是操作系统堆栈的底层。“jail”一词指的是在主机上运行的轻量级虚拟机。

Jails 对比 Chroots

jails被称为“类固醇上的chroots(chroots on steroids)”。这并没有错,但也不完全正确。

Chroot(changed root)将进程锁定到文件系统的一个子集中,限制它可以访问的文件。Chroots限制了一个混乱或损坏的进程对主机造成的伤害程度。曾经,对服务器进行chroot以主动遏制入侵者是一种普遍推荐的做法。今天,这仍然是一种将潜在损害降至最低的简单方法,但并不被广泛推荐。

Chroot目录只包含chrooted程序所需的文件。程序需要shell吗?如果没有,不要将/bin/sh放在chroot中。主机上的其他程序、共享库和脚本也是如此。入侵一个经过适当chroot处理的小程序的入侵者将无法对其访问权限进行太多操作。一些服务器,如OpenSSH的sshd(8),将自己定位到一个空目录中,以彻底阻止潜在的入侵者。

虽然chroot限制了磁盘访问,但它并没有限制网络访问。chrooted程序可以访问主机的所有网络接口和IP地址。它与所有其他进程共享相同的进程和内存空间。特权分离和删除特权等安全工具可以提供帮助,但chrooted守护进程仍然可以访问一大堆不是文件系统的资源。

jails不共享这些资源。

什么是 Jails

jail是命名空间转换的集合。

什么?

Unix有许多不同的命名实体,每个实体都用于特定类型的应用程序。每个实体都有一个离散的(discrete)命名空间。进程ID是一个命名空间——每个PID在其中都是唯一的。文件系统是一个唯一的命名空间,每个文件路径在其中也是唯一的。连接到主机的IP地址在网络命名空间中是唯一的。用户名是唯一的。正如单个操作系统安装不能有两个PID 100一样,它也不能有两份名为/etc/passwd的文件,也不能将203.0.113.1附加到多个接口。您可以创建两个相同的用户名,但结局不会很好。

jail为每个名称空间创建了新的名称空间。

就像chroot一样,jail在主机的文件系统上有一个根目录。您可以将 /var/www1 指定为jail www1的根目录。jail内的进程认为 /var/www1 的内容在根目录中。虽然FreeBSD安装只能有一个 /etc/passwd 文件,但jailed的进程将 /var/www1/etc/passwd 视为 /etc/passwd 。主机知道文件系统中有许多passwd文件,但jail内的进程只感知自己的命名空间。

chroot风格的转换在网络上不起作用。jail被授予对主机网络堆栈的有限访问权限,并且只能使用主机允许的IP地址。主机可能将整个IP范围198.51.100.1到254连接到NIC,但如果只分配了一个jail 198.51.100.99,则在jail中运行 ifconfig em0 仅显示198.51.10.99。不过,主机可以使用jail的IP地址。如果主机系统管理员想从jail的IP发送ping,她可以劫持该IP。jail没有这样的选择。(您可以为jail分配一个专用网络堆栈,正如我们将在第9章中看到的那样,但即使这样,它也是从属于主机的。)

与网络堆栈类似,进程ID在主机上是唯一的。每个jail都会得到进程命名空间的一部分。被监禁的进程只能影响该jail进程命名空间内的其他进程。主机可以在任何jail的命名空间中创建、发送信号、终止和以其他方式操纵进程。

jail内的根用户与主机的根用户不同。jail的根帐户可以启动和停止该jail的进程,管理该jail的用户,甚至在主机允许的情况下在jail内挂载文件系统,但在jail外无能为力。

jail完全服从主人。即使入侵者访问了被监禁的系统,主机也保留了监督权限,可以进行干预。把它想象成一个真正的牢房。囚犯可以自由使用自己的床。监狱长(warden)有一面单向镜,可以照进牢房,随意改变。

大多数jail文档都假设你会在jail里安装一个完整的操作系统,但这不是必需的。你可以稀疏地填充一个jail,让最铁杆的chroot粉丝点头表示赞同。

Jail 安全

有些人认为jail不安全。其他人声称他们很安全。谁说得对?

同时正确和无用:两者兼而有之。

与所有安全问题一样,答案是“这取决于”。今天的系统管理员在一个一切都有安全风险的环境中进行实践。我们不能信任我们的硬件、操作系统或软件。每隔一段时间,就会有人想出一种方法来逃离虚拟机监控程序。开发人员打补丁,我们都继续前进。所以jail是不安全的。

解决方案不是依赖裸露的金属。一位FreeBSD安全专家在2005年就指出了英特尔处理器最近达到临界质量的一类问题。即使你的主CPU很坚固,其他硬件呢?如今,许多服务器组件都有自己的操作系统。您可以将串行控制台连接到硬盘驱动器上的正确引脚,并获得命令提示符。

没有什么是安全的。一切都很糟糕。

询问jail是否安全意味着询问你的申请、环境和风险。你应该为核导弹控制提供jail吗?不,你也不应该在公共网站上控制核导弹。你能在jail里提供客户网站吗?可能吧,除非你有一个又一个被供应商解雇的客户。考虑您、您的组织和客户面临的风险。

即使你完全信任jail提供的安全保障,它们也只是安全战略的一个组成部分。您当然需要权限管理和正确应用的加密。您需要数据包过滤器、代理以及基于主机和网络的入侵检测。真的,唯一可选择的组成部分是令人不安的身材高大、肌肉发达的人,他们有反社会人格障碍和尖刺棍棒。

如果你不相信你的应用程序的安全性,通过jail限制应用程序仍然是一种很好的方法,可以确保程序不会相互干扰,满足相互冲突的软件需求,并使攻击者的生活复杂化。

文件和历史

BSD在任何其他主流操作系统之前都支持轻量级虚拟化。最早的jail-type虚拟化代码出现在1975年7月18日UNIX v6快照和1979年5月7日UNIX v7快照之间的某个时间。Poul Henning Kamp于1998年创建了现代FreeBSD jails。自那以后,许多人对其进行了改进和扩展,构建了一个极其灵活的轻量级虚拟化平台。功能被添加、改进、再改进。

所有这些迭代开发都导致了文档问题。

虽然互联网以过时的教程而闻名,但jails尤其受到旧文档的困扰。20年前的邮件列表帖子会声称解决了你的问题,如果你运行的是FreeBSD 4.8或更早版本,那么给出的方法是有效的。如果你想管理jail中的System V IPC设施,文件声称这是不可能的,并且有一个sysctl和每个jail的设置。您可以在 /etc/rc.conf/etc/jail.conf 中找到配置jail的建议。整个jail管理工具王朝都有兴衰。

这本书忽略了这段历史。

我介绍现代jail管理,掩盖或直接跳过旧方法。有些人更喜欢旧的方法,虽然这没有什么错,但你也可以开始学习当前的方法。如果你正在研究一个问题,并发现与本书相矛盾的建议,请检查日期。这篇2005年被大量引用的文章可能是错误的。(如果你在2035年仍在使用这本书:对不起。)

先决条件

与我的大多数其他书不同,FreeBSD Mastery:Jails 不是一本介绍性的书。是的,它引入了jail——但有效地使用jail意味着要了解FreeBSD。你必须了解ZFS快照和克隆。你需要掌握devfs(5)和nullfs(5)。我不会解释pkg.conf或zfs send。

同样,如果你想使用jail的虚拟网络功能,你必须了解网络。你可以在没有这种专业知识的情况下运行基本的jail,但一旦你进入jail隔离(isolation)和防火墙,你就必须了解网桥和路由表。您想为您的jail设置DHCP服务器,还是使用PF将连接重定向到您的单个公共地址,再重定向到与环回绑定的数十个jail?真为你高兴!这不是我的问题。

您可以在FreeBSD手册和常见问题解答、其他在线资源或我写的其他书籍中了解更多关于所有这些主题的信息,如最新版的 Absolute FreeBSD(2018,No Starch Press)和FreeBSD Mastery书籍。

jail不需要特殊的硬件支持。不过,当你开始学习时,我建议在你的测试系统上为每个jail指定一个单独的IP地址。这不是严格必要的,但会简化学习过程。第9章和第11章讨论了在多个jail之间共享一个IP地址。

由于vnet虚拟网络支持,我特别关注FreeBSD 12及更高版本。这本书的大部分内容都适用于FreeBSD的早期版本,但如果你要安装一个新的jail主机,请直接安装到12或更高版本。

Jails 和 ZFS

ZFS有一大堆功能可以增强jails的力量,其中最主要的是克隆。克隆太棒了。克隆是强大的。未被监视的克隆可能会破坏您的系统。记住:克隆会生长

即使你和他们相处不多。

如果你通过克隆另一个监狱来部署一个监狱,克隆开始时使用零字节。对文件系统的每次更改都会增加克隆的大小。是否编辑 /etc/rc.conf ?克隆的大小会随着 rc.conf 的大小而增加。将jail升级到新的次要或主要版本?克隆为所有新二进制文件使用了足够的空间。测试数据库升级并搅动整个存储后端会将数据库大小添加到克隆大小中。日志会增加克隆的大小。

当你有三到四个监狱时,克隆增长并不是什么大问题。有500个jails,脚本化的freebsd更新升级可能会消耗你所有的磁盘扇区,并要求更多。克隆用户必须仔细监视磁盘空间。不要仅仅因为工具让它变得容易就盲目地搅动jail文件系统。不要在主要的FreeBSD版本之间升级克隆监狱:将FreeBSD 12升级到FreeBSD 13会消耗克隆所节省的任何空间。相反,为新的FreeBSD版本安装新的jail。

当存储池填满时,ZFS会发脾气。从满池中恢复是复杂的。使用ZFS的系统管理员应为溢出数据集保留每个池20%的空间,以获得明确但易于恢复的磁盘容量问题警告。将保留减少到15%并订购新磁盘比从完全满的池中恢复要容易得多。

使用克隆jail时,不建议预留空间。它们是完全强制性的。

Jail管理工具

每个jail管理系统都是一个附加工具。即使是基础系统的 /etc/jail.conf 也是一个附加工具。通过运行带有大量命令行参数的jail(8)来创建和销毁jail。jail(8)命令内置了对解析 jail.conf 和引导自己的命令行参数的支持,但其他工具也可以生成这些命令。

此外,每增加一个jail都会增加系统的复杂性。一个最小的标准jail有三个挂载点(//dev/dev/fd)。一打jails等于三十六个挂载点。根据使用的文件系统,这些可能都是单独的数据集或大量的目录。每个base jail至少有十几个挂载点。每个jail都有自己的packages和用户。

面对所有这些复杂性,jails需要管理工具。虽然我们将介绍FreeBSD的集成jail管理,但如果你打算有很多jails,可以考虑一个附加工具。

这本书使用了最新版本的iocage(https://github.com/iocage/)。 iocage高度灵活,是在单个主机上管理jail的最受欢迎的工具。它是用Python编写的,开发人员会对错误报告做出回应。作者将缺失特征的报道视为个人挑战;如果这本书说iocage不支持某个功能,请检查最新版本,看看这是否仍然正确。

Ezjail是最古老的jail管理工具之一。ezjail在当时非常流行,在FreeBSD的最后几个版本中还没有更新。我用了ezjail,我喜欢它,但遗憾的是它已经过时了。

BSDPloy(https://github.com/ployground/bsdploy)是基于Ploy基础设施构建的DevOps风格大规模jail部署的工具。它与Ansible和Fabric等其他工具集成。如果你说DevOps,考虑一下Ploy和BSDPloy。

CBSD(https://bsdstore.ru/)是一个主机控制面板,用于管理跨多个主机的FreeBSD虚拟化。它确实有jail。确实如此。它唱歌,它跳舞,它给你端咖啡。如果你没有像管理服务器那样管理它们,如果你想要bhyve和jail,看看CBSD。我没有报道CBSD,因为我还没有写一本bhyve书。

还有更多:Fubarnetes(在Rust中)、jailctl、jailadmin、iocell、pot等等。

无论你选择哪种jail管理系统,从中长期来看,你都必须了解该工具会采取什么行动。你需要了解jail的潜在机制。jail在设置方面可能很有效,但当它偏离正轨时,只有你的理解和故障排除才能恢复服务。

此外,您必须能够区分jail问题、FreeBSD问题和管理工具错误。因此,这本书可以手动和使用iocage执行所有jail配置。为了区分,我将使用基本系统工具管理的jail称为标准jail,而iocage管理的jail是iocage jails。请注意,iocage jail是完全标准的,您可以仅使用基本系统完美地模拟所有iocage功能,但在学习工具时,这是一个有用的区别。

创建和删除jail是问题中最小的部分。您还必须管理现有的jail。虽然创建虚拟化是为了将操作系统与硬件分离,但许多组织将其用作将问题进一步推向堆栈的一种方式,这样维护所有这些积垢就变成了别人的问题。虽然我完全支持将日常维护委托给其他人,但主机系统管理员对他们提供的jail负有共同责任。也许管理一个jailed的服务器是web开发人员的问题,但他的问题可能会升级为你的问题。主机管理员可以比jail所有者更简单地管理许多问题。利用你的工具简化每个人的生活,并告诉你的jail老板你会这样做。虽然花半个小时与同事谈判运营协议很烦人,但这比花几天时间解决多个系统管理员独立攻击一个问题而产生的微妙问题要好。

本书内容

本章为第0章

第1章,Jail 主机

介绍了如何配置基本FreeBSD安装以最好地支持jail。

第2章,Jail要点

将带您了解jail的核心概念。您将学习使用基本系统工具和iocage设置一个简单的jail。

第3章,Jail管理

教你如何调整、查看和管理jail。

第4章,jail 文件系统

讨论了jail文件系统管理的特定方面。

第5章,包和升级

介绍了在jail中执行这些标准系统管理员任务的不同方法。

第6章,空间优化

讨论了克隆和base jail等节省磁盘的技巧,以及它们如何改变软件管理。

第7章,活在jail中

涵盖了在jail里工作与进入整个系统的一些区别。

第8章,jail功能和控制

将带您了解一些使jail不仅仅是chroot的特殊功能,如私有System V IPC空间、挂载文件系统的能力、安全级别等。

第9章,网络

深入探讨了TCP/IP在jail中的工作原理。我们将讨论虚拟网络堆栈和网桥。

第10章,极端jail

展示了如何在jail中使用jail,甚至在jail中运行Linux。

第11章,资源限制和移除

讨论了防止jail消耗主机。或者,如何让jail比平时更容易接近你的主机。

第12章,iocage奖金

介绍了iocage提供的一些功能,使其成为其他基础系统jail的有力选择。

虽然jail的功能比我在一本书中所能涵盖的要多,但一旦你掌握了这里所涵盖的主题,你就能解决你在jail中的大部分挑战。