当你不能依靠物理安全来保证你文件的安全时,是时候采取额外的步骤加密文件系统了,虽然本文涉及到的是基于PowerPC的系统,但原则上来说也适用于其他架构的系统。
在另一篇文章“实现加密的home目录”中,我描写了如何透明地加密home目录,本文叙述另一个技术实现--加密的root文件系统,我论述了GNU/Linux启动过程和软件需求,并提供了一些指令,对Open Firmware做了一下介绍,以及其他一些有关的考虑事项。我用于教学的系统是一台基于PowerPC架构的新世界苹果iBOOK电脑,运行Fedora Core 3预览版,不考虑细节,本文涉及到的概念和程序可以应用到任何设备、架构或操作系统。我提供的指令假设你有一个多余的USB闪存盘并且你系统的支持从USB设备启动。
同时,我还假设读者能轻松应用源代码补丁并编译程序,对于Fedora Core 3 Test 3版本,mkinitrd和启动脚本软件包需要打补丁以支持加密的root文件系统,需要掌握基本的分区管理和创建文件系统的知识,执行一个基本的Linux发行版安装超出了本文要求的范畴。
在呈现有关的技术步骤之前,一个高层概念必须先讨论:信任。信任与加密技术和认证总是纠缠在一起的,对任何有电子密钥的设备都可以假设它是可信任的。例如:当自动提款机(ATM)与我的银行账号共用个人识别号(PIN)时,我会信任ATM不会将我的PIN与不适当的第三方进行共享。同样,当我给我的计算机提供一个加密密钥时,我假设这个密钥不会与任何其他人进行共享,我会信任这台计算机在我们之间保守秘密。
那么,你能信任你的计算机吗?除非你无论到哪里都带着它,否则你真的不能信任它,即使磁盘已经经过加密处理也不行。设想这样一个情景:在你睡觉时,有人偷走了你的计算机,小偷将计算机中加密的内容做了一份拷贝,虽然没有加密密钥而对他来说毫无意义,但是他可以用更恶魔的内容替换笔记本电脑加密的内容,然后再将电脑放回去,当你第二天醒来时,计算机提示你输入加密密码,但是这时你提供的密钥会传输给小偷,他得到密钥后就有一份数据和密钥的拷贝了,他就可以读取你的文件了。
这个情景可能显得比较牵强,但是它说明了一点,你不能信任你的笔记本电脑,始终保持你的眼睛你离开它很重要,因此,无论如何优秀地实现你的加密系统,要建立在信任的基础前提条件下才行。
网络确保我们可以信任计算机的启动过程,我们需要将其从计算机中分隔出来,考虑这个问题:你携带你的汽车钥匙而不是携带你的汽车。你的密钥自身概念上与你的汽车钥匙一样。你可以更容易地保护你的密钥,因此你不用随时随地都携带上你的计算机,我们将用这个密钥提供启动计算机需要的软件,闪存盘将充当密钥的角色,通过保护启动系统最初的软件,除加密密钥外,我们可以有效地降低启动过程被劫持的风险。
你需要连接你的计算机是如何启动的,因为解锁一个加密的root文件系统是对整体的引导过程有影响,目前稳定的内核版本是2.6,可选择使用initramfs来帮助启动,在lwn.net上有一篇文档“initramfs来了”, initramfs是一个cipo归档,内核知道如何解压到基于RAM的磁盘上,这个解压的文件系统包括一个传统的载入内核挂载root文件系统的模块的脚本,在我们的样例中,这个脚本也用于解锁加密的root文件系统,关于这个主题更多的信息可以在文件buffer-format.txt和initrd.txt中找到,这两个文件都在Linux内核源代码发布包中。
对Linux有若干个文件系统加密接口是可用的,Jari Ruusu的Loop-AES就是这样一个项目,有多个cryptoloop变种提供一个加密的loopback设备,本文集中讲述最近2.6Linux内核提供的dm-crypt接口,这个接口目前已经被Fedora项目吸收,dm-crypt模块由Fedora内核包提供,还需要一个静态链接cryptsetup,这个实用程序简化了dm-crypt设备的管理,最后,还需要parted和hfsutils来管理启动文件系统。
不幸的是,Fedora Core的anaconda安装程序还不支持在盒子外安装加密文件系统,网络绕过这个限制,你必须保留一个空闲分区安装Fedora,格式化空闲分区为一个加密文件系统,然后拷贝原始安装数据到新的加密文件系统上,网络简化,我们假设Fedora已经安装到两个分区上:/dev/hda4,挂载到/home和/dev/hda5,挂载到/,因为/home下还没有用户目录,直到Fedora安装完毕,我们可以使用/dev/hda4作为我们的备用分区,/dev/hda3作为swap分区。
安装Fedroa Core 3,挂载/dev/hda4到/home,/dev/hda5挂载到/,不要添加非root用户,因为/home稍后将被清除干净,至此,你应该拥有一个全功能的Linux系统了。
在设置加密文件系统之前,你应该随意分区,这样排除一个潜在关于磁盘内容的信息漏洞,图1示范了一个抽象的半满磁盘,它没有恰当进行随机排列,图2示范了一个恰当随机排列的磁盘,在格式化之前包含一个加密的文件系统,注意,从图1中可以获取到一些关于它的内容的知识(如它们跨越了磁盘的二分之一),图2提供了一个没有那么豪华的对手,假如这样,磁盘可以很容易被清空,分区随机排列是通过用随机数据重写它的内容实现的:dd if=/dev/urandom of=/dev/hda4,这个过程可能要花很长的时间,因为创建随机数据有些困难的。
图1
图2随机排列的分区隐藏了使用量
要在/dev/hda4上创建一个加密的ext3文件系统,使用下面的步骤:
1)确认aes,dm-mod,dm-crypt模块已经载入内核
2)卸载将要托管加密root文件系统的分区/dev/hda4
#umount /dev/hda4
3)创建一个随机256位加密密钥并存储在/etc/root-key
#dd if =/dev/urandom of=/etc/root-key bs=1c count=32
这个密钥稍后将拷贝到闪存盘。
4)创建一个dm-crypt设备,使用前面创建的密钥加密
#cryptsetup -d /etc/root-key create /dev/hda4
现在访问/dev/mapper/root在/dev/hda4上提供了一个加密层,默认情况下,cryptsetup创建一个aes加密的dm-crypt设备并任务密钥大小为256位。
5)在/dev/mapper/root上创建一个ext3文件系统
#mkfs.ext3 /dev/mapper/root
6)挂载新文件系统
#mkdir /mnt/encroot
#mount /dev/mapper/root /mnt/encroot
7)现在你已经有一个加密文件系统了,你必须用/dev/hda5(原始的root文件系统)的内容来填充它
#cp -ax / /mnt/encroot
8)最后,在/mnt/encroot/crypttab中创建一个条目以便不同的实用程序知道文件系统是如何配置的:
root /dev/hda4 /etc/root-key cipher=aes
现在我们的加密文件系统已经准备好了,需要理解更多关于目标架构的启动过程,通常,计算机有一个固件程序来掌管系统启动的全过程,保护固件程序超出了本文的范畴,因此我们假设系统固件程序是可以信任的,大多数读者可能对BIOS比较熟悉,它是PC平台的启动固件程序,我主要讨论的是Open Firmware,它用于计算机制造厂商如苹果,sun和IBM启动系统。
NetBSD/macppc的安装指令对Open Firmware做了一个充分的介绍,我们对使用Open Firmware命令行接口配置计算机从一个闪存盘启动非常感兴趣,Open Firmware允许你查看连接到计算机的设备和设置固件程序变量的值。
在一个新世界(G3或更新的)苹果计算机初始化启动过程中,可以通过暂停选择性命令来访问Open Firmware提示符。
变量boot-device用于确定系统将从哪个设备启动,printenv命令允许查看当前的值:
>printenv
[...]
boot-devicehd:,:txbihd:,:txbi
这实际上意味着通过执行在第一块IDE磁盘上HFS类型txbi的文件来实现启动的,第二:txbi前的字符作为解释一个HFS文件类型的标志,否则,txbi可能被理解为文件路径,假如这样,标志hd实际上是更复杂的/pci@f4000000/ata-6@d/disk@0的一个别名,这个字符串通过子系统变量表现了路径,你可以使用Open Firmware命令查看设备对应的别名。
网络正确地设置boot-device,我们需要找出Open Firmware认出的我们闪存盘的名字,通过ls命令显示闪存盘路径,并打印出设备树:
>dev / ls
[...]
/pci@f2000000
[...]
/usb@1b,1
[...]
/disk@1
[...]
现在我们知道了一点关于计算机固件程序的知识,我们必须花些时间研究固件初始化执行程序:bootloader。通常,运行在苹果PowerPC架构上的Linux系统使用一个叫做yaboot的程序来启动系统,yaboot与LILO或GRUB类似,它包含两个关键程序:ofboot.b和yaboot。ofboot.b提供第一阶段启动过程,实际上,ofboot.b的工作决定了启动什么操作系统,例如:如果一台电脑上同时安装了Mac OS X和Linux系统,ofboot.b执行Mac OS X或Linux的bootloader,如果用户选择载入Linux,ofboot.b执行yaboot,第二阶段启动过程,然后yaboot载入Linux内核和initrd。图3提供了一个基于PowerPC架构的Linux如何使用一个加密的root文件系统启动的实例。
图3
用Open firmware启动一个基于PowerPC系统的过程
我们的可移动启动设备需要ofboot.b和yaboot程序,一个Linux内核和一个包括加密密钥的initrd文件。苹果目前基于PowerPC的架构预设它的启动介质格式化为HFS。
1)使用parted程序在闪存盘上创建正确的可启动的分区(我的是64MB大小,用设备节点/dev/sda访问)
# parted /dev/sda
(parted) mklabel mac
(parted) print
Disk geometry for /dev/sda: 0.000-62.500 megabytes
Disk label type: mac
Minor Start End Filesystem Name Flags
1 0.000 0.031 Apple
(parted) mkpart primary hfs 0.031 62.500
(parted) print
Disk geometry for /dev/sda: 0.000-62.500 megabytes
Disk label type: mac
Minor Start End Filesystem Name Flags
1 0.000 0.031 Apple
2 0.031 62.500 untitled
(parted) set 2 boot on
(parted) name 2 Apple_Boot
(parted) quit
2)在启动分区上创建HFS文件系统
# hformat /dev/sda2
3)通过修改/mnt/encroot/etc/yaboot.conf配置yaboot启动恰当的设备,下面是一个最小配置例子:
boot=/dev/sda2
ofboot=/pci@f2000000/usb@1b,1/disk@1:2
partition=2
install=/usr/lib/yaboot/yaboot
magicboot=/usr/lib/yaboot/ofboot
default=linux
image=/vmlinux
label=linux
root=/dev/hda4
initrd=/initrd.gz
read-only
值/pci@f2000000/usb@1b,1/disk@1:2来自我们先前检查的Open Firmware设备树,/pci@f2000000/usb@1b,1/disk@1是PCI总线f2000000上的第一块USB磁盘,最有兴趣的是:2意味着分区2
就此,initrd必须被安装到闪存盘上,Fedora提供了一个叫做mkinitrd的工具来创建initrd,然而,在写本文的时候,mkinitrd还不支持加载一个加密的root文件系统,补丁在https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=124789,一旦应用了补丁,mkinitrd就可以读取/etc/crypttab并创建一个恰当的initrd了:
1. mkinitrd --authtype=paranoid -f /media/usbdisk/initrd.gz
2. umount /media/usbstick
文件/mnt/encroot/etc/fstab应该被更新反映出变化:
/dev/mapper/root / ext3 defaults 1 1
有加密的swap或完全没有swap空间是一个加密文件系统的先决条件。原因可以在文章“实现加密的home目录”和BugTraq邮件列表中的一篇“Mac OS X在磁盘上存储登陆/密钥链/密码”中找到。当给启动脚本软件包应用了https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=127378的补丁后,Fedora允许用户使用一个随机生成的会话密钥加密他们的swap分区,因为swap空间在重新启动时通常不需要一致,当系统关闭时会话密钥也不保存,要启用加密的swap,完成下面的步骤:
1)添加下面的行到/mnt/encroot/etc/fstab,替换任何先前的swap记录:
/dev/mapper/swap swap swap defaults 0 0
2)添加下面的行到/mnt/encroot/etc/crypttab告诉系统如何完成加密:
swap /dev/hda3 /dev/urandom swap
至此我们应该可以重新启动系统并使用我们的加密文件系统,再说一次,我们需要暂停启动选项命令进入Open Firmware提示符。
正如上面说到的,闪存盘第二个分区路径是/pci@f2000000/usb@1b,1/disk@1:2。了解了这一点,我们可以建立路径/pci@f2000000/usb@1b,1/disk@1:2,ofboot.b。在分区号和文件系统路径之间的分隔符是‘,’,ofboot.b是文件系统路径,与Unix的/类似。
>dir /pci@f2000000/usb@1b,1/disk@1:2,
Untitled GMT File/Dir
Size/ date time TYPE Name
bytes 9/ 3/ 4 21:44:41 ???? ???? initrd.gz
2212815 8/28/ 4 12:24:21 tbxi UNIX ofboot.b
3060 9/ 3/ 4 2:21:20 ???? ???? vmlinux
141868 9/28/ 4 12:24:22 boot UNIX yaboot
914 9/28/ 4 12:24:22 conf UNIX yaboot.conf
这就确定了Open Firmware可以读取启动系统需要的文件,设置boot-device变量的值为/pci@f2000000/usb@1b,1/disk@1:2,ofboot.b使得系统可以从闪存盘启动:
setenv boot-device /pci@f2000000/usb@1b,1/disk@1:2,ofboot.b
一旦系统从加密root文件系统成功启动,必须清除掉/dev/hda5上的所有数据,可以使用随机排列root文件系统分区同样的方法来实现:
dd if=/dev/urandom of=/dev/hda5
你可能想对hda5重写几次,要想了解处理干净一个磁盘,请查看美国安全部门编写的“National Industrial Security Program Operating Manual”第八章。
根据一个安全处理原则,/dev/hda5可能被挂载为/home,/home文件系统也应该被加密,幸运的是,这是一个简单的过程,因为系统不需要/home启动,象创建root文件系统一样创建/home文件系统
1)确认aes,dm-mod,dm-crypt模块已经载入内核
2)卸载/dev/hda5
#umount /dev/hda5
3)创建一个随机256位加密密钥,存储在/etc/home-key
#dd if=/dev/urandom of=/etc/home-key bs=1c count=32
4)创建一个dm-crypt设备,用刚刚生成的密钥加密
#cryptsetup -d /etc/home-key create home /dev/hda5
5)在/dev/mapper/home上创建一个ext3文件系统
#mkfs.ext3 /dev/mapper/home
6)挂载新文件系统
#mount /dev/mapper/home /home
7)在/etc/crypttab中创建一个条目,让各种实用程序都清楚文件系统是如何配置的
root /dev/hda5 /etc/home-key cipher=aes
8)最后,为/home更新/etc/fstab条目
/dev/mapper/home /home ext3 defaults 1 2
至此,可以添加非root系统账号了,设置加密root文件系统的过程就结束了。
加密你所有数据可能很危险,如果加密密钥丢失,你的数据就丢失了,就因为这个原因,备份你的包含有你的密钥的闪存盘很重要,同样,备份加密数据对应的明文也很重要,如果你保存有一张可启动的紧急救援磁盘,重新考虑应该放哪些系统组件在上面或许很有意义,你的root和home文件系统、密钥、parted、hfsutils、加密技术有关的内核模块以及cryptsetup脚本的拷贝都应该放进去。
这个技术在保护你的数据方面究竟有什么实际好处?在《Secrets and Lies》这本书中,作者Bruce Schneier提出了一个有用的手段来评估这个技术,一个攻击树可以用于模型危险,图4呈现了一个攻击我们加密文件系统的树型图,值得注意的是这颗攻击树不是完整的,可能随时间推移会发生改变。
图4攻击者如何读取加密文件系统的数据
通过使用本文讨论的技术和一点创新的想法,确保你磁盘上的数据对常见的偷窃行为更具抵抗性是可能的,跟踪攻击种类的发展比了解防御更重要,尽管还有其他的技术用于保护基于网络的或其他类型的攻击,但本文讨论的技术对整个系统安全的目标具有重要意义。