跳转至内容

dm-crypt/Swap 加密

来自 ArchWiki

根据需求,可以使用不同的方法来加密 swap 分区,这些方法将在下面描述。一种在每次重启时重新初始化(使用新的加密)的交换加密设置可以提供更高的数据保护,因为它避免了可能很久以前就被交换出去但未被覆盖的敏感文件片段。然而,重新加密交换分区也通常会禁止使用暂停到磁盘功能。

无暂停到磁盘支持

在不希望使用暂停到磁盘(休眠)功能的系统中,可以设置 /etc/crypttab,以便在启动时使用纯 dm-crypt 和随机密码来解密交换分区。随机密码在关机时会被丢弃,只在交换设备上留下加密的、无法访问的数据。

要启用此功能,只需取消注释 /etc/crypttab 中以 swap 开头的行。将设备参数更改为您的交换设备名称。例如,它看起来会像这样

/etc/crypttab
# <name>  <device>     <password>     <options>
swap      /dev/sdX#    /dev/urandom   swap,cipher=aes-xts-plain64,size=512,sector-size=4096

这会将 /dev/sdX# 映射到 /dev/mapper/swap,作为一个交换分区,可以在 /etc/fstab 中像普通交换分区一样添加。如果您之前有一个未加密的交换分区,请不要忘记禁用它 - 或者通过将设备更改为 /dev/mapper/swap 来重用其 fstab 条目。默认选项对于大多数用途应该足够了。有关其他选项和每个列的解释,请参见 crypttab(5) 以及 cryptsetup FAQ 2.3


  • 如果先前用作交换分区的分区是一个 LUKS 分区,crypttab 不会覆盖该分区来创建交换分区。这是一种安全措施,以防止因 crypttab 中交换分区被意外误识别而导致数据丢失。要使用这样的分区,LUKS 头必须被覆盖一次
  • 交换分区设置有时会失败,请参见 systemd issue 10179
警告 指定设备的所有内容将永久性地删除。使用内核的简单命名作为交换设备名称是危险的,因为它们的命名顺序(例如 /dev/sda/dev/sdb)在每次启动时都会发生变化。选项有


按 ID 命名

要使用 by-id 持久设备命名而不是内核简单命名,首先识别交换设备

# find -L /dev/disk -samefile /dev/sdaX
/dev/disk/by-id/ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-partX
/dev/disk/by-id/wwn-0x60015ee0000b237f-partX

然后为(如果上面返回两个结果,选择其中一个)/dev/sdX# 示例分区使用持久引用

/etc/crypttab
# <name>  <device>                                                         <password>     <options>
swap      /dev/disk/by-id/ata-WDC_WD2500BEVT-22ZCT0_WD-WXE908VF0470-partX  /dev/urandom   swap,cipher=aes-xts-plain64,size=512,sector-size=4096

重启后激活加密交换,您会注意到运行 swapon -s 显示一个任意的设备映射器条目(例如 /dev/dm-1),而 lsblk 命令在 FSTYPE 列中显示 crypt。由于每次启动时都进行新的加密,/dev/mapper/swap 的 UUID 每次都会改变。

UUID 和 LABEL

