在用户模式 Linux 下运行网络服务,第一部分

作者:Mick Bauer

在我 2006 年 5 月的 Paranoid Penguin 专栏中,我详细阐述了 Debian 3.1 对虚拟化环境的出色支持,包括用户模式 Linux。在同一期中,Matthew Hoskins 在文章《用户模式 Linux》中提供了一个快速简便的方法,使用预构建的 UML 内核和根文件系统镜像来试用用户模式 Linux。

这些文章是否激起了您对更全面、更注重安全性的 UML 使用方法的兴趣? 如果是这样,您很幸运;在接下来的几篇专栏文章中,我们将深入探讨用户模式 Linux 的体验,并涵盖创建您自己的用于网络服务的用户模式 Linux 容器的每个步骤(包括每个命令)。

目标

那么,我们为什么要这样做,我们希望实现什么目标? 正如我之前在这个专栏中说过的,虚拟化类似于 chroot(更改根目录)jail 的概念。 它将进程或守护程序封装到它所驻留的操作系统环境的子集中,这样,如果攻击者成功入侵该进程或守护程序,他们就更难接触到底层环境。

chrooting 将进程限制在宿主系统真实文件系统的子集中,而虚拟化将进程限制在宿主(真实)机器内运行的完整虚拟机中。 这包括完全虚拟化的硬盘、内存和内核,甚至包括虚拟化的系统设备,例如网卡和声卡。 在用户模式 Linux 的情况下,这是通过将访客(虚拟)内核作为宿主(真实)内核中的用户空间进程运行来实现的。

由于访客内核和宿主内核都是 Linux 内核,因此用户模式 Linux 中的虚拟化快速而高效。 而且,由于访客内核 需要在宿主内核下以 root 身份运行,即使攻击者入侵了访客系统上的某些守护程序 将其权限提升为 root(在访客系统上)并且 以某种方式设法获得对底层宿主系统的 shell 访问权限,他们也只能获得对该宿主系统的非特权访问权限。

这并不是说不可能获得对宿主系统的 root 访问权限。 如果攻击者真的获得了宿主系统的 shell 访问权限,他们或许能够通过宿主内核中的某些本地权限提升漏洞或宿主上的某些用户空间程序来提升其权限。 (请记住:在 任何 网络系统上,没有哪个漏洞是严格意义上的本地漏洞!) 然而,这 确实 意味着,攻击者更难达到能够利用此类漏洞的地步,尤其是在访客(虚拟)系统上也不存在该漏洞的情况下。

这就引出了我们的设计目标。 访客机器在已安装软件方面应尽可能精简——既要最大限度地减少资源利用率,又要最大限度地减少其被入侵的可能性(其攻击面)。 例如,如果访客机器要充当 DNS 服务器,它应该具有基本的网络支持、BIND(或其他一些 DNS 服务器软件包)以及极少量的其他内容。 没有 X Window 系统,也没有 Apache——没有其他与 DNS 服务没有直接关系的东西。

如果您真的非常谨慎,您甚至可以跳过 Secure Shell 守护程序,而是通过虚拟串行控制台管理系统。 (尽管仅允许来自授权 IP 地址(例如宿主系统的 IP 地址)的 SSH 可能是更合理的折衷方案。) 您也可以在 SELinux 下运行用户模式 Linux;但是,这超出了本系列文章的范围。

如果单个堡垒服务器要托管多个网络服务——例如 Apache 和 BIND——您可以在同一宿主上运行两个不同的访客系统:一个仅包含 Apache 及其依赖软件包,另一个仅包含 BIND 等。 这样,BIND 中的漏洞就不会直接导致网站被篡改。 反之,编码不良的 Web 应用程序也不一定会导致 DNS 篡改。

总而言之,我们的两个设计原则是:每个主要网络服务运行一个虚拟机,并使每个虚拟机尽可能精简和安全。 最终结果(希望如此)将是一个高度隔离的堡垒服务器,在攻击者和完全 root 入侵之间尽可能多地设置防御抽象层。

在本系列文章的剩余部分中,我将使用运行 BIND 的单个访客系统为例。 访客系统和宿主系统都基于 Debian 3.1,因为 Debian 非常受 UML 访客的欢迎(它易于进行精简安装——这是它与 Slackware 共有的一个特点)。 然而,以下大部分内容也适用于宿主和访客上的其他 Linux 发行版。

我们的任务是

  1. 构建针对托管用户模式 Linux 访客优化的宿主内核。

  2. 构建一个或多个访客内核,以便在宿主之上运行。

  3. 获取并自定义预构建的根文件系统,供我们的访客使用。

  4. 运行、配置和加固我们的访客系统,以提供安全的 DNS 服务。

准备宿主

首先,您需要确保您的宿主系统上安装了正确的内核类型。 您很可能需要编译一个新的内核。

