SDB:加密的根文件系统

跳转到:导航搜索
本文档描述了如何设置一个整体加密的系统,而不仅仅是加密的个人或用户数据,或者为 /home 加密的划分。
Icon-checked.png
此过程已在 Leap 15.0, 15.1, 15.2, 15.3, 15.4 和 Tumbleweed 上进行了测试


简介和动机

大多数笔记本电脑用户在第一次笔记本电脑被盗后才开始考虑笔记本电脑被盗带来的问题。如果笔记本电脑恰好包含新产品的源代码、公司机密文件、关于政治腐败的新闻文章的笔记,或者可能只是一封私人的情书,那么如果数据落入坏人之手,就可能造成灾难。

为了应对笔记本电脑被盗可能造成的破坏性影响,可以选择使用硬件加密设备,或者使用软件加密来保护数据。后一种方法尤其具有吸引力,因为软件解决方案比硬件方法更灵活,并且在现代 CPU 上,大多数用户不会注意到与实时软件加密/解密相关的性能损失。

为什么要加密根文件系统?

乍一看,人们倾向于只加密最敏感的文件,或者整个用户文件系统 (/home) 包含敏感信息。如果未加密根文件系统,那么这是一种足够简单的操作,openSUSE 安装过程以及其他软件都支持这种操作,其中一些软件甚至在用户空间中运行。然而,这种方法的问题在于加密文件的内容往往会从加密区域泄漏到其他区域,例如交换分区、/tmp/var。此外,用于处理数据的编辑器或其他程序也可能在其他位置创建交换文件。最后,与现代日志文件系统相关的元数据,例如其大小、权限、访问时间等,可能存储在单独的划分上,这进一步加剧了这些问题。一般来说,因此,完全防止用户文件系统中的信息泄漏到根文件系统并不容易。

为了理解问题可能有多大,假设一家公司在其内网中安装了一个 Web 服务器,用于分发公司机密信息。如果员工使用 FirefoxOpenOffice.org 插件查看此 Web 服务器上的 doc 文件,则完整的文件将存储在 /tmp 中,并一直保留在那里,直到被删除。因此,虽然交换分区中可能只有一些敏感文档的片段,但整个文档可能在 /tmp 中可用。

因此,适当的做法是加密整个根文件系统,以及包含敏感数据的文件系统。


在新安装中加密根文件系统

加密根文件系统,以及/home, /tmp和其他划分现在完全支持在 openSUSE 图形化安装程序中。

LVM 不是必需的 (但可以激活) 用于加密的根文件系统。

Icon-warning.png
警告: 如果您决定 使用 LVM 并加密多个划分 (或选择“加密交换分区”),您将被多次提示输入加密密码,除非您设置自动解密。请参阅 使用加密交换分区休眠 部分。

请确保使用不需要特殊字符的密码,如果您不使用美国键盘布局,因为它们可能位于与您通常的布局不同的位置。


在现有安装中加密划分

Icon-warning.png
警告: 像所有涉及划分的过程一样,数据丢失可能发生!!。请在继续之前创建备份或将您的重要文件保存在其他地方。

也可以通过 YAST 中的“划分器”程序在正在运行的系统上创建加密划分。但是,加密现有划分会销毁其上的所有数据,并且需要重新调整和重构现有划分。

说明可以在 openSUSE 安全指南的“加密划分和文件”章节 中找到,它是官方 openSUSE 手册的一部分。

避免两次输入密码

对于多个划分,每个需要解密的划分都需要您输入密码。

通常发生在您使用加密的根文件系统和加密的交换分区 没有 LVM 的情况下安装 openSUSE 时。

由于 LUKS 只支持加密单个划分,因此将创建两个 LUKS 划分,并且需要两个密码。

自动解密根划分

Icon-warning.png
警告: 最新版本的 GRUB 可以自动解锁根划分!请参阅 Bug #1206710 以获取更多信息。此外,自动解锁机制可以通过在/etc/crypttab.

加密根划分的一个缺点是您需要在启动程序 (Grub) 中提供解密密码两次,然后在系统实际启动时再次提供解密密码。

您可以通过将密钥文件添加到 initrd 来避免这种情况,这样您只需在启动程序中输入解密密码即可。