将 crypttab swap 与简单的内核设备名称(如 /dev/sdX# 或甚至 /dev/disk/by-id/ata-SERIAL-partX)一起使用是危险的。设备名称或分区布局的微小更改将导致 /etc/crypttab 在下次启动时格式化您宝贵的数据。使用 PARTLABEL 或 PARTUUID 更安全,但如果您之后决定在不先删除 crypttab 条目的情况下将该分区用于其他用途,它也无法保护您。

通过提供真正的 UUID 或 LABEL 来识别正确分区的可靠性更高。默认情况下,这不起作用,因为 dm-crypt 和 mkswap 会简单地覆盖该分区上的任何内容,从而也删除 UUID 和 LABEL;但是,可以指定一个交换偏移量。这允许您创建一个非常小的、空的、虚假的(bogus)文件系统,其唯一目的是为交换加密提供持久的 UUID 或 LABEL。

创建一个您选择的带有标签的 文件系统

# mkfs.ext2 -L cryptswap /dev/sdX# 1M

设备名称后面的不寻常参数将文件系统大小限制为 1 MiB,为其留出加密交换的空间。

# blkid /dev/sdX#
/dev/sdX#: LABEL="cryptswap" UUID="b72c384e-bd3c-49aa-b7a7-a28ea81a2605" TYPE="ext2"

通过此设置,/dev/sdX# 现在可以轻松地通过 UUID 或 LABEL 进行识别,而不管其设备名称甚至分区号将来可能如何变化。剩下的只有 /etc/crypttab/etc/fstab 条目。例如,使用不同的加密选项

/etc/crypttab
# <name> <device>         <password>    <options>
swap     LABEL=cryptswap  /dev/urandom  swap,offset=2048,cipher=aes-xts-plain64,size=512,sector-size=4096

注意偏移量:它是 2048 个 512 字节的扇区(不受 dm-crypt 扇区大小的影响),因此为 1 MiB。这样,加密交换就不会影响文件系统的 LABEL/UUID,并且数据对齐也正常。

/etc/fstab
# <filesystem>    <dir>  <type>  <options>  <dump>  <pass>
/dev/mapper/swap  none   swap    defaults   0       0

使用此设置,cryptswap 将只尝试使用具有相应 LABEL 的分区,而不管其设备名称是什么。如果您决定将该分区用于其他用途,通过格式化它,cryptswap LABEL 也会消失,因此在下次启动时 /etc/crypttab 不会覆盖它。

在桌面环境中禁用休眠

桌面环境可能不会自动检测到交换分区是随机加密的,因此无法用于暂停到磁盘。

Xfce 可以通过运行以下命令配置为隐藏其“休眠”和“混合睡眠”按钮

$ xfconf-query -c xfce4-session -np /shutdown/ShowHibernate -t bool -s false
$ xfconf-query -c xfce4-session -np /shutdown/ShowHybridSleep -t bool -s false

有暂停到磁盘支持

以下三种方法是设置加密交换以支持暂停到磁盘(休眠)的替代方案。如果您应用了其中任何一种,请注意,系统交换出的关键数据可能会在较长时间内保留在交换分区中(即直到被覆盖)。为了降低这种风险,请考虑设置一个系统作业,例如每次系统正常关机时,与您选择的方法一起重新加密交换分区。

使用交换文件

交换文件可以放在加密设备内的文件系统中。按照 Swap#Swap file 中的交换文件创建说明进行操作,并根据 Power management/Suspend and hibernate#Configure the initramfs 配置休眠。

当与 基于 systemd 的 initramfs 和加密的根文件系统一起使用时,这是一种非常简单灵活的加密交换的方法。在设置好 加密的根文件系统 后,无需进一步设置即可创建、激活交换文件,并将其添加到 /etc/fstab 中以用于休眠。

注意 使用 resume= 内核参数时,它必须指向包含交换文件所在文件系统的已解锁/映射设备。

使用交换分区

注意 要使用当前被系统使用的分区,您必须先运行 swapoff /dev/device 作为 root 来禁用它,并确保从 /etc/crypttab 中删除任何指向该设备的行。

使用 cryptsetup-luksFormat(8) 为交换分区创建加密容器

# cryptsetup luksFormat --label swap /dev/device

将容器打开到 /dev/mapper/swap

# cryptsetup open /dev/disk/by-label/swap swap

在映射的分区内创建一个交换文件系统

# mkswap /dev/mapper/swap

启用映射分区进行分页

# swapon /dev/mapper/swap

如果未使用 systemd#GPT partition automounting,请通过添加以下行将映射分区添加到 /etc/fstab

/dev/mapper/swap none swap defaults 0 0

要设置系统从休眠中恢复,请使用 resume=/dev/mapper/swap 内核参数。有关详细信息,请参阅 Power management/Suspend and hibernate#Pass hibernate location to initramfs

使用 TPM

以下提供使用存储在 TPM 中的密钥进行无人值守的交换解密。

您可以使用 systemd-cryptenroll 将密钥注册到 Luks 容器和 TPM,并擦除先前创建的包含密码的密钥槽

# systemd-cryptenroll --tpm2-device auto /dev/device
# systemd-cryptenroll --wipe-slot password /dev/device

使用以下命令检查结果

# systemd-cryptenroll /dev/device
SLOT TYPE
   0 tpm2

本文章或章节需要扩充。

原因: 使用 TPM 作为交换密钥使其能够(可选地)自动化擦除/替换,例如在安装内核/需要重启时。 (在 Talk:Dm-crypt/Swap encryption 中讨论)

使用额外的密码短语或密钥文件

本文或本节正考虑移除。

原因: 本节标题具有误导性,因为它没有提供承诺的说明。其内容(警告模板)应移至更合适的部分,并删除本节以改善文章的逻辑流程。 (在 Talk:Dm-crypt/Swap encryption 中讨论)

上述 基本设置 的缺点是每次启动时都必须手动输入额外的交换分区密码短语。

警告 如果 /boot 未加密,请勿在此设置中使用密钥文件。请阅读此处报告的问题 here。或者,请按照 https://bbs.archlinux.org/viewtopic.php?id=120181 使用 gnupg 加密的密钥文件

在 initramfs 中解锁分区

要从加密的交换分区恢复,必须在 initramfs 中解锁加密分区。

mkinitcpio
基于 systemd 的 initramfs

使用带有 sd-encrypt mkinitcpio 钩子的默认 systemd 初始化 initramfs 时,需要执行以下任一操作:

例如,对于 TPM 支持的加密交换设备

/etc/crypttab.initramfs
swap UUID=56f8ee97-54b3-4a65-9282-688deb922527 none tpm2-device=auto
基于 busybox 的 initramfs

当使用带有 encrypt 钩子的基于 busybox 的 initramfs 时,请按照以下说明进行操作。

如果交换设备位于与根文件系统不同的设备上,则 encrypt 钩子不会打开它,即恢复将在 /etc/crypttab 可用之前发生,因此需要在 /etc/mkinitcpio.conf 中创建一个钩子,在恢复之前打开交换 LUKS 设备。

本文档或章节是合并到 dm-crypt/Specialties#Multiple non-root partitions 的候选。

注意: 相同的用例。 (在 Talk:Dm-crypt/Swap encryption 中讨论)
注意 此部分仅在使用 encrypt 钩子时适用,该钩子只能解锁单个设备(archlinux/mkinitcpio/mkinitcpio#231)。使用 sd-encrypt 可以解锁多个设备,请参阅 dm-crypt/System configuration#Using systemd-cryptsetup-generator

现在您需要创建一个钩子在启动时打开交换分区。您可以 安装 并配置 mkinitcpio-openswapAUR,或者按照以下说明进行。创建一个包含打开命令的钩子文件

本文或本节需要在语言、wiki 语法或风格方面进行改进。请参阅 Help:Style 获取参考。

原因: 手动创建与 AUR 包相同的文件没有意义。有什么区别吗?手动说明的动机是什么? (在 Talk:Dm-crypt/Swap_encryption 中讨论)
/etc/initcpio/hooks/openswap
run_hook ()
{
    cryptsetup open /dev/device swap
}
警告 挂载文件系统 是危险且具有破坏性的。当系统挂起时,不应从已挂载的文件系统中读取密钥文件。
注意 为最大限度地降低文件系统损坏的风险,脚本以 -o ro,noload 挂载;这些选项适用于 ext4,必须针对其他文件系统进行调整。

本文章或章节需要扩充。

原因: 添加不会导致数据丢失的说明。 (在 Talk:Dm-crypt/Swap encryption 中讨论)

通过输入密码打开交换设备,或者

/etc/initcpio/hooks/openswap
run_hook ()
{
    ## Optional: To avoid race conditions
    x=0;
    while [ ! -b /dev/mapper/root-device ] && [ $x -le 10 ]; do
       x=$((x+1))
       sleep .2
    done
    ## End of optional

    mkdir crypto_key_device
    mount -o ro,noload /dev/mapper/root-device crypto_key_device
    cryptsetup open --key-file crypto_key_device/path-to-the-key /dev/device swap
    umount crypto_key_device
}

通过从加密的根设备加载密钥文件来打开交换设备,或者

/etc/initcpio/hooks/openswap
run_hook ()
{
    ## Optional: To avoid race conditions
    x=0;
    while [ ! -b /dev/mapper/root-device ] && [ $x -le 10 ]; do
       x=$((x+1))
       sleep .2
    done
    ## End of optional

    dd if=/dev/mapper/root-device bs=key_size skip=block_number count=1 of=/swap-device.key 
    cryptsetup open --key-file /swap-device.key /dev/device swap
    rm /swap-device.key
}

通过直接从加密的根设备提取密钥文件而不挂载它来打开交换设备。

注意 此方法仅在没有压缩或加密的文件系统上可靠工作。如果使用了透明压缩(例如 Btrfs、F2FS、ZFS)或基于文件的加密(例如 ext4 上的 e4crypt)等功能,使用 `dd` 读取密钥文件将返回不正确的数据。

在 ext4 上,可以通过以下方式确定块号

debugfs /dev/mapper/root-device
extents /path/to/keyfile

相关块号将显示在输出的 Physical 列下。

在这种情况下,密钥的大小不应超过一个块(ext4 默认为 4 KiB);否则,文件可能会碎片化,并且解锁可能会失败。

注意 如果密钥文件太小(通常小于约 200 B),ext4 可能会将其作为内联数据存储在 inode 中。这会阻止使用基于块的访问(例如使用 dd)读取它。为避免此问题,您可以创建一个更大的文件(例如 4 KiB),然后将其缩小到所需大小。一旦分配了块,ext4 就不会将数据移回 inode。

在某些计算机上,当 mkinitcpio 尝试在解密过程和设备枚举完成之前挂载设备时,可能会发生竞争条件。注释掉的 *可选* 块会将启动过程延迟最多 2 秒,直到根设备准备好挂载。

注意 如果交换分区位于固态硬盘(SSD)上,并且需要 Discard/TRIM,则必须在上面的 openswap 钩子中的 cryptsetup 行中添加 --allow-discards 选项。有关 discard 的更多信息,请参阅 Dm-crypt/Specialties#Discard/TRIM support for solid state drives (SSD)SSD。此外,您必须在 fstab 条目中为交换设备添加 'discard' 挂载选项。

然后创建并编辑钩子设置文件

/etc/initcpio/install/openswap
build ()
{
   add_runscript
}
help ()
{
cat<<HELPEOF
  This opens the swap encrypted partition /dev/device in /dev/mapper/swap
HELPEOF
}

/etc/mkinitcpio.confHOOKS 数组中添加 openswap 钩子,放在 filesystem 之前,但在 encrypt 之后。不要忘记在 openswap 之后添加 resume 钩子。

HOOKS=(... encrypt openswap resume filesystems ...)

重新生成 initramfs.

在启动时,openswap 钩子将打开交换分区,以便内核恢复可以使用它。如果您使用特殊的恢复休眠钩子,请确保它们放在 HOOKS 数组中的 openswap 之后。请注意,由于 initramfs 打开交换分区,在这种情况下不需要 /etc/crypttab 中的交换条目。

dracut

创建一个密钥文件

# dd bs=512 count=4 if=/dev/random iflag=fullblock | install -m 0600 /dev/stdin /etc/cryptsetup-keys.d/swap.key

将密钥文件添加到 LUKS

# cryptsetup luksAddKey /dev/device /etc/cryptsetup-keys.d/swap.key

配置 dracut 以包含 resume 模块并将 swap.key 文件添加到 initramfs(另请参阅 dracut#Hibernation

/etc/dracut.conf.d/resume-from-hibernate.conf
add_dracutmodules+=" resume "
install_items+=" /etc/cryptsetup-keys.d/swap.key "

重新生成 initramfs.

rd.luks.namerd.luks.key(替换交换分区的 UUID)条目添加到您的内核命令行。您的内核命令现在可能看起来像这样

kernel /vmlinuz-linux cryptdevice=/dev/sda2:root root=/dev/mapper/root resume=/dev/mapper/swap rd.luks.name=fd839505-3213-4603-9a70-c5a96a24768f=swap rd.luks.key=/etc/cryptsetup-keys.d/swap.key ro

LUKS上的LVM

如果交换卷位于在 initramfs 中激活的卷组中,只需按照 Power management/Suspend and hibernate#Hibernation 中的说明进行操作。

已知问题

性能提示

本文或本节正考虑移除。

原因: 此页面是关于配置的,设备加密由 dm-crypt/Device encryption 覆盖。 (在 Talk:Dm-crypt/Swap encryption 中讨论)

上面的示例使用 AES-256-XTS,这与 cryptsetup 对普通磁盘加密的默认算法相同。由于计算机普遍支持 AES 加速,该算法不太可能成为性能瓶颈。不过,如果用户确实拥有一个非常快的交换盘,可以考虑使用 AES-128-XTS,由于舍去了一些轮次,它的速度通常快 40%:将 size=512 替换为 size=256。AES-128 的密钥大小和轮数对于非量子目的提供了足够的安全性,正如 Aumasson 在《Too Much Crypto》中论述的。(一个减少轮数的 AES-256-XTS 将是速度和量子安全性的完美结合,但它不是标准的,因此不可用。)

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.