一方面,某些 Linux 发行版已经将用户模式 Linux 编译到其默认内核中。 另一方面,您选择的发行版可能也可能没有编译 skas(独立的内核地址空间)补丁。 事实上,您的默认内核不太可能具有 skas 支持。 虽然 Linux 内核源代码自 2.6.9 版本以来就包含了 UML 支持,但 skas 补丁仍然是单独维护的(Linus 抵制将其纳入)。

skas 补丁非常重要。 它通过在与访客系统的其他进程(就像宿主内核一样)独立的地址空间中运行访客系统的内核,从而大大提高了 UML 的性能和安全性。 用户模式 Linux 网站 SourceForge 上的 skas 页面提供了更详细的解释,说明您为什么需要 skas(请参阅在线资源)。

保持内核和访客的清晰

在用户模式 Linux、VMware 和其他虚拟化系统的上下文中,我们以非常具体的方式使用“宿主”和“访客”这两个词。 您的宿主是运行虚拟化环境的系统——也就是说,它充当一个或多个虚拟机的宿主。 访客是在宿主之上运行的虚拟机实例。

因此,当我们谈到宿主内核和访客内核时,请记住访客内核在宿主内核之上运行。 在用户模式 Linux 中,您的宿主内核是普通的 Linux 内核,针对您的特定硬件平台(Intel x86、IBM PowerPC 等)编译,并编译了用户模式 Linux 功能(包括可选的 skas 补丁)。

另一方面,您的访客内核必须编译为在虚拟硬件上运行:um 架构。 除此之外,它 需要启用 skas 补丁或用户模式 Linux 支持。 除非您想在其之上运行其他访客内核。 在访客内部运行访客是可能的(这称为嵌套),但这远远超出了本文的范围。

每个 UML 虚拟机实例都包含一个访客内核、一个访客根文件系统和一个 COW(写时复制)文件。 根文件系统是一个磁盘镜像文件;它包含虚拟机中的每个文件,内核本身除外。 当您执行访客内核时,根文件系统文件的挂载方式与您挂载任何其他磁盘镜像(例如 CD ISO 文件)的方式完全相同。 就像 CD-ROM 一样,它以只读模式使用。 您在 UML 会话过程中对虚拟文件系统所做的任何更改,包括新文件和文件删除,都存储在 COW 文件中。

由于 COW 的魔力,因此可以通过为每个实例定义唯一的 COW 文件,多次运行相同的访客内核和根文件系统组合。

要获取内核源代码,您最好的选择可能是简单地安装您的 Linux 发行版的 kernel-source 软件包。 但是请注意,您的发行版提供的内核版本为 2.6.9 或更高版本,因为 UML 支持从 2.6.9 开始包含,并且之前的 UML 补丁存在安全漏洞。

由于 Debian 3.1 仍然使用内核版本 2.6.8,我决定不使用官方的 Debian 内核软件包,而是从 kernel.org 下载了 2.6.17 内核。 但是,我确实安装了 kernel-package 软件包,该软件包提供了从官方内核源代码生成 Debian 软件包的工具。

除了内核源代码,您还需要 skas 补丁,最新版本可在 Blaisorblade 的网站上找到(请参阅“资源”)。 请务必下载与您要修补的内核源代码对应的补丁版本。

在我的 Debian 宿主机上,我将官方源代码解压缩到 /usr/src/linux-2.6.17.3,将源代码目录重命名为 /usr/src/linux-2.6.17.3-host,并将 skas 补丁 tarball (skas-2.6.17-rc5-v9-pre9.patch.bz2) 复制到 /usr/src。 然后,我将目录 /usr/src/linux-2.6.17.3-host 的所有权更改为非 root 帐户。 (坚持除非真正需要,否则永远不要以 root 身份的原则,我们将以非特权用户身份完成大部分内核构建。)

以下是我以 root 身份执行的命令

host:/usr/src/# tar -xjvf ./linux-2.6.17.3.tar.bz
host:/usr/src/# mv ./linux-2.6.17.3 ./linux-2.6.17.3-host
host:/usr/src/# chown mick ./linux-2.6.17.3
host:/usr/src/# su - mick

为了应用 skas 补丁,然后我以我的非 root 用户身份导航到 /usr/src/linux-2.6.17.3-host 并运行了以下命令

host:/usr/src/linux-2.6.17.3-host$ bunzip2 -c
 ↪../skas-2.6.17-rc5-v9 -pre9.patch.bz2 | patch -p1