Icon-warning.png
警告: 仅当您拥有包含 /boot加密根划分 (没有单独的/boot划分)! 添加到 initrd 的密钥可用于解密您的根划分,因此将 initrd 放在未加密的/boot划分上将破坏加密您的根划分。

在 Leap 和 Tumbleweed 中

以下步骤描述了如何设置密钥文件。请以 root 用户身份执行以下命令并编辑以下文件。

  1. 创建一个空密钥文件。
    user $ sudo touch /.root.key
    只有 root 用户才能读取此文件。
    user $ sudo chmod 600 /.root.key
  2. 生成密钥。
    user $ sudo dd if=/dev/urandom of=/.root.key bs=1024 count=1
  3. 将密钥文件添加为解密根划分的有效方法。
    user $ sudo cryptsetup luksAddKey /dev/sda1 /.root.key
    要查找系统上的设备名称,请使用
    user $ sudo lsblk
    在树中找到类型为 crypt 的条目。在其上方,您应该看到类型为 part 的条目。这就是您的划分名称。它可能有一个名称,如 sda2nvme0n1p2
  4. 编辑/etc/crypttab,找到与根划分相关的行,通过 UUID 并将密钥文件添加到第三列,其中可能已经显示 none
    cr_sda1 UUID=... /.root.key x-initrd.attach
    (同样,划分名称只是一个示例。)
  5. 配置 dracut 将密钥文件添加到 initrd
    echo -e 'install_items+=" /.root.key "' | sudo tee --append /etc/dracut.conf.d/99-root-key.conf > /dev/null
    (请注意双引号字符前后的空格。)
  6. 重建 initrd。
    user $ sudo dracut -f
/boot/initrd-*默认情况下只能由 root 用户读取。至少从 openSUSE-15.4 开始,这是 Dracut 创建 initrd 的方式。有关详细信息,请参阅 讨论

如果您有其他加密划分 (例如/home, swap等),您可以创建其他密钥来挂载它们 (登录后) 而无需输入密码。这与上述步骤 1-4 相同,只是您不需要写入x-initrd.attach在划分的/etc/crypttab行上,也不需要将密钥添加到 initrd (步骤 5),除非您还希望这些划分在启动时解密。无论如何,步骤 6 仍然是必需的才能应用更改。

在 MicroOS 中

这是您需要在 openSUSE MicroOS 中避免两次输入密码的方法

  1. 打开事务更新 shell。
    sudo transactional-update shell
  2. 按照“在 Leap 和 Tumbleweed 中”部分中的步骤以相同的方式操作。
  3. 按照上一节的步骤后,像往常一样关闭事务更新 shell。
    exit

现在,在下次系统启动时,系统应该只要求输入密码一次。

使用加密交换分区休眠时的附加步骤

如果您想休眠您的系统,并且交换分区也已加密,在这种情况下,请编辑/etc/crypttab(与上述步骤 4 相同) 使用交换分区的密钥,同时将 force 选项附加到第四列 (它看起来像 x-initrd.attach,force)。此选项将告诉 dracut 强制包含加密的交换分区,以便在重新启动时对其进行解密。

此外,配置 dracut 以确保将 resume 模块包含在 initrd 中

# echo -e 'add_dracutmodules+=" resume "' | sudo tee --append /etc/dracut.conf.d/99-resume.conf > /dev/null

(请注意双引号字符前后的空格。)

现在重复上述步骤 6 以重建 initrd。

不要忘记使用 Yast 将 resume=UUID=.... (使用包含交换分区的加密划分的 UUID) 行添加到启动加载程序的内核参数中。

要查找包含交换分区的加密分区 UUID,请使用 sudo lsblk -o +UUID。在树中找到一个类型为 crypt [SWAP] 的条目。UUID 看起来像 abc4eef4-f9ac-7788-abc0-cda56baabf08,并且位于同一行的右侧。

例如:

# lsblk -o +UUID
NAME MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS  UUID
...
└─vda4
     253:4    0    2G  0 part               9eed6cd3-2ba0-4269-9abf-79d92193587a
  └─cr_swap
     254:1    0    2G  0 crypt [SWAP]       1feea2b9-ae28-4ca5-8d3b-d71f389e30ee

