使用 YubiKey 解密 LUKS 分区(续)
在上一篇文章 使用 YubiKey 解密 LUKS 分区 之后我发现了两个问题:
- 使用 Yubikey FIDO2 解密并不稳定,有时候还算 要使用密码解密
- 有时候强制使用 Yubikey 解密,不支持回退到密码解密
最近又查看了一下 ArchWiki1,最终解决了以上两个问题。写下这篇文章以作记录。
计划分盘
由于GRUB只识别基础的文件系统,解密根分区任务位于 initramfs 之中,因此内核镜像和 initramfs 不能被加密。具体步骤是:
- UEFI 识别到
/dev/sda1
下的/EFI/arch/grubx64.efi
,将控制权交给 grub - grub 根据
/dev/sda2
下的/grub.cfg
显示引导选项,选择 arch 后使用/dev/sda2
下的内核镜像和 initramfs 调用内核 - initramfs 下的内核使用 initramfs 中的
/etc/crypttab
提示用户解密分区 - initramfs 下的内核使用
/dev/mapper/system
中的/etc/fstab
挂载分区,引导结束
本次分区假设如下2:
/dev/sda1 1GB -> /boot/efi FAT32
/dev/sda2 500MB -> /boot FAT32
/dev/sda3 other -> /dev/mapper/system btrfs
|- /
|- /@ -> /
|- /@home -> /home
|- /.snapshots
进行之前先确保已经能使用密码解密系统,具体参考使用 YubiKey 解密 LUKS 分区。
配置 Yubikey
首先安装相关依赖3,然后将 Yubikey 插入电脑,检查是否出现 /dev/hidrawX
设备,完成后将 Yubikey FIDO2 插入密钥槽:
systemd-cryptenroll --fido2-device=auto /dev/sda3
可选参数:
参数 | 说明 |
---|---|
/dev/sda3 | 设备路径 |
--fido2-device | 设备,可用 auto,或前面的 /dev/hidrawX |
--fido2-with-client-pin | 默认是 yes ,若为 no ,从而开机时只需要触摸 YubiKey 而不需输入 PIN |
--fido2-credential-algorithm | 算法,此处选择 eddsa |
配置 crypttab
编辑 /etc/crypttab.initramfs
,systemd 会将这个文件打包到 initramfs 的 /etc/crypttab
# name device password options
system UUID=2f9a8428-ac69-478a-88a2-4aa458565431 none fido2-device=auto,token-timeout=30
意思是:使用 FIDO2 设备将 /dev/sda3
解密到 /dev/mapper/system
,如果超过 30 秒未使用 FIDO2 设备则回退到密码解密。
fido2-device=auto
指定使用 FIDO2 密钥解密token-timeout=30
超过 30 秒未使用 FIDO2 则回退到密码解密(token-timeout in systemd man page)
配置 initramfs
BusyBox 模式下并不支持这些功能4,我们需要改用 systemd 模式。幸好这个过程并不复杂。
编辑 /etc/mkinitramfs.conf
,修改其中的 HOOKS
(参考 dm-crypt/System configuration#mkinitramfs),要确保:
- 如果包含
keymap
或consolefont
,去掉,就地换成sd-vconsole
- 如果包含
udev
,就地换成systemd
- 如果包含
encrypt
,就地换成sd-encrypt
,否则在sd-vconsole
之后加上sd-encrypt
重新生成 initramfs
mkinitramfs -p linux
修改内核参数
如果你之前配置过 luks 相关的内核参数,需要修改一下。
编辑 /etc/default/grub
,修改其中的 GRUB_CMDLINE_LINUX
,与 luks 相关的 cryptdevice
等参数全部删掉,因为这是用于 encrypt
hook 的,而我们现在用的是 sd-encrypt
hook,这个 hook 会自动识别 /etc/crypttab
中的配置(由 systemd
自动从 /etc/crypttab.initramfs
复制到 initramfs 中的 /etc/crypttab
)。
只需要保留 root=/dev/mapper/system
即可。例如
GRUB_CMDLINE_LINUX="root=/dev/mapper/system rw loglevel=3 quiet"
这里的 /dev/mapper/system
不需要使用 UUID,因为这个是由我们 /etc/crypttab
中的 name
指定的,不会改变。
改完记得 grub-mkconfig -o /boot/grub/grub.cfg
。