LUKS全盘加密实战

  • ~5.36K 字
  • ? 条评论
  1. 1. 准备工作
    1. 1.1. 评估加解密性能
    2. 1.2. 缩小文件系统,为加密预留空间
    3. 1.3. 分离/boot与根分区
    4. 1.4. 启动验证与文件系统检查
  2. 2. 开始加密
    1. 2.1. 执行原地加密
    2. 2.2. 打开加密分区并扩展文件系统
    3. 2.3. 挂载检查数据完整性
  3. 3. 配置系统
    1. 3.1. 挂载/boot并进入chroot环境
    2. 3.2. 更新mkinitcpio钩子
    3. 3.3. 重新生成initramfs
    4. 3.4. 配置GRUB内核参数
    5. 3.5. 更新fstab指向映射设备
    6. 3.6. 生成GRUB配置并重启
  4. 4. 进阶配置
    1. 4.1. 更新加密口令
    2. 4.2. 注册FIDO2安全密钥
    3. 4.3. 开启TRIM支持
    4. 4.4. 配置交换分区
      1. 4.4.1. 创建加密交换分区
      2. 4.4.2. 配置系统使用加密交换分区
  5. 5. 未雨绸缪
    1. 5.1. 创建恢复密钥
    2. 5.2. 备份加密头信息
  6. 6. 结语

在日常使用Linux系统时,大家总会遇到需要保护数据安全的场景。LUKS(Linux Unified Key Setup)作为Linux系统中常用的全盘加密解决方案,能够有效地保护磁盘上的数据。本文将详细介绍如何在Linux系统中使用LUKS进行全盘加密。

LUKS的配置非常灵活,能够进行对已有数据的加密。下面我将介绍如何在已经安装了Linux系统的机器中使用LUKS进行全盘加密。

笔者的系统环境配置
  • 发行版:Arch Linux
  • 使用systemd来管理系统服务
  • 硬盘:NVMe QLC SSD
  • 采用GRUB作为引导加载程序
  • 根分区/dev/nvme0n1p8使用ext4文件系统
  • ESP分区/dev/nvme0n1p6用于存放引导文件

准备工作

在开始之前,我们需要准备好cryptsetup工具。Arch Linux Live环境中已经预装了该工具。

评估加解密性能

首先,我们将测试系统的加解密性能。如果你的电脑的加解密速度还不如硬盘读写速度,应该考虑不要使用LUKS加密。

1
cryptsetup benchmark

确认要进行LUKS加密后,启动到Arch Linux Live环境。不要挂载分区,以便进行后续操作。

LUKS2加密推荐保留32 MB的未分配空间来存储加密头信息。准确地说,是LUKS2最小头信息大小的两倍。

在Linux中,分区与文件系统是不同的概念,我们将要缩小文件系统来为LUKS加密腾出空间。这一步可以先缩得小一些,后续可以再扩大。

缩小文件系统,为加密预留空间

例如,我们将ext4格式的根分区/dev/nvme0n1p8缩小99G,以腾出空间用于存储LUKS加密头信息。

1
2
e2fsck -f /dev/nvme0n1p8
resize2fs /dev/nvme0n1p8 99G

完成文件系统的缩小后,应尝试启动系统,确保一切正常。

分离/boot与根分区

让GRUB解密磁盘是一件很麻烦的事情。为了使GRUB能够正常启动Linux,我们需要让/boot/不在同一分区上。

笔者原先只是把ESP分区挂载在/efi,但ESP分区足够大,有1 GB。现在我们可以把/boot中的内容移动到ESP分区,再把/efi所在的分区挂载为/boot

