dm-crypt/交换分区加密
根据需求,可以使用不同的方法来加密 交换分区,以下将对此进行描述。在重启时重新初始化交换分区加密(使用新的加密)的设置提供了更高的数据保护,因为它避免了可能很久以前被换出而没有被覆盖的敏感文件片段。然而,重新加密交换分区通常也禁止使用休眠到磁盘功能。
不支持休眠到磁盘
在不需要休眠到磁盘(休眠)功能的系统中,可以设置 /etc/crypttab
以在启动时使用随机密码和 plain 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 点。
/dev/sda
,/dev/sdb
)在每次启动时都会更改。可选项有- 使用
by-id
和by-path
路径。然而,这些都容易受到硬件更改的影响。请参阅 持久块设备命名#by-id 和 by-path。 - 使用 PARTLABEL。
- 使用 LVM 逻辑卷的名称。
- 使用 #UUID 和 LABEL 中描述的方法。标签和 UUID 不能 直接使用,因为每次启动时都会使用
mkswap
重新创建和重新加密交换设备,请参阅 cryptsetup FAQ。
要使用 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 交换分区和简单的内核设备名称(如 /dev/sdX#
甚至 /dev/disk/by-id/ata-SERIAL-partX
)是很危险的。您的设备名称或分区布局的微小更改,/etc/crypttab
将在下次启动时格式化您的宝贵数据。如果您使用 PARTUUID,然后决定将该分区用于其他用途,而没有首先删除 crypttab 条目,情况也是如此。
更可靠的方法是通过给正确的分区一个真正的 UUID 或 LABEL 来识别它。默认情况下,这不起作用,因为 dm-crypt 和 mkswap
会简单地覆盖该分区上的任何内容,这将删除 UUID 和 LABEL;但是,可以指定交换偏移量。这允许您创建一个非常小的、空的、伪造的文件系统,其唯一目的是为交换分区加密提供持久的 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
支持休眠到磁盘
以下三种方法是设置用于休眠到磁盘(休眠)的加密交换分区的替代方法。如果您应用其中任何一种方法,请注意系统换出的关键数据可能会在交换分区中停留很长时间(即直到它被覆盖)。为了降低这种风险,请考虑设置一个系统作业来重新加密交换分区,例如,每次系统进入常规关机时,以及您选择的方法。
LVM on LUKS
如果交换卷位于 initramfs 中激活的卷组中,只需按照 电源管理/挂起和休眠#休眠 中的说明进行操作即可。
使用交换分区
swapoff /dev/device
来禁用它,并确保删除 /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
如果不使用 systemd#GPT 分区自动挂载,请通过添加以下行将映射的分区添加到 /etc/fstab
/dev/mapper/swap none swap defaults 0 0
要设置您的系统从休眠状态恢复,请使用 resume=/dev/mapper/swap
内核参数。有关详细信息,请参阅 电源管理/挂起和休眠#将休眠位置传递给 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
未加密,请不要将此设置与密钥文件一起使用。请阅读 此处 报告的问题。或者,按照 https://bbs.archlinux.org/viewtopic.php?id=120181 的说明使用 gnupg 加密的密钥文件在 initramfs 中解锁分区
要从加密的交换分区恢复,必须在 initramfs 中解锁加密分区。
mkinitcpio
基于 systemd 的 initramfs
当将基于 systemd 的 initramfs 与 sd-encrypt mkinitcpio 钩子一起使用时,可以
- 指定适当的
rd.luks.uuid=
内核参数 以解锁交换分区,或者 - 编辑
crypttab.initramfs
并 重新生成 initramfs。
例如,对于 TPM 支持的加密交换设备
/etc/crypttab.initramfs
swap UUID=56f8ee97-54b3-4a65-9282-688deb922527 none tpm2-device=auto
基于 busybox 的 initramfs
当将默认的基于 busybox 的 initramfs 与 encrypt 钩子一起使用时,请按照以下说明进行操作。
如果交换设备与根文件系统的设备不同,则 encrypt
钩子不会打开它,即将在可以使用 /etc/crypttab
之前进行恢复,因此需要在 /etc/mkinitcpio.conf
中创建一个钩子以在恢复之前打开交换 LUKS 设备。
encrypt
钩子时适用,该钩子只能解锁单个设备 (archlinux/mkinitcpio/mkinitcpio#231)。使用 sd-encrypt
可以解锁多个设备,请参阅 dm-crypt/System configuration#使用 systemd-cryptsetup-generator。现在您必须创建一个钩子以在启动时打开交换分区。您可以 安装 和配置 mkinitcpio-openswapAUR,或按照以下说明进行操作。创建一个包含 open 命令的钩子文件
/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 /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 }
用于通过从加密的根设备加载密钥文件来打开交换设备。
在某些计算机上,当 mkinitcpio 尝试在解密过程和设备枚举完成之前挂载设备时,可能会发生竞争条件。注释掉的可选块会将启动过程延迟最多 2 秒,直到根设备准备好挂载。
--allow-discards
添加到上面 openswap 钩子中的 cryptsetup 行。有关丢弃的更多信息,请参阅 Dm-crypt/Specialties#固态硬盘 (SSD) 的 Discard/TRIM 支持 或 SSD。此外,您必须将挂载选项“discard”添加到交换设备的 fstab 条目中。然后创建并编辑钩子设置文件
/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
之后。请注意,由于 initrd 打开了交换分区,因此在这种情况下,/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#休眠)
/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
使用交换文件
交换文件可用于在现有分区内保留交换空间,也可以在加密块设备的分区内设置。
按照 Swap#交换文件 中的交换文件创建说明进行操作,并根据 电源管理/挂起和休眠#配置 initramfs 设置休眠。
- 从交换文件恢复时,
resume
参数必须指向包含交换文件的文件系统的已解锁/映射设备。 - 确保 mkinitcpio 的 resume 钩子在交换分区所在的设备被解锁后运行,方法是将
resume
放在HOOKS
数组中的encrypt
之后。
已知问题
- 日志中显示
Stopped (with error) /dev/dm-1
。请参阅 systemd 问题 1620。