在此示例中,resume 内核命令行选项的值应为 resume=UUID=1feea2b9-ae28-4ca5-8d3b-d71f389e30eeresume=/dev/mapper/cr_swap

密码locale

当前的 openSUSE 设置不支持为 grub2 早期阶段设置 locale。

请确保使用不需要特殊字符的密码,如果您不使用美国键盘布局,因为它们可能位于与您通常的布局不同的位置。

使用 TPM 2.0 无人值守启动

Icon-warning.png
警告
  • 这是一个实验性功能,现已弃用。它仅在 openSUSE Tumbleweed 和 MicroOS 中可用。
  • 有关新实现的文档,请在此处找到:[1]
  • fde-tools 需要一个包含 /boot 的加密根文件系统
  • 更新指南

借助 TPM 2.0 芯片,可以在无需输入任何密码的情况下自动解密根分区。其核心概念是将 LUKS 密钥与一组适当的 TPM 平台配置寄存器 (PCR) 密封。当系统达到某种状态时,启动加载程序(即 grub2)可以使用预期的 PCR 解封 LUKS 密钥并解密根分区。

默认情况下,测量的 PCR 为 0、2、4、7 和 9,并且该列表是可配置变量 FDE_SEAL_PCR_LIST,位于/etc/sysconfig/fde-tools。有关 TPM PCR 的详细信息,请查看 Linux TPM PCR Registry

在 grub2 解密根分区后,它会通过合成一个额外的 initrd 将解封的密钥进一步转发给 systemd,以便 systemd 可以重用解封的密钥。出于安全原因,grub2 在进入交互模式时(例如,菜单编辑器或 shell)会立即丢弃该密钥。

潜在用例

  • 无需干预即可启动远程服务器或云 VM
  • 在断电后自动启动本地服务器

先决条件

首先,密钥密封和解封基于 TPM 2.0。确保您的系统支持 TPM 2.0 并且 TPM 2.0 已在 BIOS/固件菜单中启用。

当前,所需的软件包是:pcr-oracle >= 0.4.5, fde-tools >= 0.6.5,和grub2具有最新的 TPM 2.0 支持,仅在 openSUSE Tumbleweed 和 MicroOS 中可用。这些软件包将来可能会合并到 openSUSE Leap 中。

安装后fde-tools,您可以使用以下命令检查系统是否支持 TPM 2.0 密封/解封

user $ sudo fdectl tpm-present

设置 LUKS2 分区

Icon-warning.png
警告:虽然 LUKS2 支持更高级的 PBKDF 算法,例如 Argon2,但请坚持使用PBKDF2目前。grub2 中的 Argon2 支持仍在开发中,并且使用 PBKDF 算法(pbkdf2 除外)可能会导致系统无法启动。如果需要,请参阅 使用现有的 LUKS2 分区 部分进行更改。

fde-tools依赖于 LUKS2 令牌来跟踪密封密钥的密钥槽,因此需要 LUKS2 格式的根分区。设置 LUKS2 分区可以在安装期间完成,也可以通过转换现有的 LUKS1 分区来完成。

在安装期间选择 LUKS2 格式

启用磁盘加密的引导设置将自动创建一个使用 PBKDF 算法格式化的 LUKS2 分区。无需进行其他更改。

或者,可以在专家分区器中设置分区。

在修改加密选项时,请选择PBKDF2用于 PBKDF,因为这是 grub2 目前支持的唯一算法。

更改所有加密分区的加密方法后,继续安装,您将拥有具有 LUKS2 分区的系统。


将现有的 LUKS1 分区转换为 LUKS2
Icon-warning.png
警告:请务必在转换之前备份您的数据。

由于不支持在线转换,您需要启动到Live OS或安装介质的Rescue 模式才能继续执行后续命令。

启动到 Live OS 后,使用 lsblk 检查分区布局。例如

# lsblk /dev/sda
NAME        MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS
sda           8:0    0   20G  0 disk  
├─sda1        8:1    0  512M  0 part  /boot/efi
├─sda2        8:2    0 18.3G  0 part  
│ └─cr_root 254:1    0 18.2G  0 crypt /var
│                                     /usr/local
│                                     /srv
│                                     /root
│                                     /opt
│                                     /home
│                                     /boot/grub2/x86_64-efi
│                                     /boot/grub2/i386-pc
│                                     /.snapshots
│                                     /
└─sda3        8:3    0  1.2G  0 part  
  └─cr_swap 254:0    0  1.2G  0 crypt [SWAP]

