dm-crypt/系统配置
- 如果您需要远程解锁根目录或其他早期启动文件系统(无头机器、远程服务器等),请遵循 dm-crypt/Specialties#远程解锁根目录(或其他)分区 中的具体说明。
- 为了方便在配置文件中输入 UUID、PARTUUID 等信息,您可以安装并使用一个支持插入命令输出的文本编辑器(例如,支持 `Ctrl+t` 的 nano、支持 `:read` 的 Vim 或 Neovim,或支持 `Alt+u` 的 mcedit),并传递适当的 lsblk 或 blkid 命令给它。或者,您可以安装一个终端多路复用器并使用其复制粘贴功能。
早期用户空间解锁
启动加密的根卷需要 initramfs 包含早期用户空间解锁卷所需的工具。解锁指令通常通过内核参数传递。
以下章节将描述如何配置 mkinitcpio 以及需要哪些内核参数。
mkinitcpio
根据具体情况,将需要启用以下mkinitcpio hooks的子集
| busybox | systemd | 用例 |
|---|---|---|
encrypt
|
sd-encrypt
|
当根分区被加密,或者需要在根分区之前挂载一个加密分区时需要。其他情况下则不需要,因为系统初始化脚本(如 `/etc/crypttab`)已负责解锁其他非根分区。此 hook 必须放在 `udev` 或 `systemd` hook 的之后。 |
keyboard (键盘)
|
需要使键盘在早期用户空间工作。 提示 对于使用不同硬件配置启动的系统(例如,带有外接键盘的笔记本电脑 vs. 内置键盘,或无头系统),将此 hook 放在 `autodetect` 之前会很有用,以便始终包含所有键盘驱动程序。否则,外接键盘仅在创建镜像时连接时才在早期用户空间工作。
| |
keymap
|
sd-vconsole
|
为非美式键盘布局提供支持,用于输入加密密码;它必须放在 `encrypt` hook 的之前,否则您需要使用默认的美式键盘布局输入加密密码。在 `/etc/vconsole.conf` 中设置您的键盘布局,请参阅 键盘控制台配置#持久化配置。 |
consolefont (控制台字体)
|
在早期用户空间加载备用控制台字体。在 `/etc/vconsole.conf` 中设置您的字体,请参阅 Linux 控制台#持久化配置。 | |
根据安装系统过程中遵循的其他手动步骤,应该清楚还需要哪些其他 hooks。
示例
使用 `encrypt` hook 的典型 `/etc/mkinitcpio.conf` 配置
/etc/mkinitcpio.conf
... HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt lvm2 filesystems fsck) ...
使用 `sd-encrypt` hook 的基于 systemd 的 initramfs 配置
/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
- 如果文件系统直接格式化在解密后的设备文件上,这将是 `/dev/mapper/dmname`。
- 如果首先激活 LVM 并且 LVM 包含一个加密的逻辑根卷,那么上述形式也适用。
- 如果根文件系统包含在一个完全加密的 LVM 的逻辑卷中,那么它的设备映射器将是 `root=/dev/volumegroup/logicalvolume` 的通用形式。
- 当使用 `sd-encrypt` hook 和GPT 分区自动挂载时,可以省略 `root=` 参数的指定。参阅 分区上的 LUKS。
- 使用GRUB并使用grub-mkconfig生成 `grub.cfg` 时,不需要手动指定 `root=` 参数。grub-mkconfig 将自动确定解密后的根文件系统的正确 UUID 并将其添加到 `grub.cfg`。
resume
resume=device
- `device` 是用于暂停到磁盘的解密后(交换)文件系统的设备文件。如果交换分区在单独的分区上,它将是 `/dev/mapper/swap` 的形式。另请参阅 dm-crypt/交换分区加密。
使用 encrypt hook
- 解锁多个加密磁盘(archlinux/mkinitcpio/mkinitcpio#231)。在 initramfs 中只能解锁一个设备。
- 使用分离的 LUKS 头(archlinux/mkinitcpio/mkinitcpio#234)。
- 设置 crypttab 支持的附加选项。
cryptdevice
这指定了冷启动时包含加密根目录的设备。它被 `encrypt` hook 解析,以识别哪个设备包含加密系统。
cryptdevice=device:dmname:options
- `device` 是加密设备后备设备的路径。强烈建议使用持久化块设备命名。
- `dmname` 是解密后设备被赋予的设备映射器名称,该名称将作为 `/dev/mapper/dmname` 提供。
- `options`(可选)是以逗号分隔的选项,例如,用于 TRIM 支持。如果不需要选项,则省略此参数(使用 `cryptdevice=device:dmname`)。
- 如果 LVM 包含加密的根目录,则首先激活 LVM,包含加密根目录逻辑卷的卷组作为设备。然后是映射到根目录的相应卷组。参数形式为 `cryptdevice=/dev/vgname/lvname:dmname`。
cryptkey
此参数指定密钥文件的位置,并且是 `encrypt` hook 读取该密钥文件以解锁 `cryptdevice` 所必需的(除非密钥位于默认位置,请参阅下文)。它可以有三个参数集,取决于密钥文件是存在于特定设备上的文件、存在于特定位置的比特流,还是存在于 initramfs 中的文件。
对于设备上的文件,格式为
cryptkey=device:fstype:path
- `device` 是密钥所在的原始块设备的路径。强烈建议使用持久化块设备命名。
- `fstype` 是 `device` 的文件系统类型(或 auto)。
- `path` 是设备内密钥文件的绝对路径。
示例: `cryptkey=LABEL=usbstick:vfat:/secretkey`
对于设备上的比特流,密钥位置的指定方式如下:
cryptkey=device:offset:size
其中偏移量和大小以字节为单位。例如,`cryptkey=UUID=ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ:0:512` 读取设备开头起的 512 字节密钥文件。
cryptkey=rootfs:path
示例: `cryptkey=rootfs:/secretkey`
另外请注意,如果未指定 `cryptkey`,则默认为 `/crypto_keyfile.bin`(在 initramfs 中)。[2]
另请参阅 dm-crypt/设备加密#密钥文件。
crypto
此参数用于将dm-crypt普通模式选项传递给encrypt hook。
其形式为
crypto=hash:cipher:keysize:offset:skip
参数直接对应于cryptsetup选项。请参阅 dm-crypt/设备加密#普通模式的加密选项。
对于仅使用普通默认选项加密的磁盘,必须指定 `crypto` 参数,但每个条目可以留空。
crypto=::::
参数的具体示例为
crypto=sha512:twofish-xts-plain64:512:0:
使用 systemd-cryptsetup-generator
systemd-cryptsetup-generator 是一个systemd单元生成器,它读取一部分内核参数和 `/etc/crypttab`,用于解锁加密设备。有关它和所有支持选项的更多详细信息,请参阅 systemd-cryptsetup-generator(8) man 页。
当使用 `sd-encrypt` mkinitcpio hook 或 `systemd` dracut module 时,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/disk/by-designator/`符号链接,避免在 `/etc/crypttab.initramfs` 中硬编码根块设备标识符(例如 UUID、PARTUUID 等)。参阅 #systemd-gpt-auto-generator。
- 在启动时输入的密码会被 systemd 缓存到内核密钥环中,由 systemd-cryptsetup(8) 处理,因此如果多个设备可以使用相同的密码解锁(这包括 crypttab 中在启动后解锁的设备),那么您只需要输入每个密码一次。
- 所有 `rd.luks` 参数都可以指定多次,以解锁多个 LUKS 加密卷。
- `rd.luks` 参数仅支持解锁 LUKS 设备。要解锁普通 dm-crypt 设备,您必须在 `/etc/crypttab.initramfs` 中指定。有关语法,请参阅 #crypttab。
- 更改 `/etc/crypttab.initramfs` 后,请记住重新生成 initramfs。
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.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
如果密钥文件在另一个设备上
rd.luks.key=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=/path/to/keyfile:UUID=ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ
将 `UUID=ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ` 替换为密钥文件所在设备的标识符。
- 如果文件系统类型与您的根文件系统不同,您必须在 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 指定的设备的选项,或者(如果未指定)为所有未在其他地方(例如 crypttab)指定的 UUID 设置选项。
此参数是 crypttab 的选项字段的类似物。格式相同——选项用逗号分隔,带值的选项使用 `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 在放弃之前等待根文件系统设备出现的时间(默认为 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 兼容的安全密钥,您可以使用它来自动解锁您的卷,而不是使用密码或密钥文件。
除了 `rd.luks.uuid` 或 `rd.luks.name` 之外,请设置
- 对于 TPM2 芯片: `rd.luks.options=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=tpm2-device=auto`
- 对于 FIDO2 密钥: `rd.luks.options=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX=fido2-device=auto`
或者,使用 `/etc/crypttab.initramfs`
/etc/crypttab.initramfs
root UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX none tpm2-device=auto
在此,加密卷以 `root` 的名称挂载(出现在 `/dev/mapper/root` 中),通过存储设备的 UUID 挂载,无需密码,并从 TPM2 设备检索密钥。
请注意,对于 TPM2 设备,必须在密码字段顺序中提供 `none` 或 `-`,否则将使用给定的值作为密码或密钥,如果不起作用,它将在启动时要求您输入密钥,而不会尝试从 TPM2 设备加载密钥。
如果像上面那样通过 UUID 指定设备,请确保它是底层(加密)存储设备的 UUID,而不是在其他地方指定为根文件系统的解密卷的 UUID。
rd.luks.data
使用分离的 LUKS 头时,请指定包含加密数据的块设备。必须与 `rd.luks.options` 一起使用以指定头文件位置。
有关详细信息和说明,请参阅 dm-crypt/Specialties#使用分离的 LUKS 头加密的系统。
systemd-gpt-auto-generator
如果满足systemd#GPT 分区自动挂载的所有先决条件,您可以避免指定任何 `rd.luks` 内核参数。 *systemd-cryptsetup-generator* 将自动尝试解锁 LUKS 加密的根分区。
要在配置文件中持久地引用发现的分区,请使用来自持久化块设备命名#by-designator 和 gpt-auto的标识符。如果您想为根分区指定 crypttab 选项,请在 `/etc/crypttab.initramfs` 中使用 `/dev/disk/by-designator/root-luks` 作为设备。例如,`/etc/crypttab.initramfs` 在没有内核选项且没有密码的情况下
/etc/crypttab.initramfs
root /dev/disk/by-designator/root-luks none tpm2-device=auto,fido2-device=auto
后期用户空间解锁
crypttab
`/etc/crypttab`(加密设备表)文件类似于 fstab 文件,其中包含在系统启动期间要解锁的加密设备列表。此文件可用于自动挂载加密的交换设备或辅助文件系统。
`crypttab` 的读取时间在 `fstab` *之前*,以便在文件系统挂载之前解锁 dm-crypt 容器。请注意,`crypttab` 是在系统启动*之后*读取的,因此它不能替代使用 mkinitcpio hooks 和通过内核参数配置它们来解锁加密分区,就像加密根分区那样。启动时的 `crypttab` 处理由 systemd-cryptsetup-generator(8) 自动完成。
有关详细信息,请参阅 crypttab(5);有关如何使用 UUID 挂载加密设备,请阅读下面的 #启动时挂载 部分。
- 如果指定了 `nofail` 选项,则输入密码屏幕可能会在输入密码时消失。因此 `nofail` 应该只与密钥文件一起使用。
- 对于dm-crypt普通模式设备,必须显式设置 `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/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx as /dev/mapper/backup using LUKS, with a passphrase stored in a file. backup UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /home/archie/backup.key # Unlock /dev/disk/by-partuuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx using the only available TPM, naming it myvolume myvolume PARTUUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 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
如果您的加密设备是 LUKS2 卷,您也可以通过其标签来引用它,前提是它有一个标签。
/etc/crypttab
externaldrive LABEL=encrypted-ext-drive-1 none timeout=180
您应该注意,LUKS2 头中设置的标签不应与其中包含的加密文件系统的标签相同。
第一个参数是您首选的加密驱动器的设备映射器名称。 `none` 选项会在启动时触发提示,要求输入密码来解锁分区。`timeout` 选项定义了启动时输入解密密码的超时时间(秒)。
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 选项的时间量。使用密钥文件解锁
如果辅助文件系统的密钥文件本身存储在加密的根目录下,那么在系统关闭时它是安全的,并且可以通过 crypttab 在启动时自动解锁挂载。例如,解锁一个由UUID指定的 crypt
/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 将与它所加密的分区的 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` 处理仅适用于非根挂载。一个例外是当*已经*使用了 `mdadm_udev` hook 时(例如,对于根设备)。在这种情况下,需要更新 `/etc/madadm.conf` 和 initramfs 以确保正确地先选择根 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
非阻塞挂载
当 secondary devices 在 crypttab 中定义但对引导过程不是必需的时,默认选项将使 cryptsetup 服务等待它们解锁后引导过程才能继续。nofail 选项将通过从指定设备的挂载服务中移除 Before=cryptsetup.target 来避免这种情况。当设备使用密钥文件解锁时,可以使用此选项,因为没有此选项,引导过程将延迟几秒钟,直到解锁过程完成。
/etc/crypttab
data UUID=d0d0d110-0a71-4ed6-936a-304969ea36af /etc/cryptsetup-keys.d/data.key nofail
故障排除
系统卡在引导/密码提示符未显示
如果您正在使用 Plymouth,请确保使用正确的模块(参见 Plymouth#mkinitcpio)或禁用它。否则,Plymouth 将吞噬密码提示符,导致系统无法引导。
键盘或文件系统上的密钥文件不可用于解锁
如果您使用键盘或文件系统上的密钥文件解锁 LUKS 设备,而该文件系统在生成 initramfs 时不存在,您可能需要将相应的模块添加到 mkinitcpio 的 MODULES 数组中。当键盘通过 USB 集线器连接时,也可能需要这样做。有关此问题的更多信息,请参见 mkinitcpio#MODULES,并将 Minimal initramfs#Sorting out modules 作为潜在的键盘和文件系统模块名称的起点。
一般来说,对于在 initramfs 生成时未连接到 PC 的键盘,您需要将 keyboard hook 放在 autodetect hook 之前,或者只保留当前连接的硬件所需的部分,请参见 mkinitcpio#Common hooks。