系统安全包括两个有些冲突的目标。第一个目标是实现完整的细粒度访问控制。必须对有可能泄露或损坏信息的位置实施控制。过于粗粒度的控制和不进行控制没有区别。例如,如果必须将所有文件归为一种类型,并且有任何一个文件是公开的,则所有文件都是公开的。
另一方面,配置必须简单,否则管理员就需要管理很多访问(但是再次强调,这和不进行控制是一样的)。例如,如果使程序正常工作需要大量访问规则,那么管理员就会为程序添加许多访问权限,而不是测试这些访问规则是否有必要。
Linux 中的两个基本安全模块使用不同的方法来平衡这个矛盾。
SELinux 首先对所有东西实施控制,同时使用强大的策略语言简化策略的管理。
Smack 主要提供简单的访问控制。
主要元素 2:SELinux
到目前为止,SELinux 是针对 Linux 的最有名的 MAC 系统(强制访问控制)。尽管仍然有人反对它,但流行的 Fedora? 发行版从几年前开始就和 SELinux 一起部署,这是它取得成功的有力证明。
SELinux 使用模块化策略语言配置,因此用户可以轻松更新已安装的策略。这种语言还提供一些接口,允许使用更高级的语句表达一组低级的语句。
在本文中,我们将使用一个新的接口来定义容器。虽然为容器添加许多访问权限使接口本身变得非常大,但是使用接口创建新的容器却很简单。这个接口很有希望成为核心发布策略的一部分。
主要元素 3:Smack
Smack 是简化的强制访问控制内核(Simplified Mandatory Access Control Kernel)的缩写。它首先使用简单的文本标签标记所有进程、文件和网络流量。使用创建进程的标签创建最新的文件。通常存在一些带有明确定义的访问规则的默认类型。进程常常可以对具有同一标签的对象进行读写。绕过 Smack 访问规则的特权由 POSIX 功能控制,因此带有 CAP_MAC_OVERRIDE 的任务可以覆盖规则;带有 CAP_MAC_ADMIN 的任务可以更改规则和标签。“POSIX file capabilities: Parceling the power of root”(参考资料)演示了这些特权。
安全目标
我们不能盲目地应用策略并期望带来某些价值,而是应该首先定义明确的安全目标。Smack 的简单性实际上限定了可实现的目标的范围,我们将力求实现以下目标:
使用提供 Web 和 ssh 服务的隔离的文件系统创建容器。
容器应该是独立的,以保护彼此的安全。容器 vs1 不能读取另一个容器 vs2 的文件或中断它的任务。
主机的关键文件不受容器的影响。
外部能够访问容器中的 Web 服务器和 ssh 服务器。
一般设置
在本文中,我们将进行两个实验:首先设置由 SELinux 保护的容器,然后设置由 Smack 保护的容器。这两个实验演示了大部分初级设置。
您可以使用真实的机器来完成这两个实验,但是使用虚拟机更加方便。要使用 qemu 或 kvm,可以通过 qemu-img create vm.img 10G 创建一个硬盘。
使用命令 kvm -hda vm.img -cdrom cdrom.iso -boot d -m 512M 从 CDROM 引导虚拟机。要获得 CDROM 映像,可以从 Fedoraproject.org/get-fedora 下载 Fedora 10 for i386 的安装 DVD。用下载获得的文件的名称替换上一命令中的 cdrom.iso。安装过程基本可以使用默认值,但一定不要选择 office and productivity,而是选择 software development。此外,还需要使用 yum 包管理器安装 bridge-utils、debootstrap 和 ncurses-devel rpms。
现在需要编译一个定制内核。下载内核源代码 rpm 并对其使用补丁 enable-netns.patch(参见 下载 小节)以提供网络名称空间(在 2.6.29 中为上游(upstream),但在 Fedora 10 中不是),然后更改配置并完成编译和安装。这需要作为根用户用以下指令来实现:
yumdownloader --source kernel
rpm -i kernel*
cd rpmbuild
rpmbuild -bc SPECS/kernel-*
cd BUILD/kernel-2.6.27/linux-2.6*
patch -p1 < ~/enable-netns.patch
make menuconfig
make && make modules_install && make install
对于这两个实验,在 make menuconfig 步骤中都需要选择 Network Namespaces(在 Networking support -> Networking options 菜单下)。对于 Smack 实验,还需要进入 Security options 菜单,取消选定 SELinux,并选择下一个选项 Smack。您还需要将 /boot/grub/grub.conf 中的 default 引导项改为 0 而不是 1。
现在我们试试 liblxc。“LXC:Linux 容器工具” 详细描述了 liblxc 的基本用法,因此这里不再细谈。仅需使用 container_setup.sh 脚本(参见 下载 小节)设置网桥(bridge),容器网络设备将在此进行对话。它还会清除防火墙(默认情况下不处理网桥),并且在进行 Smack 实验时设置 Smack 策略(我们稍后将在文件 /etc/smackaccesses 中创建)。每次重新引导之后必须运行 container_setup.sh,或者设置为在引导时自动运行它(如果知道怎么做的话)。
现在已经准备好虚拟机!我们来试试 liblxc。可以从 lxc.sf.net 通过 cvs 下载最新的源代码,并按照以下方法编译它:
cvs -d:pserver:anonymous@lxc.cvs.sourceforge.net:/cvsroot/lxc login
cvs -z3 -d:pserver:anonymous@lxc.cvs.sourceforge.net:/cvsroot/lxc co -P lxc
cd lxc
./bootstrap && ./configure && make && make install
现在,如果您查看 README 文档的话,将发现有好几个入口点可以选择。容器是非常轻量级的,因为它们与系统共享许多资源 —— 包括文件系统。但我们的目标是提供一些简单的隔离,因此将使用脚本 lxc-debian 为每个容器创建完整的 debian chroot 映像。首先创建一个名为 vsplain 的容器:
mkdir /vsplain
cd /vsplain
lxc-debian create
container name: vsplain
hostname: vsplain
IP 10.0.2.20
gateway: 10.0.2.2
这个容器的配置存储在 /usr/local/var/lxc/vsplain 目录下。如果查找名为 cgroup 的文件,将会看到一些以 devices. 开头的行。这些是设备白名单 cgroup 的指令,它协调由容器执行的设备创建、读和写。