dm-crypt/系统配置
- 如果需要远程解锁 root 分区或其他早期启动的文件系统(无头机器,远程服务器...),请遵循 dm-crypt/Specialties#远程解锁 root 分区(或其他分区) 中的特定说明。
- 为了方便在配置文件中输入 UUID、PARTUUID 等,您可以安装并使用支持插入命令输出的文本编辑器(例如,nano,使用
Ctrl+t
;Vim 或 Neovim,使用:read
;或 mcedit,使用Alt+u
),并向其传递合适的 lsblk 或 blkid 命令。或者,您可以安装一个终端复用器并使用其复制和粘贴功能。
在早期用户空间解锁
启动加密的 root 卷需要 initramfs 包含必要的工具,以便早期用户空间解锁该卷。关于解锁内容的说明通常通过内核参数传递。
以下章节描述了如何配置 mkinitcpio,并列出了所需的内核参数。
mkinitcpio
根据具体情况,需要启用以下 mkinitcpio hooks 的子集
busybox | systemd | 用例 |
---|---|---|
encrypt
|
sd-encrypt
|
当 root 分区被加密或加密分区需要在 root 分区之前挂载时需要。在其他情况下不需要,因为像 /etc/crypttab 这样的系统初始化脚本已经处理解锁其他非 root 分区。此 hook 必须放置在 udev 或 systemd hook 之后。 |
keyboard
|
使键盘在早期用户空间中工作所必需。 提示: 对于使用不同硬件配置启动的系统(例如,带有外接键盘与内置键盘的笔记本电脑或无头系统),将此 hook 放在
autodetect 之前有助于始终包含所有键盘驱动程序。 否则,只有在创建映像时连接了外部键盘,外部键盘才会在早期用户空间中工作。 | |
keymap
|
sd-vconsole
|
为输入加密密码提供非美国键盘布局支持;它必须在 encrypt hook 之前,否则您将需要使用默认的美国键盘布局输入加密密码。在 /etc/vconsole.conf 中设置您的键盘布局,请参阅控制台键盘配置#持久配置。 |
consolefont
|
在早期用户空间中加载备用控制台字体。在 /etc/vconsole.conf 中设置您的字体,请参阅Linux 控制台#持久配置。 |
其他需要的 hooks 应该从系统安装过程中遵循的其他手动步骤中明确。
/etc/mkinitcpio.conf
进行任何更改后,请记住重新生成 initramfs。示例
使用 encrypt
hook 的典型 /etc/mkinitcpio.conf
配置
/etc/mkinitcpio.conf
... HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt lvm2 filesystems fsck) ...
使用基于 systemd 的 initramfs 和 sd-encrypt
hook 的配置
/etc/mkinitcpio.conf
... HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck) ...
内核参数
您需要指定的内核参数取决于正在使用 encrypt
hook 还是 sd-encrypt
hook。 root
和 resume
的指定方式对于两者是相同的。
root
root=
参数指定实际(解密)root 文件系统的 device
root=device
- 如果文件系统直接在解密设备文件上格式化,则这将是
/dev/mapper/dmname
。 - 如果首先激活 LVM 并且包含加密的逻辑 root 卷,则上述形式也适用。
- 如果 root 文件系统包含在完全加密的 LVM 的逻辑卷中,则其设备映射器的一般形式为
root=/dev/volumegroup/logicalvolume
。
- 当使用
sd-encrypt
hook 和GPT 分区自动挂载时,可以省略root=
参数的规范。 请参阅LUKS on a partition。 - 当使用 GRUB 并使用 grub-mkconfig 生成
grub.cfg
时,不需要手动指定root=
参数。 grub-mkconfig 将确定解密 root 文件系统的正确 UUID,并自动将其添加到grub.cfg
中。
resume
resume=device
device
是用于挂起到磁盘的解密(交换)文件系统的设备文件。 如果交换分区位于单独的分区上,则其形式为/dev/mapper/swap
。 另请参阅dm-crypt/Swap encryption。
使用 encrypt hook
encrypt
hook 不支持- 解锁多个加密磁盘 (archlinux/mkinitcpio/mkinitcpio#231)。 在 initramfs 中只能解锁一个设备。
- 使用分离的 LUKS 头 (archlinux/mkinitcpio/mkinitcpio#234)。
- 设置 crypttab 支持的其他选项。
cryptdevice
这指定了冷启动时包含加密 root 分区的设备。 它由 encrypt
hook 解析,以识别哪个设备包含加密系统
cryptdevice=device:dmname:options
device
是支持加密设备的设备路径。 强烈建议使用持久性块设备命名。dmname
是解密后分配给设备的设备映射器名称,它将以/dev/mapper/dmname
的形式提供。options
(可选)是以逗号分隔的选项,例如,用于 TRIM 支持。 如果不需要任何选项,请省略此参数(使用cryptdevice=device:dmname
)。- 如果 LVM 包含加密的 root 分区,则首先激活 LVM,并且包含加密 root 分区的逻辑卷的卷组充当 device。 之后是将被映射到 root 分区的相应卷组。 该参数的形式为
cryptdevice=/dev/vgname/lvname:dmname
。
cryptkey
cryptkey=
参数。 然后,系统将在启动时提示您输入密码短语。此参数指定密钥文件的位置,并且 encrypt
hook 需要它来读取此类密钥文件以解锁 cryptdevice
(除非密钥位于默认位置,请参见下文)。 它可以有三个参数集,具体取决于密钥文件是作为特定设备中的文件、特定位置开始的位流还是 initramfs 中的文件存在。
对于设备中的文件,格式为
cryptkey=device:fstype:path
device
是密钥所在的原始块设备。 强烈建议使用持久性块设备命名。fstype
是device
的文件系统类型(或 auto)。path
是设备中密钥文件的绝对路径。
示例:cryptkey=LABEL=usbstick:vfat:/secretkey
对于设备上的位流,密钥的位置通过以下方式指定
cryptkey=device:offset:size
其中 offset 和 size 以字节为单位。 例如,cryptkey=UUID=ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ:0:512
读取从设备开头开始的 512 字节密钥文件。
:
,则必须使用反斜杠 \
对其进行转义。 在这种情况下,cryptkey 参数将如下所示: cryptkey=/dev/disk/by-id/usb-123456-0\:0:0:512
,用于 ID 为 usb-123456-0:0
的 USB 密钥。cryptkey=rootfs:path
示例:cryptkey=rootfs:/secretkey
另请注意,如果未指定 cryptkey
,则默认值为 /crypto_keyfile.bin
(在 initramfs 中)。[2]
另请参阅dm-crypt/设备加密#密钥文件。
crypto
此参数专门用于将 dm-crypt plain 模式选项传递给 encrypt hook。
它采用以下形式
crypto=hash:cipher:keysize:offset:skip
这些参数直接与 cryptsetup 选项相关。 请参阅dm-crypt/设备加密#Plain 模式的加密选项。
对于仅使用 plain 默认选项加密的磁盘,必须指定 crypto
参数,但每个条目都可以留空
crypto=::::
参数的一个具体示例是
crypto=sha512:twofish-xts-plain64:512:0:
使用 systemd-cryptsetup-generator
systemd-cryptsetup-generator 是一个 systemd 单元生成器,它读取 内核参数 和 /etc/crypttab
的子集,用于解锁加密设备。 有关更多详细信息及其支持的所有选项,请参阅 systemd-cryptsetup-generator(8) 手册页。
当使用 sd-encrypt
mkinitcpio hook 或 systemd
dracut 模块时,systemd-cryptsetup-generator 在 initramfs 阶段运行。
在下面,我们描述了 systemd-cryptsetup-generator 解释的一些 内核参数。
- 如果文件
/etc/crypttab.initramfs
存在,它将被添加到 initramfs 中作为/etc/crypttab
,您可以在其中指定需要在 initramfs 阶段解锁的设备。 有关语法,请参阅 #crypttab。 如果/etc/crypttab.initramfs
不存在,则 initramfs 中将没有/etc/crypttab
,并且需要通过下面列出的内核参数指定可解锁的设备。 /etc/crypttab.initramfs
不限于仅使用像rd.luks
这样的 UUID。 您可以使用任何持久性块设备命名方法。- 如果满足systemd#GPT 分区自动挂载的所有先决条件,则可以通过使用
/dev/gpt-auto-root-luks
来避免在/etc/crypttab.initramfs
中硬编码 root 块设备标识符(例如,UUID、PARTUUID 等)。 - 在启动期间输入的密码由 systemd-cryptsetup(8) 缓存在内核密钥环中,因此,如果可以使用相同的密码解锁多个设备(包括在启动后解锁的 crypttab 中的设备),则您只需输入每个密码一次。
- 可以多次指定所有
rd.luks
参数以解锁多个 LUKS 加密卷。 rd.luks
参数仅支持解锁 LUKS 设备。 要解锁 plain dm-crypt 设备,您必须在/etc/crypttab.initramfs
中指定它。 有关语法,请参阅 #crypttab。
/etc/crypttab
或 /etc/crypttab.initramfs
与 luks.*
或 rd.luks.*
参数一起使用,则只有在内核命令行上指定的那些设备将被激活,您将看到 Not creating device 'devicename' because it was not specified on the kernel command line.
。 这是因为 luks.*
或 rd.luks.*
参数控制从 crypttab 激活哪些设备。 要激活 /etc/crypttab
中的所有设备,请不要指定任何 luks.*
参数并使用 rd.luks.*
。 要激活 /etc/crypttab.initramfs
中的所有设备,请不要指定任何 luks.*
或 rd.luks.*
参数。rd.luks.uuid
rd.luks.name
时,可以省略 rd.luks.uuid
。rd.luks.uuid=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
使用此标志指定启动时要解密的设备的UUID。
默认情况下,映射的设备将位于 /dev/mapper/luks-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
,其中 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 是 LUKS 分区的 UUID。
rd.luks.name
rd.luks.uuid
。rd.luks.name=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=name
指定 LUKS 分区打开后映射设备的名称,其中 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 是 LUKS 分区的 UUID。 这等效于 encrypt
的 cryptdevice
的第二个参数。
例如,指定 rd.luks.name=12345678-9abc-def0-1234-56789abcdef0=root
会导致 UUID 为 12345678-9ABC-DEF0-1234-56789ABCDEF0
的解锁 LUKS 设备位于 /dev/mapper/root
。
rd.luks.key
指定用于解密由其 UUID 指定的设备的密码文件的位置。 与 encrypt
hook 参数 cryptkey
不同,没有默认位置。
如果密钥文件包含在 initramfs 中
rd.luks.key=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=/path/to/keyfile
或
rd.luks.key=/path/to/keyfile
/etc/cryptsetup-keys.d/name.key
,则可以省略整个 rd.luks.key
参数。如果密钥文件位于另一个设备上
rd.luks.key=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=/path/to/keyfile:UUID=ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ
将 UUID=ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ
替换为密钥文件所在设备的标识符。
- 如果文件系统类型与您的 root 文件系统不同,则必须在 initramfs 中包含其内核模块。
- 默认情况下,带有另一个设备上的密钥文件的
rd.luks.key
不会回退到在设备不可用时询问密码。 要回退到密码提示,请在rd.luks.options
中指定keyfile-timeout=
选项。 例如,对于 10 秒超时rd.luks.options=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=keyfile-timeout=10s
rd.luks.options
rd.luks.options=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=options
或
rd.luks.options=options
为由其 UUID 指定的设备设置选项,或者,如果未指定,则为所有其他地方未指定的 UUID 设置选项(例如,crypttab)。
此参数类似于 crypttab 的 options 字段。 格式相同——选项用逗号分隔,带有值的选项使用 option=value
指定。 这大致等效于 encrypt
的 cryptdevice
的第三个参数。
例如
rd.luks.options=timeout=10s,discard,password-echo=no,tries=1
超时
有两个选项会影响启动期间输入密码的超时
rd.luks.options=timeout=mytimeout
指定查询密码的超时时间rootflags=x-systemd.device-timeout=mytimeout
指定 systemd 应等待 rootfs 设备出现多长时间才放弃(默认为 90 秒)
如果您想完全禁用超时,请将两个超时都设置为零
rd.luks.options=timeout=0 rootflags=x-systemd.device-timeout=0
密码回显
当用户键入密码时,systemd-cryptsetup 默认情况下为每个键入的字符输出星号 (*
)。 这与 encrypt
hook 不同,后者不输出任何内容。 要静默输出,请设置 password-echo=no
选项
rd.luks.options=password-echo=no
可信平台模块和 FIDO2 密钥
如果您的系统中有可用的 TPM2 芯片,或者您使用 FIDO2 兼容的安全密钥,则可以使用它来自动解锁您的卷,而无需使用密码或密钥文件。
设置
- 对于 TPM2 芯片:
rd.luks.options=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=tpm2-device=auto
- 对于 FIDO2 密钥:
rd.luks.options=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=fido2-device=auto
除了 rd.luks.uuid
或 rd.luks.name
之外
或者,可以使用 /etc/crypttab.initramfs
,这样可以避免指定任何内核选项。
/etc/crypttab.initramfs
root UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX none tpm2-device=auto
/etc/crypttab.initramfs
进行任何更改后,请记住重新生成 initramfs。这里,加密卷以名称 root
挂载(出现在 /dev/mapper/root
中),通过存储设备的 UUID 挂载,无需密码,并从 TPM2 设备检索密钥。
请注意,必须在密码字段顺序中提供 none
才能使用 TPM2 设备,否则给定的值将用作密码或密钥,如果它不起作用,它会要求您在启动期间键入密码,而不会尝试从 TPM2 设备加载密钥。
如果如上所示通过 UUID 指定设备,请确保它是底层(加密的)存储设备的 UUID,而不是在其他地方指定为 root 文件系统的解密卷的 UUID。
rd.luks.data
当使用分离的 LUKS 头时,指定带有加密数据的块设备。 必须与 rd.luks.options
一起使用以指定头文件位置。
有关详细信息和说明,请参阅dm-crypt/Specialties#使用分离的 LUKS 头的加密系统。
在后期用户空间解锁
crypttab
/etc/crypttab
(加密设备表)文件类似于 fstab 文件,其中包含系统启动期间要解锁的加密设备列表。 此文件可用于自动挂载加密的交换设备或辅助文件系统。
crypttab
在 fstab
之前读取,以便可以在挂载内部文件系统之前解锁 dm-crypt 容器。 请注意,crypttab
在系统启动后读取,因此它不能替代使用 mkinitcpio hooks 和 使用内核参数配置它们 来解锁加密分区,就像加密 root 分区的情况一样。 启动时对 crypttab
的处理由 systemd-cryptsetup-generator(8) 自动完成。
有关详细信息,请参阅 crypttab(5),阅读以下示例,以及 #启动时挂载 部分,以获取有关如何使用 UUID 挂载加密设备的说明。
- 如果指定了
nofail
选项,则在键入密码时密码输入屏幕可能会消失。 因此,nofail
应该仅与密钥文件一起使用。 - 对于 dm-crypt plain 模式 设备,必须显式设置
plain
选项,以强制 systemd-cryptsetup(8) 识别它们。 请参阅 systemd issue 442。
/etc/crypttab
# Example crypttab file. Fields are: name, underlying device, passphrase, cryptsetup options. # Mount /dev/lvm/swap re-encrypting it with a fresh key each reboot swap /dev/lvm/swap /dev/urandom swap,cipher=aes-xts-plain64,size=256,sector-size=4096 # Mount /dev/lvm/tmp as /dev/mapper/tmp using plain dm-crypt with a random passphrase, making its contents unrecoverable after it is dismounted. tmp /dev/lvm/tmp /dev/urandom tmp,cipher=aes-xts-plain64,size=256 # Mount /dev/lvm/home as /dev/mapper/home using LUKS, and prompt for the passphrase at boot time. home /dev/lvm/home # Mount /dev/sdb1 as /dev/mapper/backup using LUKS, with a passphrase stored in a file. backup /dev/sdb1 /home/alice/backup.key # Unlock /dev/sdX using the only available TPM, naming it myvolume myvolume /dev/sdX none tpm2-device=auto
要在编辑 crypttab 后立即对其进行测试,请使用 daemon-reload 重新加载 systemd 管理器配置,并启动新生成的 systemd-cryptsetup@name.service
。
# cryptsetup status name
/dev/mapper/name is active. type: ... cipher: ... keysize: ... bits key location: ... device: /dev/sdxN sector size: ... offset: ... sectors size: ... sectors mode: ... flags: ...
有关 systemd-cryptsetup@name.service
的更多信息,请参阅 #按需挂载。
启动时挂载
如果您想在启动时挂载加密驱动器,请在 /etc/crypttab
中输入设备的 UUID。 您可以使用命令 lsblk -f
获取 UUID(分区),并以以下形式将其添加到 crypttab
中
/etc/crypttab
externaldrive UUID=2f9a8428-ac69-478a-88a2-4aa458565431 none timeout=180
第一个参数是您首选的加密驱动器的设备映射器名称。 选项 none
将在启动期间触发提示,以键入用于解锁分区的密码短语。 timeout
选项定义了在启动期间输入解密密码的超时时间(以秒为单位)。
crypttab
中的设备使用先前输入的密码,则可以将第三个参数设置为 none
,并且将自动使用缓存的密码。crypttab
中的 timeout
选项仅确定允许输入加密设备密码的时间量。 此外,systemd 还有一个默认超时时间,它确定允许设备可用的时间量(默认为 90 秒),这与密码计时器无关。 因此,即使 crypttab
中的 timeout
选项设置为大于 90 秒的值(或者它处于默认值 0,表示无限时间),systemd 仍然只会等待最多 90 秒以解锁设备。 为了更改 systemd 等待设备可用的时间,可以在 fstab 中为所述设备设置选项 x-systemd.device-timeout
(请参阅 systemd.mount(5))。 因此,可能需要使 crypttab
中 timeout
选项的时间量等于 fstab 中每个启动时挂载的设备的 x-systemd.device-timeout
选项的时间量。使用密钥文件解锁
如果辅助文件系统的密钥文件本身存储在加密的 root 分区中,则在系统断电时它是安全的,并且可以在启动期间通过 crypttab 获取它以自动解锁挂载。 例如,解锁由 UUID 指定的加密
/etc/crypttab
home-crypt UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /etc/cryptsetup-keys.d/home-crypt.key
- 如果未指定密钥文件,systemd-cryptsetup(8) 将自动尝试从
/etc/cryptsetup-keys.d/name.key
和/run/cryptsetup-keys.d/name.key
加载它。[3] - 如果您更喜欢使用
--plain
模式块设备,则解锁它所需的加密选项在/etc/crypttab
中指定。 在这种情况下,请注意应用 crypttab 中提到的 systemd 解决方法。
然后使用设备映射器的名称(在 /etc/crypttab
中定义)在 /etc/fstab
中创建一个条目
/etc/fstab
/dev/mapper/home-crypt /home ext4 defaults 0 2
由于 /dev/mapper/home-crypt
已经是唯一分区映射的结果,因此无需为其指定 UUID。 在任何情况下,带有文件系统的映射器都将具有与加密分区不同的 UUID。
挂载堆叠块设备
systemd 生成器还在启动时自动处理堆叠块设备。
例如,您可以创建一个 RAID 设置,在其上使用 cryptsetup,并在加密块设备内创建一个带有相应文件系统的 LVM 逻辑卷。 结果
$ lsblk -f
─sdXX linux_raid_member │ └─md0 crypto_LUKS │ └─cryptedbackup LVM2_member │ └─vgraid-lvraid ext4 /mnt/backup └─sdYY linux_raid_member └─md0 crypto_LUKS └─cryptedbackup LVM2_member └─vgraid-lvraid ext4 /mnt/backup
将要求输入密码短语并在启动时自动挂载。
如果您指定了正确的 crypttab (例如 crypto_LUKS
设备的 UUID) 和 fstab (/dev/vgraid/lvraid
) 条目,则无需添加额外的 mkinitcpio hooks/配置,因为 /etc/crypttab
处理仅适用于非 root 挂载。一个例外是当已经使用了 mdadm_udev
hook 时 (例如,对于 root 设备)。在这种情况下,需要更新 /etc/madadm.conf
和 initramfs 以实现首先选择正确的 root raid。
按需挂载
与其使用
# cryptsetup open UUID=... externaldrive
您可以 启动 systemd-cryptsetup@externaldrive.service
,当您的 /etc/crypttab
中有如下条目时
/etc/crypttab
externaldrive UUID=... none noauto
这样您就不需要记住确切的 crypttab 选项。如果需要,它会提示您输入密码。
相应的单元文件由 systemd-cryptsetup-generator(8) 自动生成。您可以使用以下命令列出所有生成的单元文件
$ systemctl list-unit-files | grep systemd-cryptsetup
故障排除
系统卡在启动/密码提示不显示
如果您正在使用 Plymouth,请确保使用正确的模块 (参见 Plymouth#mkinitcpio) 或禁用它。否则,Plymouth 将吞噬密码提示,导致系统无法启动。
如果您使用键盘或位于 initramfs 生成时不存在的文件系统上的密钥文件解锁 LUKS 设备,您可能需要将相应的模块添加到 mkinitcpio 的 MODULES
数组中。当键盘通过 USB 集线器连接时,也可能需要这样做。有关此问题的更多信息,请参见 mkinitcpio#MODULES,并参见 Minimal initramfs#Sorting out modules,作为要添加的潜在键盘和文件系统模块名称的起点。
一般来说,对于在 initramfs 生成时未连接到 PC 的键盘,您需要将 keyboard
hook 放在 autodetect
hook 之前,否则只保留当前连接硬件所需的部分,请参见 mkinitcpio#Common hooks。