20.13.加密磁盘分区 ================== FreeBSD 提供了出色的在线保护,以防止未经授权的数据访问。文件权限和\ `强制访问控制 `__\ (MAC)有助于防止未经授权的用户在操作系统运行和计算机开机时访问数据。然而,如果攻击者拥有对计算机的物理访问权限,并且可以将计算机的硬盘移动到另一个系统中去复制和分析数据,那么操作系统所强制执行的权限就没有意义了。 无论攻击者是如何占有硬盘或断电的计算机,FreeBSD 内置的基于 GEOM 的加密子系统都能够保护计算机文件系统中的数据,即使是面对拥有大量资源的高度活跃的攻击者。与加密单个文件的方法不同,可以用内置的工具 ``gbde`` 和 ``geli`` 来透明地加密整个文件系统。任何明文数据都不会被存储到硬盘上。 本章演示了如何在 FreeBSD 上创建一个加密的文件系统。它首先演示了使用 ``gbde`` 的过程,然后用 ``geli`` 对同一个例子进行示范。 20.13.1.用 gbde 进行磁盘加密 ---------------------------- 工具 `gbde(4) `__ 为攻击者获取 *冷* 存储设备的内容提供一个巨大的挑战。然而,如果计算机在运行时被破坏,并且存储设备被主动连接,或者攻击者能够获得有效的口令,那么它就不能为存储设备的内容提供保护。因此,在系统运行时提供物理安全并保护加密机制所使用的口令是很重要的。 该工具提供了几个屏障来保护存储在每个磁盘扇区的数据。它使用 CBC 模式下的 128 位 AES 对磁盘扇区的内容进行加密。磁盘上的每个扇区都用不同的 AES 密钥进行加密。关于加密设计的更多信息,以及如何从用户提供的口令中获得扇区密钥,请参考 `gbde(4) `__\ 。 FreeBSD 为 gbde 提供了一个内核模块,可以用这个命令加载: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # kldload geom_bde 如果使用定制内核配置文件,确保它包含这一行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session options GEOM_BDE 下面的例子演示了在系统中添加一个新的硬盘,该硬盘将存放一个加密的分区,该分区将被挂载为 **/private**\ 。 用 gbde 加密一个分区的步骤 1. 添加新的硬盘驱动器 按照\ `添加硬盘 `__\ 中的说明,将新硬盘安装到系统中。在这个例子中,一个新的硬盘分区被添加为 **/dev/ad4s1c**\ 。\ **/dev/ad0s1**\ \* 代表现有的标准 FreeBSD 分区。 .. code:: shell-session # ls /dev/ad* /dev/ad0 /dev/ad0s1b /dev/ad0s1e /dev/ad4s1 /dev/ad0s1 /dev/ad0s1c /dev/ad0s1f /dev/ad4s1c /dev/ad0s1a /dev/ad0s1d /dev/ad4 1. 创建一个存放 ``gbde`` Lock 文件的目录 .. code:: shell-session # mkdir /etc/gbde gbde Lock 文件包含 gbde 访问加密分区所需的信息。如果不能访问 Lock 文件,在没有大量人工干预的情况下,gbde 将不能解密加密分区中包含的数据,而软件不支持人工干预。每个加密分区都使用一个单独的 Lock 文件。 1. 初始化 ``gbde`` 分区 一个 gbde 分区在被使用之前必须被初始化。该初始化只需要执行一次。该命令将打开默认编辑器,以便在一个模板中设置各种配置选项。为了与 UFS 文件系统一起使用,将扇区大小设置为 2048。 .. code:: shell-session # gbde init /dev/ad4s1c -i -L /etc/gbde/ad4s1c.lock # $FreeBSD: src/sbin/gbde/template.txt,v 1.1.36.1 2009/08/03 08:13:06 kensmith Exp $ # # Sector size is the smallest unit of data which can be read or written. # Making it too small decreases performance and decreases available space. # Making it too large may prevent filesystems from working. 512 is the # minimum and always safe. For UFS, use the fragment size # sector_size = 2048 [...] 编辑保存之后,用户将被要求两次输入用于保护数据的口令。这两次的口令必须是相同的。gbde 保护数据的能力完全取决于口令的质量。关于如何选择一个容易记住的安全口令的提示,见 http://world.std.com/~reinhold/diceware.htm\ 。 该初始化为 gbde 分区创建一个 Lock 文件。在这个例子中,它被存储为 **/etc/gbde/ad4s1c.lock**\ 。Lock 文件必须以 ``.lock`` 结尾,以便被 **/etc/rc.d/gbde** 启动脚本正确检测。 **当心** Lock 文件 *必须* 与任何加密分区的内容一起进行备份。如果没有 Lock 文件,合法所有者也将无法访问加密分区上的数据。 1. 将加密的分区附加到内核上 .. code:: shell-session # gbde attach /dev/ad4s1c -l /etc/gbde/ad4s1c.lock 该命令将提示输入初始化加密分区时选择的口令。新的加密设备将作为 **/dev/device_name.bde** 出现在 **/dev** 中: .. code:: shell-session # ls /dev/ad* /dev/ad0 /dev/ad0s1b /dev/ad0s1e /dev/ad4s1 /dev/ad0s1 /dev/ad0s1c /dev/ad0s1f /dev/ad4s1c /dev/ad0s1a /dev/ad0s1d /dev/ad4 /dev/ad4s1c.bde 1. 在加密的设备上创建一个文件系统 加密的设备被连接到内核后,就可以在设备上创建一个文件系统。这个例子创建了一个 UFS 文件系统,启用了软更新。请确保指定具有 \*\ **.bde** 扩展名的分区: .. code:: shell-session # newfs -U /dev/ad4s1c.bde 1. 挂载加密的分区 创建一个挂载点并挂载加密的文件系统: .. code:: shell-session # mkdir /private # mount /dev/ad4s1c.bde /private 1. 验证加密的文件系统是否可用 加密的文件系统现在应该是可见的并且可供使用: .. code:: shell-session % df -H Filesystem Size Used Avail Capacity Mounted on /dev/ad0s1a 1037M 72M 883M 8% / /devfs 1.0K 1.0K 0B 100% /dev /dev/ad0s1f 8.1G 55K 7.5G 0% /home /dev/ad0s1e 1037M 1.1M 953M 0% /tmp /dev/ad0s1d 6.1G 1.9G 3.7G 35% /usr /dev/ad4s1c.bde 150G 4.1K 138G 0% /private 每次启动后,任何加密的文件系统都必须手动重新连接到内核,检查是否有错误,并挂载,然后才能使用这些文件系统。要配置这些步骤,请在 **/etc/rc.conf** 中添加以下几行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session gbde_autoattach_all="YES" gbde_devices="ad4s1c" gbde_lockdir="/etc/gbde" 这需要在启动时在控制台输入密码。输入正确的口令后,加密的分区将被自动挂载。其他 gbde 启动选项也是可用的,在 `rc.conf(5) `__ 中列出。 **注意** sysinstall 与 gbde-encrypted 设备不兼容。在启动 sysinstall 之前,所有 \*\ **.bde** 设备必须从内核中分离出来,否则它在最初探测设备时将崩溃。要分离本例中使用的加密设备,使用下面的命令: .. code:: shell-session # gbde detach /dev/ad4s1c 20.13.2.用 ``geli`` 进行磁盘加密 -------------------------------- 使用 ``geli`` 可以获得另一种 GEOM 加密级别。这个控制工具增加了一些功能,并使用一个不同的方案来做加密工作。它提供了以下功能: - 利用 `crypto(9) `__ 框架,在有加密硬件时自动使用。 - 支持多种加密算法,如 AES、Blowfish 和 3DES。 - 允许对根分区进行加密。在系统启动时,将要求提供用于访问加密的根分区的口令。 - 允许使用两个独立的密钥。 - 它是快速的,因为它执行简单的扇区到扇区的加密。 - 允许备份和恢复主密钥。如果用户破坏了他们的密钥,仍有可能通过从备份中恢复密钥来获取数据。 - 允许磁盘附加一个随机的、一次性的密钥,这对交换分区和临时文件系统很有用。 更多的功能和使用实例可以在 `geli(8) `__ 中找到。 下面的例子示范了如何生成一个密钥文件,该文件将被用作安装在 **/private** 下的加密 provider 的主密钥的一部分。密钥文件将提供一些用于加密主密钥的随机数据。主密钥也将受到口令的保护。provider 的扇区大小将是 4kB。这个例子描述了如何附加到 ``geli`` provider 上,在它上面创建一个文件系统,挂载它,使用它,最后是如何分离它 用 ``geli`` 加密一个分区的步骤 1. 加载 ``geli`` 对 ``geli`` 的支持是作为一个可加载的内核模块提供的。要配置系统在启动时自动加载该模块,请在 **/boot/loader.conf** 中添加以下一行: .. code:: shell-session geom_eli_load="YES" 要立即加载这个内核模块: .. code:: shell-session # kldload geom_eli 对于一个定制内核,确保内核配置文件包含这些行: .. code:: shell-session options GEOM_ELI device crypto 1. 生成主密钥 下面的命令生成了一个主密钥,所有的数据都将用这个密钥进行加密。这个密钥永远不能被改变。与其直接使用它,不如用一个或多个用户密钥进行加密。用户密钥是由文件 **/root/da2.key** 中的随机字节和/或口令的可选组合组成的。在这种情况下,密钥文件的数据源是 **/dev/random**\ 。该命令还将 provider(\ **/dev/da2.eli**\ )的扇区大小配置为 4kB,以获得更好的性能: .. code:: shell-session # dd if=/dev/random of=/root/da2.key bs=64 count=1 # geli init -K /root/da2.key -s 4096 /dev/da2 Enter new passphrase: Reenter new passphrase: 并非一定要同时使用口令和密钥文件,因为任何一种保护主密钥的方法都可以单独使用。 如果钥匙文件以“-”的形式给出,将使用标准输入。例如,这个命令产生了三个密钥文件: .. code:: shell-session # cat keyfile1 keyfile2 keyfile3 | geli init -K - /dev/da2 1. 用生成的密钥连接 provider 要连接 provider,指定密钥文件、磁盘名称和口令: .. code:: shell-session # geli attach -k /root/da2.key /dev/da2 Enter passphrase: 这将创建一个带有 **.eli** 扩展名的新设备: .. code:: shell-session # ls /dev/da2* /dev/da2 /dev/da2.eli 1. 创建新的文件系统 接下来,用 UFS 文件系统格式化该设备,并将其挂载到一个现有的挂载点: .. code:: shell-session ## dd if=/dev/random of=/dev/>da2.eli bs=1m ## newfs /dev/da2.eli ## mount /dev/da2.eli /private 加密的文件系统现在应该可以使用了: .. code:: shell-session # df -H Filesystem Size Used Avail Capacity Mounted on /dev/ad0s1a 248M 89M 139M 38% / /devfs 1.0K 1.0K 0B 100% /dev /dev/ad0s1f 7.7G 2.3G 4.9G 32% /usr /dev/ad0s1d 989M 1.5M 909M 0% /tmp /dev/ad0s1e 3.9G 1.3G 2.3G 35% /var /dev/da2.eli 150G 4.1K 138G 0% /private 加密分区的工作完成后,如果不再需要 **/private** 分区,谨慎的做法是让设备进入冷存储,将 geli 加密分区从内核中卸载并分离出来: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # umount /private # geli detach da2.eli 我们提供了一个 **rc.d** 脚本来简化启动时挂载 ``geli`` 加密设备的过程。对于这个例子,在 **/etc/rc.conf** 中添加这些行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session geli_devices="da2" geli_da2_flags="-k /root/da2.key" 这就把 **/dev/da2** 配置为一个 ``geli`` provider,主密钥为 **/root/da2.key**\ 。在系统关闭之前,系统将自动从内核中分离出 provider。在启动过程中,脚本会在连接 provider 之前提示输入口令。在密码提示前后可能会出现其他内核信息。如果启动过程似乎停滞不前,仔细寻找其他信息中的密码提示。只要输入了正确的口令,provider 就会被连接。然后,文件系统被挂载,通常是通过 **/etc/fstab** 中的一个条目。关于如何配置文件系统在启动时挂载,请参考“\ `挂载和卸载文件系统 `__\ ”的说明。