根据输出,/dev/sda2/dev/sda3 是加密分区,我们可以进一步使用 cryptsetup luksDump 检查 LUKS 版本,如下所示

# cryptsetup luksDump /dev/sda2
LUKS header information for /dev/sda2

Version:        1
Cipher name:    aes
Cipher mode:    xts-plain64
...

很明显,/dev/sda2 的 LUKS 版本是1,我们将使用以下命令将其转换为 LUKS2

# cryptsetup convert --type luks2 /dev/sda2

如果需要,请对其他 LUKS1 分区重复该过程。


使用现有的 LUKS2 分区

如果您已经在 `/` 目录中拥有 LUKS2 分区,则需要执行一些额外的步骤才能使系统与 GRUB 2 完全兼容。

截至 GRUB 2.12rc1(Tumbleweed 和 Leap 15.5 版本),从密码生成密钥支持的唯一算法是 pbkdf2。但是,默认的 cryptsetup 算法是 argon2id。

要检查密钥使用的算法,请使用以下命令

 $ sudo cryptsetup luksDump /dev/nvme0n1p7 | grep PBKDF

其中 /dev/nvme0n1p7 是您的加密设备。该命令将显示用于解锁设备的每个密钥使用的算法。例如

PBKDF:      argon2id
PBKDF:      argon2id

在这种情况下,第一个密钥槽使用 pbkdf2,而第二个密钥槽使用如 上面 解释的那样生成的密钥文件,而第一个密钥槽是在启动时用于访问设备的密码。

为了更改第一个密钥槽的 PBKDF 算法,请使用以下命令

$ sudo cryptsetup luksConvertKey --hash sha512 --pbkdf pbkdf2 /dev/nvme0n1p7 

将 /dev/nvme0n1p7 替换为您的设备。

此时,我们可以再次检查该算法

 $ sudo cryptsetup luksDump /dev/nvme0n1p7 | grep PBKDF
   PBKDF:      pbkdf2
   PBKDF:      argon2id

现在,重新生成 EFI GRUB 及其配置

$ sudo update-bootloader --reinit

使用 TPM 2.0 密封 LUKS 密钥

使用fde-tools,只需一个命令即可创建密封的 LUKS 密钥并更新 grub2 配置

user $ sudo fdectl regenerate-key

fdectl regenerate-key 将请求根分区的密码,因为它将把随机生成的密钥注册到根分区。然后,该命令将使用pcr-oracle预测 PCR 值并使用 TPM 2.0 密封密钥。如果一切顺利,密封的密钥将是/boot/efi/EFI/opensuse/sealed.tpm,和/boot/efi/EFI/opensuse/grub.cfg将如下所示

set btrfs_relative_path="yes"
tpm_record_pcrs 0-9
tpm2_key_protector_init -T $prefix/sealed.tpm
if ! cryptomount -u 597e2ffc6d6a4f32a6c2b7359542f90f --protector tpm2; then
    cryptomount -u 597e2ffc6d6a4f32a6c2b7359542f90f
fi
search --fs-uuid --set=root 1e71ec27-4de0-4bff-9436-8da3951508fa
set prefix=(${root})/boot/grub2
source "${prefix}/grub.cfg"

由于 TPM PCR 对更改敏感,因此在启动组件更新后(例如,shim、grub2 或 UEFI 固件),密钥解封可能会失败。在这种情况下,您可以使用

user $ sudo fdectl tpm-authorize

更新密封密钥的签名

更多 fdectl 命令

如果您想暂时禁用 TPM 密钥解封

user $ sudo fdectl tpm-disable

此命令从 grub2 配置中删除 TPM 密钥解封命令,同时保持 LUKS 密钥槽不变,以便用户可以使用以下命令恢复 TPM 密钥解封

user $ sudo fdectl tpm-enable

如果您想完全删除 TPM 密钥解封以及 LUKS 密钥槽

user $ sudo fdectl tpm-wipe

撤销授权策略