1
2
3
4
5
6
7
8
9
10
11
12
13
mount /dev/nvme0n1p8 /mnt
mount /dev/nvme0n1p6 /mnt/efi
mv /mnt/boot/* /mnt/efi/
umount /mnt/efi
rm -r /mnt/boot
rm -r /mnt/efi
mkdir /mnt/boot
mount /dev/nvme0n1p6 /mnt/boot
arch-chroot /mnt
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfg
exit
umount -R /mnt

启动验证与文件系统检查

完成上述步骤后,应再次尝试启动系统,确保一切正常。为保险起见,应再次执行e2fsck检查文件系统。

开始加密

接下来,我们将开始对根分区进行LUKS加密。

务必确保电脑连接稳定的电源。在加密过程中断电可能会导致数据丢失!

执行原地加密

1
cryptsetup reencrypt --encrypt --reduce-device-size=32m /dev/nvme0n1p8

这意味着我们将在分区开头留出32 MB的空间用于存储LUKS加密头信息,加密后的数据将从偏移32 MB处开始存储,整个可用空间减少32 MB。因为我们已经预先缩小了文件系统,所以数据不会超出可用范围,不会丢失。

系统会询问你是否进行加密。因为我们完成了文件系统的缩小,所以不会有内容被抹去,可以输入YES继续。接下来请输入并确认加密密码。

接下来就是漫长的等待时间。笔者在一块使用QLC闪存的硬盘上加密了750 GB的数据,花费了大约3小时2分钟。

打开加密分区并扩展文件系统

完成加密后,应尝试解密分区。

1
cryptsetup open /dev/nvme0n1p8 crypt_data

输入密码后,分区将被解密并映射到/dev/mapper/crypt_data。若一切正常,我们可以扩大文件系统以恢复剩余的空间。

1
resize2fs /dev/mapper/crypt_data

挂载检查数据完整性

接下来,挂载分区并检查数据是否完好无损。

1
2
mount /dev/mapper/crypt_data /mnt
ls /mnt

完成检查后,先不要退出Live环境,接下来我们将进行必要的配置以确保系统能够正常启动。

配置系统

为了使系统能够在启动时解密LUKS分区,我们需要在初始化内存盘中包含系统解密的支持。首先挂载/boot分区,并切换到已安装的系统环境中。

挂载/boot并进入chroot环境

1
2
mount /dev/nvme0n1p6 /mnt/boot
arch-chroot /mnt

为了使用FIDO2安全密钥进行解密,我们需要使用sd-encrypt钩子,而不是传统的encrypt钩子,即添加sd-encrypt钩子到/etc/mkinitcpio.confHOOKS数组中。

更新mkinitcpio钩子

打开/etc/mkinitcpio.conf文件,找到HOOKS行,将原有的udev替换为systemd,再将sd-encrypt添加到filesystems之前的位置,类似下面:

/etc/mkinitcpio.conf
1
HOOKS=(base systemd autodetect microcode modconf kms keyboard keymap consolefont block sd-encrypt resume filesystems fsck)
提示

为了在输入口令时启动小键盘数字锁定,可以安装mkinitcpio-sd-numlockAUR包,并将sd-numlock钩子添加到sd-encrypt之前。

保存并退出后,重新生成初始化内存盘:

重新生成initramfs

1
mkinitcpio -P

接下来,我们要配置分区的自动挂载。请注意,因为我们加密的是根分区,所以不应/etc/crypttab中配置,而是要更新GRUB配置。编辑/etc/default/grub文件:

配置GRUB内核参数

编辑/etc/default/grub文件,找到GRUB_CMDLINE_LINUX行,添加rd.luks.name=参数,指定加密分区的UUID和映射名称。可以使用blkid命令获取分区的UUID。

为了方便起见,可以在vim中使用:r !blkid /dev/nvme0n1p8命令来把命令输出插入到文件中,再把光标移到合适的位置,用36xp命令剪切和粘贴UUID。完成后记得删除插入的行。

增加内核参数,将LUKS分区映射到/dev/mapper/root,并设为根分区。记得把UUID替换为实际的内容,如下所示:

/etc/default/grub
1
GRUB_CMDLINE_LINUX="... rd.luks.name=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx=root root=/dev/mapper/root ..."

保存并退出。

更新fstab指向映射设备

需要进一步更新/etc/fstab文件,确保根分区指向解密后的映射设备。应将原有的根分区行中的UUID替换为/dev/mapper/root,例如:

/etc/fstab
1
/dev/mapper/root        /               ext4            rw,relatime     0 1

生成GRUB配置并重启

重新生成GRUB配置:

1
grub-mkconfig -o /boot/grub/grub.cfg

完成后,退出chroot环境并重启系统:

1
2
3
exit
umount -R /mnt
reboot

在系统启动时,应该会提示输入LUKS加密的密码。输入正确的密码后,系统将继续启动并挂载根分区。

进阶配置

完成加密后,就可以在线使用LUKS分区并进行管理操作了。

更新加密口令

要更新LUKS分区的密码,我们应先添加新密码,再删除旧密码。可以使用以下命令:

1
2
3
4
sudo cryptsetup luksAddKey /dev/nvme0n1p8
# 输入新密码
sudo cryptsetup luksRemoveKey /dev/nvme0n1p8
# 输入旧密码

注册FIDO2安全密钥

要使用FIDO2安全密钥进行解密,可以使用以下命令将硬件密钥添加到LUKS分区:

1
sudo systemd-cryptenroll --fido2-device=auto /dev/nvme0n1p8

这样,我们就完成了LUKS全盘加密的配置。

至于TPM2.0自动解密,由于涉及到安全启动的配置,笔者因使用NVIDIA硬件难以配置安全启动,故无法测试该功能。

开启TRIM支持

默认情况下,LUKS会阻止TRIM命令传递到底层存储设备,这是为了安全考虑(dm-crypt/特殊应用 § 固态硬盘的Discard/TRIM支持 — Arch Linux 中文维基)。

如果使用的是SSD,开启TRIM支持可以提升性能和延长寿命,还有利于保护对LUKS头的修改。执行:

1
sudo cryptsetup --allow-discards --persistent refresh root

请记得启用fstrim.timer systemd服务,以在后台定期运行TRIM操作。

配置交换分区

在使用LUKS时,需要搭配加密交换分区以保护交换数据。此处演示如何将已有的交换分区加密。

创建加密交换分区

首先,卸载已有的交换分区:

1
sudo swapoff /dev/nvme0n1p7

然后,清空并使用LUKS加密交换分区:

1
sudo cryptsetup luksFormat --label=swap /dev/nvme0n1p7

打开该容器,并映射到/dev/mapper/swap:

1
sudo cryptsetup open /dev/disk/by-label/swap swap

在映射设备上创建swap文件系统:

1
sudo mkswap /dev/mapper/swap

这样我们就完成了加密交换分区的创建。

配置系统使用加密交换分区

编辑/etc/fstab文件,将映射设备添加为交换分区:

/etc/fstab
1
/dev/mapper/swap        none            swap            defaults        0 0

最后,编辑/etc/default/grub文件,增加一组rd.luks.name=参数,并更改交换分区的resume参数。加密分区的UUID可以通过blkid /dev/nvme0n1p7命令获取。

编辑后的参数类似:

/etc/default/grub
1
GRUB_CMDLINE_LINUX="... rd.luks.name=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx=swap resume=/dev/mapper/swap ..."

重新生成GRUB配置:

1
sudo grub-mkconfig -o /boot/grub/grub.cfg

这样就完成了加密交换分区的配置。

接下来可以为交换分区更改验证方式,例如添加TPM2.0自动解密,方法与根分区类似。

未雨绸缪

建议创建一个恢复密钥,以便在忘记密码时使用。此外,为了防止加密头信息损坏导致数据无法访问,建议备份LUKS加密头信息。

创建恢复密钥

1
sudo systemd-cryptenroll --recovery-key /dev/nvme0n1p8

请把恢复密钥妥善保管在安全的地方。

备份加密头信息

1
sudo cryptsetup luksHeaderBackup /dev/nvme0n1p8 --header-backup-file luks_header_backup.img

结语

数据无价,谨慎操作。

LUKS全盘加密为Linux用户提供了强大的数据保护手段,但在实施过程中务必小心谨慎,确保数据安全。

分享这一刻
让朋友们也来瞅瞅!