接下来,从同一目录中,我发出命令make menuconfig。 在为用户模式 Linux 设置内核配置时,默认设置通常就可以,尽管您应该确保配置与您的宿主硬件匹配。 此外,仔细检查以下设置可能是明智之举

  • 在“处理器类型和特性”下,确保启用 /proc/mm。

  • 在“网络选项”下,确保启用“IP:隧道”和“802.1d 以太网桥接”。 如果您打算使用 iptables 限制访客系统的行为,您可能还需要检查“网络数据包过滤”部分,以确保已设置“核心 Netfilter 配置”、“IP:Netfilter 配置”和“桥接 IP/ARP 数据包过滤”。

  • 在“网络设备支持”下,启用“通用 TUN/TAP 设备驱动程序支持”。

  • 并且,务必将系统根分区格式化的文件系统(例如,ext3 或 ReiserFS)硬编译(编译到内核中,而不是作为模块)。

从那时起,该过程与任何其他内核构建相同:发出命令make bzImagemake modules;。 然后,成为 root 并发出命令make modules_install, make installmake modules。 (或者对于 Debian,使用make-kpkg命令来实现相同的目的,并运行dpkg来安装生成的内核软件包。)

安装新的宿主内核后,重新启动系统。 您的宿主系统现在能够运行用户模式 Linux 访客系统。

创建访客内核

好的,我们已经具备了 UML 宿主能力,但我们仍然需要一个访客内核来运行。 此过程比宿主内核构建稍微简单一些,因为我们不需要 skas 补丁。

首先,导航回 Linux 内核源代码 tarball 所在的目录,然后再次解压缩它。 还记得我们重命名解压缩后的源代码目录吗? 这是为了我们可以再次解压缩内核 tarball。 我们需要在单独的源代码树中构建宿主内核和访客内核。

因此,在我的 Debian 测试系统上,我将源代码 tarball 解压缩到 /usr/src/linux-2.6.17.3,这次将其重命名为 /usr/src/linux-2.6.17.3-guest。 同样,将此目录的所有权更改为非特权用户,并将您的工作目录更改为它。

同样,此时我们可以跳过应用 skas 补丁的步骤。 因为我们将为特殊的 um(用户模式 Linux)架构而不是像 x86 这样的真实架构编译我们的内核,所以我建议您使用以下三个命令准备您的源代码树

host:/usr/src/linux-2.6.17.3-guest$ make mrproper ARCH=um
host:/usr/src/linux-2.6.17.3-guest$ make defconfig ARCH=um
host:/usr/src/linux-2.6.17.3-guest$ make menuconfig ARCH=um

命令make mrproper清除源代码树中的任何配置和目标文件;make defconfig生成适合 um 架构的全新默认配置文件;以及make menuconfig,当然,让您有机会微调此配置文件。

特别注意以下几点

  • 如果您跳过可加载内核模块支持并将所有内容硬编译到内核中,生活将会更轻松。 如果您真的想要内核模块,请参阅用户模式 Linux HOWTO,第 2.2 节(请参阅“资源”)。

  • 在“处理器类型和特性”下,仔细检查您的系统架构是否设置为 um(用户模式 Linux),并确保启用 /proc/mm。

  • 在“网络选项”下,确保启用“IP:隧道”和“802.1d 以太网桥接”。

  • 在“网络设备支持”下,启用“通用 TUN/TAP 设备驱动程序支持”。

  • 禁用尽可能多的专用硬件内核模块;此内核将在虚拟化硬件上运行,因此您不需要对无线 LAN 硬件、晦涩的并行端口设备等的支持。

保存新的配置文件后,您可以使用以下命令编译内核(无需 先成为 root 用户;以非特权用户身份执行此操作)

host:/usr/src/linux-2.6.17.3-guest$ make linux ARCH=um

请注意,我 没有 告诉您制作压缩或 bzip 压缩的镜像。 请记住,您将像运行用户空间命令一样运行此内核,因此不应压缩它。 完成的内核将位于您的源代码树的顶层目录(在上面的示例中为 /usr/src/linux-2.6.17.3-guest)中,并将被命名为 linux——您可能需要将其重命名为更具描述性的名称,例如 uml-guestkernel-2.6.17.3。 您可能还需要将其移动到您打算从中运行它的目录——可能类似于 /usr/local/uml/。

顺便说一句,不要被您的访客内核文件的大小吓到。 大部分体积是符号信息,当您执行它时,这些信息 不会 加载到内存中。

结论

您的宿主系统现在完全支持用户模式 Linux,并且您已经拥有一个访客内核镜像可以运行。 下一步是获取或创建要与访客内核一起使用的根文件系统镜像。 这就是我们下次将继续讨论的内容!

本文资源: /article/9260

Mick Bauer (darth.elmo@wiremonkeys.org) 是美国最大的银行之一的网络安全架构师。 他是 O'Reilly 图书 Linux 服务器安全 第二版(以前称为 使用 Linux 构建安全服务器)的作者,偶尔在信息安全会议上发表演讲,并且是“网络工程波尔卡”的作曲家。

加载 Disqus 评论