如果在启动组件(例如 grub2 或 shim 加载程序)中发现严重漏洞,建议删除与受影响组件关联的授权策略。但是,没有简单的方法可以撤销已经签名和授权的策略。最有效的方法是用 fdectl regenerate-key 替换密封的 LUKS 密钥

user $ sudo fdectl regenerate-key

由于旧的 LUKS 密钥已被替换,因此所有针对旧密钥的授权策略都会被无效化。

加密交换分区的其他步骤

假设您对根分区和交换分区使用相同的密码(openSUSE Tumbleweed 的默认设置),fde-tools可以同时处理这两个分区。

首先,将根分区和交换分区(例如,根分区为 /dev/sda2,交换分区为 /dev/sda3)添加到 FDE_DEVS 中,位于/etc/sysconfig/fde-tools如下所示

FDE_DEVS="/dev/sda2 /dev/sda3"

然后,调用 fdectl regenerate-key 将密封的密钥注册到根分区和交换分区。

user $ sudo fdectl regenerate-key

编辑/etc/crypttab添加/.fde-virtual.key到根分区和交换分区的第三列,以及 x-initrd.attach 到第四列

cr_root  UUID=597e2ffc-6d6a-4f32-a6c2-b7359542f90f  /.fde-virtual.key  x-initrd.attach
cr_swap  UUID=dbf1fd8a-d2ab-4e8d-a7bc-4e3493fadee7  /.fde-virtual.key  x-initrd.attach,force
最新的 grub2 在 openSUSE Tumbleweed 中可以解释/etc/crypttab并将解封的密钥转发到 initrd 中的文件路径,以便 systemd 可以获取转发的密钥来解密根分区。在这里,我们为根分区和交换分区指定相同的密钥路径,然后合成的密钥文件可以用于交换分区。由于它发生在 initrd 中,建议添加 x-initrd.attach 以显式解密两个分区中的 initrd。

最后一步是更新 initrd 和 grub2 配置以反映/etc/crypttab.

user $ sudo dracut --force
user $ sudo update-bootloader --refresh

中的更改。如果一切配置正确,grub2 将自动解锁根分区并将密钥安全地传递给 systemd 以进行进一步的启动。

已知问题

TPM2_Load 失败

一些用户在启动期间可能会遇到类似的错误消息

error: ../../grub-core/tpm2/module.c:796: Failed to load sealed key (TPM2_Load: 0x1df).

这可能是由存储在 TPM 持久句柄中的主密钥引起的0x81000001。要检查此句柄是否存在,请键入以下命令

user $ tpm2_getcap handles-persistent |grep 0x81000001

然后,使用此命令将其驱逐

user $ sudo tpm2_evictcontrol -C o -c 0x81000001


GRUB 级别解密在启动时太慢

默认情况下,在启动系统并在 GRUB 的提示符处键入密码以解密根分区后,密码验证可能需要很长时间(我的系统上大约 30 秒)。根据 此 Arch Linux wiki 页面,此解密过程缓慢是由于 openSUSE 在安装设置期间定义了一些与加密相关的参数。由于 Arch Linux 的解释已经很好,让我们直接进入要点来修复此行为。

1. 找到您的根分区或 LVM 分区,具体取决于您设置系统的方式。例如:/dev/nvme0n1p2

2. 输入此命令(以及相应的密码),并查找您想要影响的密钥的“Iterations”(迭代次数)值

# cryptsetup luksDump /dev/nvme0n1p2
[...]
Key Slot 0: ENABLED
        Iterations:             1920000
        Salt:                   [...]
        Key material offset:    [...]
        AF stripes:             [...]
[...]

3. 我们想将值“1920000”更改为较低的值。但不要太低,因为它会降低安全性。在 RFC-2898 及其升级版 RFC-8018 中建议的最小值是 1000(一千)。我个人建议从 100k(十万)开始,以 100k 的增量增加,直到您觉得解锁时间明显且低于无法忍受的水平。这是将值更改为 100k 的命令

# cryptsetup luksChangeKey --pbkdf-force-iterations 100000 --pbkdf pbkdf2 /dev/nvme0n1p2

请注意,cryptsetup 的默认算法已从 PBKDF2 切换到 Argon2,但它不一定适用于 GRUB,因此请确保在上述命令中指定了它!