我为 genkernel 提供了一个补丁,允许使用单个密码解密多个卷(将文件另存为/tmp/genkernel_multicrypt.patch
):
diff --git a/defaults/initrd.d/00-crypt-multicrypt.sh b/defaults/initrd.d/00-crypt-multicrypt.sh
new file mode 100755
index 0000000..848f06a
--- /dev/null
+++ b/defaults/initrd.d/00-crypt-multicrypt.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+
+MULTICRYPT_MAX_TRIES=4
+
+multicrypt_all_volumes_mapped()
+{
+ local k=0
+
+ while true; do
+ eval local voltype='"${MULTICRYPT_type'${k}'}"'
+ k=$(( k+1 ))
+
+ [ -n "$voltype" ] || return 0
+
+ local m=0
+ while true; do
+ eval local vol='"${MULTICRYPT_'${voltype}${m}'}"'
+ [ -n "$vol" ] || break
+ [ -e "/dev/mapper/${voltype}${m}" ] || return 1
+ m=$(( m+1 ))
+ done
+ done
+
+ return 0
+}
+
+multicrypt_open_volumes()
+{
+ local pass="$1"; shift
+
+ local k=0
+
+ while true; do
+ eval local voltype='"${MULTICRYPT_type'${k}'}"'
+ k=$(( k+1 ))
+
+ [ -n "$voltype" ] || return 0
+
+ local m=0
+ while true; do
+ local volname="${voltype}${m}"
+
+ eval local vol='"${MULTICRYPT_'${volname}'}"'
+ [ -n "$vol" ] || break
+
+ echo Decrypting vol ${volname} ${vol} ...
+ echo -n "$pass" | ${CRYPTSETUP_BIN} luksOpen /dev/disk/by-uuid/${vol} "${volname}" -d - || return 1
+
+ m=$(( m+1 ))
+ done
+ done
+}
+
+multicrypt_execute() {
+
+ [ -z "${MULTICRYPT_type0}" ] && return 1 # multicrypt not requested
+
+ local root_or_swap=
+ if [ -n "${CRYPT_ROOTS}" ] || [ -n "${CRYPT_SWAPS}" ]; then
+ root_or_swap=1
+ fi
+
+ if ! multicrypt_all_volumes_mapped; then
+ echo "Opening multiple encrypted partitions..."
+ fi
+
+ local try=0
+ while ! multicrypt_all_volumes_mapped && [ "$try" -lt "$MULTICRYPT_MAX_TRIES" ]; do
+ try=$(( try+1 ))
+
+ echo -n "Password (try $try of $MULTICRYPT_MAX_TRIES): "
+ read -s pass
+ echo ""
+
+ multicrypt_open_volumes "$pass"
+
+ if [ $? -ne 0 ]; then
+ echo "ERROR: Decrypting one or more volumes failed."
+ fi
+ done
+
+ if [ -n "${root_or_swap}" ]; then
+ # We postponed the initialization of raid devices
+ # in order to avoid to assemble possibly degraded
+ # arrays.
+ start_volumes
+ fi
+}
diff --git a/defaults/initrd.d/00-crypt.sh b/defaults/initrd.d/00-crypt.sh
index 0e7c863..0515446 100755
--- a/defaults/initrd.d/00-crypt.sh
+++ b/defaults/initrd.d/00-crypt.sh
@@ -4,6 +4,7 @@
. /etc/initrd.d/00-devmgr.sh
. /etc/initrd.d/00-splash.sh
. /etc/initrd.d/00-fsdev.sh
+. /etc/initrd.d/00-crypt-multicrypt.sh
CRYPTSETUP_BIN="/sbin/cryptsetup"
KEY_MNT="/mnt/key"
@@ -285,6 +286,8 @@ _open_luks() {
start_luks() {
+ multicrypt_execute && return 0
+
local root_or_swap=
if [ -n "${CRYPT_ROOTS}" ] || [ -n "${CRYPT_SWAPS}" ]; then
root_or_swap=1
该补丁必须以 root 身份应用于 genkernel 目录/usr/share/genkernel
:
su
# Make a backup of genkernel if something goes wrong.
cp -r /usr/share/genkernel /root/genkernel-backup
cd /usr/share/genkernel
patch -p1 < /tmp/genkernel_multicrypt.patch
如果一切顺利,补丁将被应用,您将不会看到任何错误消息。
用法
首先确保您的磁盘可以使用相同的密码解密!!!
该补丁修改了 genkernel 的初始 ramdisk 以支持以下附加输入参数:
MULTICRYPT_type0=boot
MULTICRYPT_type1=root
MULTICRYPT_type2=tank
MULTICRYPT_boot0=aaaaaaaaa
MULTICRYPT_root0=bbbbbbbbb
MULTICRYPT_root1=ccccccccc
MULTICRYPT_tank0=ddddddddd
MULTICRYPT_tank1=eeeeeeeee
...
在上面的例子中你可以自由选择你想要的类型,我用了 3: boot
, root
, tank
. 对于每种类型,您可以拥有一个或多个卷 UUID,如上所示。
确保 UUID 存在于/dev/disk/by-uuid
.
确保 UUID 准确无误!错别字会导致系统无法启动!
设备将以 、 、 等形式添加到设备映射boot0
器root0
中root1
。
现在,内核行必须进行如下修改(只需将上面提到的所有参数与常规参数一起附加到内核行,例如dolvm
,dozfs
等)。
不要删除您原来的内核行,只需将其注释掉以防您想恢复。
GRUB_CMDLINE_LINUX="MULTICRYPT_type0=boot MULTICRYPT_type1=root MULTICRYPT_type2=tank MULTICRYPT_boot0=aaaaaaaaa MULTICRYPT_root0=bbbbbbbbb MULTICRYPT_root1=ccccccccc MULTICRYPT_tank0=ddddddddd MULTICRYPT_tank1=eeeeeeeee ..."
# As per standard grub configuration, we need to load the necessary modules and enable encryption:
GRUB_PRELOAD_MODULES="part_gpt search_fs_uuid cryptodisk luks linux" # zfs lvm etc. if necessary
GRUB_ENABLE_CRYPTODISK="y"
完成这项工作后,我们可以调用 genkernel 生成新的 initramfs。确保您制作了旧副本的备份副本,以便在出现问题时轻松恢复。不需要编译内核和模块。
另外,在一张纸上写下你原来的内核行,这样你就可以在 Grub 中输入它,以防系统无法正常启动。
su
cp /boot/<YOUR-INITRAMFS> /boot/<YOUR-INITRAMFS>--copy
# This uses 8 threads for compilation, adjust accordingly.
# Add "--zfs" if your root is on ZFS.
genkernel --makeopts=-j8 --udev --luks --busybox --bootloader=grub2 --menuconfig --oldconfig --install initramfs
您闪亮的新 initramfs 安装在/boot
. 现在进行最后一步 - 必须生成 GRUB 的配置文件以激活新参数:
grub-mkconfig -o /boot/grub/grub.cfg
在编写时 grub-mkconfig 会生成一个不正确的文件,如果您的根目录位于 ZFS 上,则需要手动修补该文件。在文件中,/boot/grub/grub.cfg
我的根数据集被错误地指定为/ROOT/gentoo
,zroot/ROOT/gentoo
所以我需要zroot
在多个位置插入。一旦修复了特定的错误,就不需要这样做了。
完毕!重启后会出现如下提示:
Opening multiple encrypted partitions...
Password (try 1 of 4):
输入您的密码,然后(手指交叉)所有卷都应该解密。
故障排除
如果您的系统无法启动,您可以使用我们保存的旧 initramfs。当显示 Grub 菜单时,点击E
并重新键入原始内核行,将“--saved”附加到您的 initramfs 文件名。这应该像以前一样引导您的系统。
如果您对补丁不满意,请将原始 genkernel 从/root/genkernel-backup
to/usr/share/genkernel
恢复,然后恢复原始内核行/etc/default/grub
并再次调用 genkernel 和 grub-mkconfig:
genkernel --makeopts=-j8 --udev --luks --busybox --bootloader=grub2 --menuconfig --oldconfig --install initramfs
grub-mkconfig -o /boot/grub/grub.cfg
警告
因为我使用全盘加密,我仍然需要在启动时输入两次密码。首先,解密/boot
并加载内核,然后第二次解密所有其他卷。我不知道有任何解决方案。
状态 17.02.2022