> For the complete documentation index, see [llms.txt](https://handbook.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://handbook.bsdcn.org/di-21-zhang-cun-chu/21.12.-jia-mi-ci-pan-fen-qu.md).

# 21.12.加密磁盘分区

FreeBSD 提供了出色的在线保护，防止未经授权的数据访问。文件权限和强制访问控制（MAC）有助于防止未经授权的用户在操作系统运行且计算机开机时访问数据。但是，如果攻击者对计算机有物理访问权限，并且可将计算机的硬盘移动到另一个系统以复制和分析数据，那么操作系统强制执行的权限就无关紧要了。

无论攻击者如何获得硬盘或关闭的计算机，FreeBSD 内置的基于 GEOM 的加密子系统都能保护计算机文件系统上的数据，即使是拥有大量资源且有强烈动机的攻击者也无法访问。与加密单个文件的加密方法不同，内置的 `gbde` 和 `geli` 工具可透明地加密整个文件系统。明文永远不会触及硬盘盘片。

本章演示如何在 FreeBSD 上创建加密文件系统。首先演示使用 `gbde` 的过程，然后演示使用 `geli` 的相同示例。

> **警告**
>
> GBDE 磁盘加密已弃用，并在 FreeBSD 15.0 中移除。

## 21.12.1. 使用 gbde 进行磁盘加密

[gbde(4)](https://man.freebsd.org/cgi/man.cgi?query=gbde\&sektion=4\&format=html) 工具的目标是让攻击者在获取 *冷存储* 设备内容时面临极大的挑战。但是，如果计算机在运行中且存储设备已附加时被入侵，或攻击者拥有有效的密码短语，它将不会保护存储设备的内容。因此，在系统运行时提供物理安全性非常重要，同时也需要保护加密机制所使用的密码短语。

此工具提供了几个屏障来保护每个磁盘扇区中存储的数据。它使用 128 位 AES CBC 模式加密磁盘扇区的内容。磁盘上的每个扇区都使用不同的 AES 密钥加密。有关加密设计的更多信息，包括扇区密钥是如何从用户提供的密码短语派生的，请参阅 [gbde(4)](https://man.freebsd.org/cgi/man.cgi?query=gbde\&sektion=4\&format=html)。

FreeBSD 提供了 gbde 的内核模块，可使用以下命令加载：

```sh
# kldload geom_bde
```

如果使用的是定制内核配置文件，请确保它包含以下行：

```sh
options GEOM_BDE
```

以下示例演示了如何向系统添加一块新的硬盘，该硬盘将持有单独的加密分区，并将其挂载为 **/private**。

**过程：使用 gbde 加密分区**

1. **添加新硬盘**\
   按照 [添加磁盘](/di-21-zhang-cun-chu/21.2.-tian-jia-ci-pan.md) 中的说明将新硬盘安装到系统中。对于本示例，添加了新硬盘分区 **/dev/ad4s1c**，**/dev/ad0s1\*** 代表现有的标准 FreeBSD 分区。

   ```sh
   # 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
   ```
2. **创建用于存储 `gbde` 锁文件的目录**

   ```sh
   # mkdir /etc/gbde
   ```

   gbde 锁文件包含 gbde 访问加密分区所需的信息。如果没有访问锁文件，gbde 将无法解密加密分区中的数据，除非进行大量不受软件支持的手动干预。每个加密分区使用单独的锁文件。
3. **初始化 `gbde` 分区** 在使用之前，必须初始化 gbde 分区。此初始化只需要执行一次。执行此命令后将打开默认编辑器，以便在模板中设置各种配置选项。对于 UFS 文件系统，将 `sector_size` 设置为 2048：

   ```sh
   # gbde init /dev/ad4s1c -i -L /etc/gbde/ad4s1c.lock
   #
   # 扇区大小是可以读取或写入的最小数据单位。
   # 将其设置得过小会降低性能并减少可用空间。
   # 将其设置得过大可能会导致文件系统无法正常工作。512 是
   # 最小值且始终安全。对于 UFS，请使用碎片大小
   #
   sector_size	=	2048
   [...]
   ```

   保存编辑后，用户将被要求两次输入用于保护数据的密码短语。密码短语必须一致。gbde 保护数据的能力完全依赖于密码短语的质量。有关如何选择既安全又易于记住的密码短语的提示，请参见 [http://world.std.com/\~reinhold/diceware.htm](http://world.std.com/~reinhold/diceware.html)。

   此初始化会为 gbde 分区创建锁文件。在本示例中，它存储为 **/etc/gbde/ad4s1c.lock**。锁文件必须以 `.lock` 结尾，以便 **/etc/rc.d/gbde** 启动脚本能正确检测。

   > **当心**
   >
   > 锁文件 *必须* 与任何加密分区的内容一起备份。没有锁文件，合法所有者将无法访问加密分区上的数据。
4. **将加密分区附加到内核**

   ```sh
   # gbde attach /dev/ad4s1c -l /etc/gbde/ad4s1c.lock
   ```

   此命令将提示输入在加密分区初始化时选择的密码短语。新加密设备将出现在 **/dev** 目录中，名称为 **/dev/device\_name.bde**：

   ```sh
   # 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
   ```
5. **在加密设备上创建文件系统** 加密设备附加到内核后，就可在设备上创建文件系统。此示例创建启用了软更新的 UFS 文件系统。确保指定具有 `*.bde` 扩展名的分区：

   ```sh
   # newfs -U /dev/ad4s1c.bde
   ```
6. **挂载加密分区** 创建挂载点并挂载加密文件系统：

   ```sh
   # mkdir /private
   # mount /dev/ad4s1c.bde /private
   ```
7. **验证加密文件系统是否可用**\
   现在，加密文件系统应该可见并可用：

   ```sh
   % 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**：

```sh
gbde_autoattach_all="YES"
gbde_devices="ad4s1c"
gbde_lockdir="/etc/gbde"
```

这要求在引导时通过控制台输入密码短语。输入正确的密码短语后，加密分区将自动挂载。更多 gbde 引导选项可在 [rc.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=rc.conf\&sektion=5\&format=html) 中查看。

> **注意**
>
> sysinstall 与 gbde 加密的设备不兼容。所有 `*.bde` 设备在启动 sysinstall 之前必须从内核中分离，否则它将在初始设备探测期间崩溃。要分离示例中使用的加密设备，请使用以下命令：
>
> ```sh
> # gbde detach /dev/ad4s1c
> ```

## 21.12.2. 使用 `geli` 进行磁盘加密

另一种可用的加密 GEOM 类是 `geli`。该控制工具增加了一些功能，并使用不同的方案执行加密工作。它提供以下特性：

* 利用 [crypto(9)](https://man.freebsd.org/cgi/man.cgi?query=crypto\&sektion=9\&format=html) 框架，并在可用时自动使用加密硬件。
* 支持多种加密算法，如 AES-XTS、AES-CBC 和 Camellia-CBC。
* 可加密根分区。在系统引导时，将要求输入用于访问加密根分区的密码短语。
* 可使用两个独立的密钥。
* 它执行简单的扇区到扇区的加密，因此速度很快。
* 可备份和恢复主密钥。如果用户销毁了他们的密钥，仍可通过恢复备份的密钥来访问数据。
* 可使用随机的一次性密钥附加磁盘，这对于交换分区和临时文件系统非常有用。

更多功能和使用示例可参考 [geli(8)](https://man.freebsd.org/cgi/man.cgi?query=geli\&sektion=8\&format=html)。

以下示例说明了如何生成密钥文件，该文件将作为加密 provider 的主密钥的一部分，挂载在 **/private** 下。该密钥文件将提供一些随机数据，用于加密主密钥。主密钥也将由密码短语保护。provider 的扇区大小将设置为 4kB。该示例说明了如何附加到 `geli` provider，如何在其上创建文件系统、挂载、操作并最终如何分离它。

**过程：使用 `geli` 加密分区**

1. **加载 `geli` 支持** `geli` 支持作为可加载的内核模块提供。要配置系统在引导时自动加载该模块，请将以下行添加到 **/boot/loader.conf**：

   ```sh
   geom_eli_load="YES"
   ```

   要立即加载内核模块：

   ```sh
   # kldload geom_eli
   ```

   对于定制内核，确保内核配置文件包含以下行：

   ```sh
   options GEOM_ELI
   device crypto
   ```
2. **生成主密钥** 以下命令生成主密钥，所有数据都将使用该密钥加密。此密钥不可更改。它不会直接使用，而是使用一个或多个用户密钥对其进行加密。用户密钥由一个可选的组合构成，包括来自文件 **/root/da2.key** 的随机字节和/或密码短语。在此例中，密钥文件的数据源是 **/dev/random**。此命令还将 provider（**/dev/da2.eli**）的扇区大小设置为 4kB，以提高性能：

   ```sh
   # 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:
   ```

   使用密码短语和密钥文件并不是强制性的，可单独使用任何一种方法来保护主密钥。

如果密钥文件作为 `-` 提供，将使用标准输入。例如，以下命令生成三个密钥文件：

```sh
# cat keyfile1 keyfile2 keyfile3 | geli init -K - /dev/da2
```

3. **使用生成的密钥附加 provider** 要附加 provider，请指定密钥文件、磁盘名称和密码短语：

   ```sh
   # geli attach -k /root/da2.key /dev/da2
   Enter passphrase:
   ```

   这将创建新设备，扩展名为 `.eli`：

   ```sh
   # ls /dev/da2*
   /dev/da2  /dev/da2.eli
   ```
4. **创建新文件系统** 接下来，使用 UFS 文件系统格式化该设备，并将其挂载到现有挂载点：

   ```sh
   # dd if=/dev/random of=/dev/da2.eli bs=1m
   # newfs /dev/da2.eli
   # mount /dev/da2.eli /private
   ```

   加密文件系统现在应该可使用：

   ```sh
   # 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` 加密分区从内核中分离来将该设备放入冷存储：

```sh
# umount /private
# geli detach da2.eli
```

提供了一个 `rc.d` 脚本，以简化在引导时挂载 `geli` 加密设备。对于此示例，请将以下行添加到 **/etc/rc.conf**：

```sh
geli_devices="da2"
geli_da2_flags="-k /root/da2.key"
```

这将配置 **/dev/da2** 作为具有主密钥 **/root/da2.key** 的 `geli` provider。在系统关闭之前，系统将自动将 provider 从内核中分离。在引导过程中，脚本将在附加 provider 之前提示输入密码短语。引导过程中的其他内核消息可能会在密码提示之前或之后显示。如果引导过程似乎停滞，请仔细查看其他消息中的密码提示。输入正确的密码短语后，provider 将被附加。然后，文件系统将挂载，通常通过 **/etc/fstab** 中的条目挂载。有关如何配置文件系统以在引导时挂载的说明，请参考 [挂载和卸载文件系统](/di-3-zhang-freebsd-ji-chu/3.7.-wen-jian-xi-tong-de-gua-zai-yu-xie-zai.md)。
