dm-crypt/Swap 加密
根据需求,可以使用不同的方法来加密 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)在每次启动时都会发生变化。选项有- 使用
by-id和by-path路径。然而,这两者都容易受到硬件更改的影响。请参见 Persistent block device naming#by-id and by-path。 - 使用 PARTLABEL 或 PARTUUID。
- 使用 LVM 逻辑卷的名称。
- 使用 #UUID and LABEL 中描述的方法。标签和 UUID 不能直接使用,因为每次启动时都会使用
mkswap重新创建和重新加密交换设备,请参见 cryptsetup FAQ,但通过间接方法可以实现。
按 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
使用额外的密码短语或密钥文件
上述 基本设置 的缺点是每次启动时都必须手动输入额外的交换分区密码短语。
/boot 未加密,请勿在此设置中使用密钥文件。请阅读此处报告的问题 here。或者,请按照 https://bbs.archlinux.org/viewtopic.php?id=120181 使用 gnupg 加密的密钥文件在 initramfs 中解锁分区
要从加密的交换分区恢复,必须在 initramfs 中解锁加密分区。
mkinitcpio
基于 systemd 的 initramfs
使用带有 sd-encrypt mkinitcpio 钩子的默认 systemd 初始化 initramfs 时,需要执行以下任一操作:
- 指定适当的
rd.luks.uuid=内核参数来解锁交换分区,或者 - 编辑
crypttab.initramfs并 重新生成 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 设备。
encrypt 钩子时适用,该钩子只能解锁单个设备(archlinux/mkinitcpio/mkinitcpio#231)。使用 sd-encrypt 可以解锁多个设备,请参阅 dm-crypt/System configuration#Using systemd-cryptsetup-generator。现在您需要创建一个钩子在启动时打开交换分区。您可以 安装 并配置 mkinitcpio-openswapAUR,或者按照以下说明进行。创建一个包含打开命令的钩子文件
/etc/initcpio/hooks/openswap
run_hook ()
{
cryptsetup open /dev/device swap
}
通过输入密码打开交换设备,或者
/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
}
通过直接从加密的根设备提取密钥文件而不挂载它来打开交换设备。
在 ext4 上,可以通过以下方式确定块号
debugfs /dev/mapper/root-device extents /path/to/keyfile
相关块号将显示在输出的 Physical 列下。
在这种情况下,密钥的大小不应超过一个块(ext4 默认为 4 KiB);否则,文件可能会碎片化,并且解锁可能会失败。
在某些计算机上,当 mkinitcpio 尝试在解密过程和设备枚举完成之前挂载设备时,可能会发生竞争条件。注释掉的 *可选* 块会将启动过程延迟最多 2 秒,直到根设备准备好挂载。
--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.conf 的 HOOKS 数组中添加 openswap 钩子,放在 filesystem 之前,但在 encrypt 之后。不要忘记在 openswap 之后添加 resume 钩子。
HOOKS=(... encrypt openswap resume filesystems ...)
在启动时,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 "
将 rd.luks.name 和 rd.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 中的说明进行操作。
已知问题
- 日志中出现
Stopped (with error) /dev/dm-1。请参阅 systemd issue 1620。
性能提示
上面的示例使用 AES-256-XTS,这与 cryptsetup 对普通磁盘加密的默认算法相同。由于计算机普遍支持 AES 加速,该算法不太可能成为性能瓶颈。不过,如果用户确实拥有一个非常快的交换盘,可以考虑使用 AES-128-XTS,由于舍去了一些轮次,它的速度通常快 40%:将 size=512 替换为 size=256。AES-128 的密钥大小和轮数对于非量子目的提供了足够的安全性,正如 Aumasson 在《Too Much Crypto》中论述的。(一个减少轮数的 AES-256-XTS 将是速度和量子安全性的完美结合,但它不是标准的,因此不可用。)