跳转到内容

dm-crypt/加密整个系统

来自 Arch Linux 中文维基

本文介绍了几种常见的使用“dm-crypt”加密整个系统的方式,以及相比正常安装过程所需的改动。官方安装镜像已经包含了加密所需的工具。

若要加密的是已有的未加密的文件系统,见 dm-crypt/设备加密#加密现有的未加密文件系统

概览

[编辑 | 编辑源代码]

“dm-crypt”能为为根文件系统提供安全保护,且相比其它方案具更优的性能。相比仅仅加密部分非根文件系统,加密根文件系统可以隐藏许多敏感信息(如已安装应用列表、用户名等),并能避免通过locate/var/log/等常见方式泄露数据。此外,由于除了引导加载程序和内核(通常情况下),所有数据都被加密,更难对系统进行未授权的改动。

除了上面提到的共同优点以外,各种加密方案还有如下特有的优缺点:

方案 优点 缺点
#在单一分区上配置LUKS 展示了使用LUKS完全加密的根文件系统的基本方式,最直接。
  • 不灵活;用于加密的整个磁盘空间需要预先分配。
#使用TPM2和安全启动在单一分区上配置

与上例相似,并通过使用安全启动、TPM2提高了安全性。

相比上例,本方法还有如下优点:

  • 安全启动可抵御邪恶女佣攻击
  • 在安全启动被关闭或配置被修改时,TPM2将阻止解密。
  • 与上例缺点相似。
#在LUKS上配置LVM

在LUKS加密的单一分区上配置LVM,实现了分区灵活性。

  • 通过LVM,可简单地在加密设备上配置多个分区。
  • 只需单一密码即可解密所有分区。
  • 在未解密时系统的分区结构不可见。
  • 若要使用休眠功能,这是最简单的方式。
  • LVM增加了系统设备映射结构的复杂性,且需要单独添加钩子。
  • 难以对某个分区单独指定密码。
  • 若需要配置的LVM卷组包含多个物理卷,则所有物理卷必须分别进行LUKS加密。在系统启动时,必须分别解锁所有物理卷后,才能激活并使用卷组。
#在LVM上配置LUKS

在LVM上层使用LUKS。

  • 可通过LVM将(单个)加密分区拓展到多个磁盘上。
  • 可方便地同时配置加密与未加密分区。
  • 若更改了LVM逻辑卷的结构,需要同时更改加密设备与逻辑卷的对应关系,配置复杂。
  • 每个逻辑卷需要单独设置密码。
  • LVM中逻辑卷的结构在未解密时也是可见的。
  • 由于每个加密的逻辑卷都需要单独解密,系统启动较慢。
#在软RAID上配置LUKS

在软RAID上层使用LUKS。

  • 与在LVM上配置LUKS相似。
  • 与在LVM上配置LUKS,并使用加密引导分区类似。
#Plain dm-crypt

使用dm-crypt的plain模式(不使用LUKS头及LUKS的多密钥选项)。
此方案还将/boot配置到USB设备上,并通过USB设备储存密钥。该思路也适用于其它方案。

  • 在面临可能损坏LUKS头的意外情况时,仍能保证数据完整性。
  • 能够实现可抵赖加密
  • 有助于解决在SSD上应用加密的一些问题
  • 需要尤其关注所有使用的加密参数。
  • 只能使用单个密码且不能更换密码。
  • 即使对于常规系统,配置也非常复杂。
#加密boot分区(GRUB)

展示了如何在使用GRUB时加密boot分区。
该方案还使用了EFI系统分区,这也适用于其它方案。

  • 与选择的加密配置方式相同的优点。(在本例中采用在LUKS上配置LVM)
  • 未加密的数据更少,只有引导加载程序和EFI系统分区(若有)未加密。
  • 与选择的加密配置方式相同的缺点。(在本例中采用在LUKS上配置LVM)
  • 配置更复杂。
  • 其它引导加载程序不支持此方案。
  • GRUB解密LUKS卷所需的时间较长,将减慢启动速度。
#Root on ZFS
  • 若将zpool加密,则其中的所有数据集(dataset)都将使用相同的ZFS加密设置加密。同时,由于加密在ZFS层面进行,支持ZFS的系统都可解密,便于配置双系统或在不同系统间共享数据。
  • 可将加密的文件系统安全地备份到未加密的ZFS中。产生的文件系统快照将保持原生加密状态
  • ZFS 不会加密有关存储池结构的文件系统元数据(例如,数据集/快照名称,数据集结构/属性/文件大小/文件空洞,deduplication tables(though the deduplicated data itself is encrypted))。
  • 若要追求最佳性能,需要根据磁盘物理属性创建存储池时(甚至需要考虑物理块大小ashift)。
  • ZFS的aes实现存在一些问题;此外,某些加密算法的实现可能存在性能问题
  • 使用zvol作为交换分区或者使用数据集中的文件作为交换文件存在问题。只能通过关闭休眠并设置交换分区到其它分区(详见下)解决。

虽然对于外界威胁,相比文件系统层面的加密,上述方案提供了好得多的保护。但也有一个共同的缺点:任何拥有密码的用户都能解密整个设备,进而访问其它用户的数据。若要防范上述风险,可以结合使用块设备加密和文件系统加密。可参见静态数据加密进行提前规划。

对于本文中所有方案的分区策略的概述,参见dm-crypt/准备磁盘#分区

此外,还需考虑是否设置加密的swap分区及设置方式。详见Dm-crypt/交换分区加密

加密整个系统可在设备失窃时保护数据,但不能抵御逻辑层面的非法修改(例如,系统上运行的恶意软件修改未加密的boot分区)。若有相关需求,还应参见dm-crypt/特殊应用#保护未加密的boot分区

在使用固态硬盘时,可能需要启用TRIM支持。但这可能影响安全性,详见dm-crypt/特殊应用#固态硬盘的Discard/TRIM支持

警告:
  • 在任何情况下都不要直接在加密卷上运行文件系统修复工具(例如,fsck),否则,加密密钥将永久丢失,使得所有加密内容无法被解密。只应当在解密后的设备上运行文件系统修复工具。
  • Argon2 密钥派生函数的设计方式使得其在运行时将占用大量内存(在默认设置下,每个加密卷将占用1GiB内存)。在设备内存较少或启动时并行解密多个LUKS2分区的情况下,可能导致错误。可使用--pbkdf-memory选项控制内存使用。[1]
  • GRUB对LUKS2的支持并不完善,详见GRUB#加密的/boot。对于需要由GRUB解密的分区,建议使用PBKDF2密钥派生函数(cryptsetup luksFormat --pbkdf pbkdf2)。
  • 对于ZFS,即使交换分区并没有放置在zvol上,从休眠中唤醒时也有可能损坏存储池。因此在配置休眠时需要额外注意。参考

在单一分区上配置LUKS

[编辑 | 编辑源代码]

本例说明了如何通过“dm-crypt”与LUKS,将安装在单一分区上的系统进行加密。

+-----------------------+------------------------+-----------------------+
| boot分区              | LUKS加密的根分区      | 可选的用于其它分区的  |
|                       | partition              | 空闲空间              |
|                       |                        |                       | 
| /boot                 | /                      |                       |
|                       |                        |                       |
|                       | /dev/mapper/root       |                       |
|                       |------------------------|                       |
| /dev/sda1             | /dev/sda2              |                       |
+-----------------------+------------------------+-----------------------+

本例的前几步可在启动到Arch Linux安装镜像后直接进行。

准备磁盘

[编辑 | 编辑源代码]

在创建分区前,应先查看dm-crypt/准备磁盘,了解安全地擦除整个磁盘的重要性,并掌握相关方法。

接下来,创建本例中的分区(至少需要//dev/sda2)和/boot/dev/sda1),详见分区

准备非boot分区

[编辑 | 编辑源代码]

在格式化分区时,不要使用安装指南中的步骤,而是使用本节及下一节的步骤。

使用如下命令创建并挂载加密的根分区,dm-crypt/设备加密#使用 LUKS 模式加密设备中详细介绍了进行的操作。若要使用非默认的加密选项(例如,修改加密算法,密钥长度,扇区大小),在执行如下第一条指令前参见相关加密选项

# cryptsetup -v luksFormat /dev/sda2
# cryptsetup open /dev/sda2 root

在解密的LUKS设备上创建文件系统。例如,要创建Ext4文件系统,执行:

# mkfs.ext4 /dev/mapper/root

将根分区挂载到/mnt

# mount /dev/mapper/root /mnt

确保设备映射正常:

# umount /mnt
# cryptsetup close root
# cryptsetup open /dev/sda2 root
# mount /dev/mapper/root /mnt

若还创建了其它分区(例如,/home),则对于除了/boot的其它分区,执行类似操作。在启动时解密其它分区的方法可参见dm-crypt/加密非root文件系统#自动解锁并挂载

注意,对于每个要加密并挂载的块设备,都需要单独设置密钥,这将导致在启动时需要多次输入密钥,造成不便。可通过在根分区中存储密钥文件,并通过修改crypttab设置,自动使用密钥文件解锁其它设备。详见dm-crypt/设备加密#使用LUKS来格式化带有密钥文件的分区

准备boot分区

[编辑 | 编辑源代码]

对于加密根分区的配置,需要设置非加密的/boot分区。

对于UEFI启动的系统,使用如下命令格式化新创建的EFI 系统分区

警告:只有在EFI系统分区是在安装Arch Linux的分区步骤中创建的情况下,才应当格式化该分区。否则,若EFI系统分区是由其它系统创建的,则重新格式化将导致其它系统的引导程序丢失。
# mkfs.fat -F32 /dev/sda1

对于传统BIOS启动的系统:

# mkfs.ext4 /dev/sda1

之后,创建boot分区的挂载点并挂载分区:

# mount --mkdir /dev/sda1 /mnt/boot

挂载分区

[编辑 | 编辑源代码]

安装指南#挂载分区步骤时,应当挂载/dev/mapper/*中的相应设备(包含LUKS加密的设备的解密后的版本),而不是LUKS加密的设备自身对应的分区。不过,对于未加密的/boot分区,仍应当直接挂载到/mnt/boot(假设在安装过程中,根分区被挂载到/mnt)。

配置mkinitcpio

[编辑 | 编辑源代码]

安装指南#关于_initramfs步骤前,需要在新安装的系统中完成如下操作:

若使用基于busybox的initramfs,在mkinitcpio.conf中添加keyboardencrypt钩子。此外,若要使用非标准键盘布局,添加keymap钩子;若要自定义控制台字体,添加consolefont钩子。

HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)

若使用基于systemd的initramfs,在mkinitcpio.conf中添加keyboardsd-encrypt钩子。此外,若要使用非标准键盘布局,或要自定义控制台字体,添加sd-vconsole钩子。

HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)

保存上述修改后,重新生成initramfs。其它可能需要用到的钩子以及配置细节参见Dm-crypt/系统配置#mkinitcpio

配置引导加载程序

[编辑 | 编辑源代码]

要在启动时解密已加密的根分区,需配置引导加载程序,设置如下内核参数

cryptdevice=UUID=device-UUID:root root=/dev/mapper/root

若使用的是sd-encrypt,则应该添加如下内核参数:

rd.luks.name=device-UUID=root root=/dev/mapper/root

device-UUID指的是LUKS超级块的UUID,在本例中为/dev/sda2对应的UUID。详见块设备持久化命名

另见Dm-crypt/系统配置#内核参数

提示:若根分区与boot分区在同一硬盘上,并且使用的引导加载程序支持GPT分区自动挂载,则可以修改根分区的分区类型GUID为“Root partition”并通过systemd-gpt-auto-generator(8)自动挂载,而不必设置上述内核参数。

使用TPM2和安全启动在单一分区上配置

[编辑 | 编辑源代码]

本例与#在单一分区上配置LUKS相似,但通过使用安全启动可信平台模块,使启动过程更安全。

在本配置方案中,只有EFI 系统分区是未加密的,存储经过签名以用于安全启动的统一内核映像systemd-boot。在本配置中,若安全启动功能被关闭,或者安全启动的密钥数据库被修改,则TPM将不会释放用于解密分区的密钥。此时,仍可以使用配置过程中创建的恢复密钥解密数据。此外,还可要求在解密数据前必须输入设置的TPM PIN码。本配置方案类似Windows中的BitLocker和macOS中的FileVault。

在继续之前,确保已经详细阅读了可信平台模块#LUKS_数据加密,并着重留意其中的警告。

本例中的分区按照符合Systemd#GPT分区自动挂载的方式创建,因此无需fstab、crypttab文件。

+-----------------------+---------------------------------+
| EFI系统分区             | LUKS加密的根分区                  |
|                       |                                 |
|                       |                                 |
| /boot                 | /                               |
|                       |                                 |
|                       | /dev/mapper/root                |
|                       |---------------------------------|
| /dev/sda1             | /dev/sda2                       |
+-----------------------+---------------------------------+

按照安装指南#创建硬盘分区前的步骤进行基本配置。之后,按本文下一节的内容进行磁盘分区。

准备磁盘

[编辑 | 编辑源代码]

在创建分区前,应先查看dm-crypt/准备磁盘,了解安全地擦除整个磁盘的重要性,并掌握相关方法。

使用GUID分区表 (GPT),并创建需要的分区。

创建大小合适的EFI 系统分区(在本例中,使用/dev/sda1)。该分区将被挂载到/boot

在磁盘的剩余空间上创建根分区(在本例中,使用/dev/sda2)。根分区将被加密,并挂载到/。将根分区的分区类型GUID设置为4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709(在fdisk中,设置为"Linux root (x86-64)"类型;在gdisk中,设置为8304类型)。

准备根分区

[编辑 | 编辑源代码]

使用如下命令创建并挂载加密的根分区,dm-crypt/设备加密#使用 LUKS 模式加密设备中详细介绍了进行的操作。

若要使用非默认的加密选项(例如,修改加密算法,密钥长度,扇区大小),或者不想使用TPM解密,在执行如下第一条指令前参见相关加密选项

创建并挂载LUKS卷(由于在配置完成后将擦除密码槽位,可以直接使用空密码):

# cryptsetup luksFormat /dev/sda2
# cryptsetup open /dev/sda2 root

在解密的LUKS设备上创建文件系统。例如,要创建Ext4文件系统,执行:

# mkfs.ext4 /dev/mapper/root

将根分区挂载到 /mnt:

# mount /dev/mapper/root /mnt

准备EFI系统分区

[编辑 | 编辑源代码]

格式化新创建的EFI系统分区,并挂载:

# mount --mkdir /dev/sda1 /mnt/boot

继续执行安装指南#关于_initramfs前的步骤。注意无需执行安装指南#生成_fstab_文件步骤。

配置mkinitcpio

[编辑 | 编辑源代码]

修改mkinitcpio.conf中的HOOKS=为如下内容,以构建可用的基于systemd的initramfs:

HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)

按照统一内核映像#mkinitcpio中的步骤配置统一内核映像

由于/boot/EFI/Linux目录暂未由启动加载程序创建,暂时不要重新生成initramfs。

配置引导加载程序

[编辑 | 编辑源代码]

可以直接通过UEFI启动内核,而无需引导加载程序。

若仍需使用引导加载程序,可以安装systemd-boot

# bootctl install

systemd-boot可自动识别mkinitcpio生成的统一内核映像,无需在/boot/loader/entries/手动添加条目。

其它配置参见systemd-boot#更新 EFI 启动管理器Systemd-boot#配置

完成安装

[编辑 | 编辑源代码]

重新生成initramfs,并确保相关镜像成功生成。

不要忘记设置 root 密码重启以完成安装。

安全启动

[编辑 | 编辑源代码]

为了启用安全启动,需要为引导加载程序、EFI镜像签名。可使用sbctl简单、快速地实现。

注册TPM

[编辑 | 编辑源代码]

在签名引导加载程序并启用安全启动后,可以向TPM注册密钥用以解锁LUKS卷。如下命令将移创建LUKS卷时设置的空密码,创建绑定到TPM PCR 7安全启动状态和已注册证书)寄存器的密钥,并创建恢复密钥,用于在TPM出现问题时解密卷。若安全启动链完好,TPM将自动释放密钥。详见systemd-cryptenroll#Trusted Platform Modulesystemd-cryptenroll(1)

# systemd-cryptenroll /dev/sda2 --recovery-key
# systemd-cryptenroll /dev/sda2 --wipe-slot=empty --tpm2-device=auto --tpm2-pcrs=7
提示:若要求在启动时需要输入PIN码解密卷,可添加--tpm2-with-pin=yes参数。
警告:
  • 在绑定密钥到PCR7寄存器时,需要确保安全启动已启用且处于用户模式。否则,未授权的启动设备也可能解锁加密卷。
  • 若固件证书状态改变,则PCR7寄存器状态也可能改变,导致解锁失败。例如,使用fwupd[2]可能在不经意间改变固件证书状态;此外,轮转安全启动密钥也将改变固件证书状态。


在LUKS上配置LVM

[编辑 | 编辑源代码]

在加密的单个分区上配置LVM是一种较为直接的方案。该方案将LVM设置在一个大的加密块设备中,LVM结构只在块设备解密,扫描并挂载LVM物理卷后才可见。

示例磁盘结构如下:

+-----------------------------------------------------------------------+ +----------------+
| 逻辑卷 1              | 逻辑卷 2              | 逻辑卷 3              | | boot分区       |
|                       |                       |                       | |                |
| [SWAP]                | /                     | /home                 | | /boot          |
|                       |                       |                       | |                |
| /dev/MyVolGroup/swap  | /dev/MyVolGroup/root  | /dev/MyVolGroup/home  | |                |
|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _| | (可能在其他    |
|                                                                       | | 设备上)        |
|                         使用LUKS加密的分区                           | |                |
|                           /dev/sda1                                   | | /dev/sdb1      |
+-----------------------------------------------------------------------+ +----------------+
注意:使用默认的encrypt钩子时,不能将逻辑卷分配到多个磁盘上。可使用sd-encrypt钩子或参见dm-crypt/特殊应用#修改encrypt钩子以用于多个分区
提示:该配置方案有两种变形:

准备磁盘

[编辑 | 编辑源代码]

在创建分区前,应先查看dm-crypt/准备磁盘,了解安全地擦除整个磁盘的重要性,并掌握相关方法。

提示:若要在BIOS启动的设备上使用GPT磁盘,且使用GRUB引导加载程序,需创建BIOS boot partition

创建一个大于1GiB的分区用于/boot

提示:对于UEFI启动的设备,可将EFI 系统分区用于/boot

创建一个分区,用于存储整个加密的LVM。

在上述创建的分区上配置LUKS作为LVM的容器(若要修改加密选项,参见dm-crypt/设备加密#LUKS 模式的加密选项):

# cryptsetup luksFormat /dev/sda1

打开创建的容器:

# cryptsetup open /dev/sda1 cryptlvm

现在可通过/dev/mapper/cryptlvm访问解密的容器。

准备逻辑卷

[编辑 | 编辑源代码]

在解密的LUKS容器上创建物理卷:

# pvcreate /dev/mapper/cryptlvm

创建卷组(本例中使用MyVolGroup,也可使用其它名称),并加入先前创建的物理卷:

# vgcreate MyVolGroup /dev/mapper/cryptlvm

在卷组中创建逻辑卷:

提示:若需要使用ext4格式的逻辑卷,应在卷组中预留至少256MiB的空闲空间,以便能正常使用e2scrub(8)。可以在使用-l 100%FREE创建占满所有剩余空间的最后一个逻辑卷后,使用类似lvreduce -L -256M MyVolGroup/home的命令减少该逻辑卷的大小。
# lvcreate -L 4G -n swap MyVolGroup
# lvcreate -L 32G -n root MyVolGroup
# lvcreate -l 100%FREE -n home MyVolGroup

在每个逻辑卷上创建文件系统。例如,若根分区和home分区使用Ext4文件系统:

# mkfs.ext4 /dev/MyVolGroup/root
# mkfs.ext4 /dev/MyVolGroup/home
# mkswap /dev/MyVolGroup/swap

挂载文件系统:

# mount /dev/MyVolGroup/root /mnt
# mount --mkdir /dev/MyVolGroup/home /mnt/home
# swapon /dev/MyVolGroup/swap

准备boot分区

[编辑 | 编辑源代码]

引导加载程序从/boot目录加载内核、initramfs和自身的配置文件。可使用任何引导加载程序支持的文件系统。

/boot分区创建文件系统。对于UEFI启动的系统,使用如下命令格式化新创建的EFI 系统分区

警告:只有在EFI系统分区是在安装Arch Linux的分区步骤中创建的情况下,才应当格式化该分区。否则,若EFI系统分区是由其它系统创建的,则重新格式化将导致其它系统的引导程序丢失。
# mkfs.fat -F32 /dev/sdb1

对于传统BIOS启动的系统:

# mkfs.ext4 /dev/sdb1

将上述分区挂载到/mnt/boot

# mount --mkdir /dev/sdb1 /mnt/boot

继续执行安装指南#开始安装系统中的步骤。之后回到本页,执行修改后的关于 initramfs安装引导程序步骤。

配置mkinitcpio

[编辑 | 编辑源代码]

确保已安装lvm2

若使用基于busybox的initramfs,在mkinitcpio.conf中添加keyboardencryptlvm2钩子。此外,若要使用非标准键盘布局,添加keymap钩子;若要自定义控制台字体,添加consolefont钩子。

HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt lvm2 filesystems fsck)

若使用基于systemd的initramfs,在mkinitcpio.conf中添加keyboardsd-encryptlvm2钩子。此外,若要使用非标准键盘布局,或要自定义控制台字体,添加sd-vconsole钩子。

HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck)

保存上述修改后,重新生成initramfs。其它可能需要用到的钩子以及配置细节参见Dm-crypt/系统配置#mkinitcpio

注意:若使用dracut生成mkinitcpio,则其已经包含必要的模块,无需额外配置。

配置引导加载程序

[编辑 | 编辑源代码]

要在启动时解密已加密的根分区,需配置引导加载程序设置如下内核参数

cryptdevice=UUID=device-UUID:cryptlvm root=/dev/MyVolGroup/root

若使用的是sd-encrypt,则应该添加如下内核参数:

rd.luks.name=device-UUID=cryptlvm root=/dev/MyVolGroup/root

device-UUID指的是LUKS超级块的UUID,在本例中为/dev/sda1对应的UUID。详见块设备持久化命名

若使用dracut,一般可使用如下参数:

rd.luks.uuid=device-UUID root=/dev/MyVolGroup/root

有时,需要设置更多参数:

rd.luks.uuid=luks-deviceUUID rd.lvm.lv=MyVolGroup/root  rd.lvm.lv=MyVolGroup/swap  root=/dev/mapper/MyVolGroup-root rootfstype=ext4 rootflags=rw,relatime

详见Dm-crypt/系统配置#内核参数

在LVM上配置LUKS

[编辑 | 编辑源代码]

为了在LVM上层设置加密,首先要设置LVM卷,用作加密分区的基础。在本方案中,可同时创建加密及未加密的分区。

提示:#在LUKS上配置LVM不同,可以使用常规方式将逻辑卷分配到多个磁盘上。

下例展示了在LVM上配置LUKS加密卷,并使用密钥文件解锁home分区。对于swap分区,使用临时加密卷,以确保在每次重启后,都重新配置swap分区的加密,防止敏感信息泄露,提升安全性。若熟悉LVM配置,可自行修改LVM分区方案。

若要创建横跨多个磁盘的逻辑卷,或要将已有逻辑卷扩展到其它已配置好的磁盘上,详见dm-crypt/特殊应用#将LVM拓展到多个磁盘上。注意调整逻辑卷的大小后,LUKS加密容器的大小也需要调整。

准备磁盘

[编辑 | 编辑源代码]

分区方案如下:

+----------------+-------------------------------------------------------------------------------------------------+
| boot分区       | dm-crypt plain加密的分区        | LUKS加密的分区               | LUKS加密的分区               |
|                |                                 |                               |                               |
| /boot          | [SWAP]                          | /                             | /home                         |
|                |                                 |                               |                               |
|                | /dev/mapper/swap                | /dev/mapper/root              | /dev/mapper/home              |
|                |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
|                | 逻辑卷 1                        | 逻辑卷 2                      | 逻辑卷 3                      |
|                | /dev/MyVolGroup/cryptswap       | /dev/MyVolGroup/cryptroot     | /dev/MyVolGroup/crypthome     |
|                |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
|                |                                                                                                 |
|   /dev/sda1    |                                   /dev/sda2                                                     |
+----------------+-------------------------------------------------------------------------------------------------+

按照dm-crypt/准备磁盘#dm-crypt 擦除空设备或分区随机擦除/dev/sda2

准备逻辑卷

[编辑 | 编辑源代码]
# pvcreate /dev/sda2
# vgcreate MyVolGroup /dev/sda2
# lvcreate -L 4G -n cryptswap MyVolGroup
# lvcreate -L 32G -n cryptroot MyVolGroup
# lvcreate -l 100%FREE -n crypthome MyVolGroup
# cryptsetup luksFormat /dev/MyVolGroup/cryptroot
# cryptsetup open /dev/MyVolGroup/cryptroot root

在解密后的设备上创建文件系统,并挂载到对应挂载点。例如,要创建Ext4文件系统:

# mkfs.ext4 /dev/mapper/root
# mount /dev/mapper/root /mnt

关于加密选项的更多信息,详见dm-crypt/设备加密#LUKS 模式的加密选项

注意/home的加密会在#加密/home逻辑卷步骤中进行。

提示:若要在Arch ISO中访问加密的根文件系统,可在LVM逻辑卷出现后执行上述open操作。

准备boot分区

[编辑 | 编辑源代码]

/boot分区创建文件系统。对于UEFI启动的系统,使用如下命令格式化新创建的EFI 系统分区

警告:只有在EFI系统分区是在安装Arch Linux的分区步骤中创建的情况下,才应当格式化该分区。否则,若EFI系统分区是由其它系统创建的,则重新格式化将导致其它系统的引导程序丢失。
# mkfs.fat -F32 /dev/sda1

对于传统BIOS启动的系统:

# mkfs.ext4 /dev/sda1

之后,创建boot分区的挂载点并挂在分区:

# mount --mkdir /dev/sda1 /mnt/boot

配置mkinitcpio

[编辑 | 编辑源代码]

确保已安装lvm2

若使用基于busybox的initramfs,在mkinitcpio.conf中添加keyboardencryptlvm2钩子。此外,若要使用非标准键盘布局,添加keymap钩子;若要自定义控制台字体,添加consolefont钩子。

HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block lvm2 encrypt filesystems fsck)

若使用基于systemd的initramfs,在mkinitcpio.conf中添加keyboardsd-encryptlvm2钩子。此外,若要使用非标准键盘布局,或要自定义控制台字体,添加sd-vconsole钩子。

HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck)

保存上述修改后,重新生成initramfs。其它可能需要用到的钩子以及配置细节参见Dm-crypt/系统配置#mkinitcpio

配置引导加载程序

[编辑 | 编辑源代码]

要在启动时解密已加密的根分区,需配置引导加载程序设置如下内核参数

cryptdevice=UUID=device-UUID:root root=/dev/mapper/root

若使用的是sd-encrypt,则应该添加如下内核参数:

rd.luks.name=device-UUID=root root=/dev/mapper/root

device-UUID指的是LUKS超级块的UUID,在本例中为/dev/MyVolGroup/cryptroot对应的UUID。详见块设备持久化命名

若使用的是dracut,需要一系列更复杂的参数:

kernel_cmdline="rd.luks.uuid=luks-deviceUUID rd.lvm.lv=MyVolGroup/root  rd.lvm.lv=MyVolGroup/swap  root=/dev/mapper/MyVolGroup-root rootfstype=ext4 rootflags=rw,relatime"

详见Dm-crypt/系统配置#内核参数

配置fstab和crypttab

[编辑 | 编辑源代码]

crypttab用于解密设备,fstab用于挂载文件系统。如下配置将在每次重启时用不同的密钥重新加密swap分区:

/etc/crypttab
swap	/dev/MyVolGroup/cryptswap	/dev/urandom	swap,cipher=aes-xts-plain64,size=256,sector-size=4096
/etc/fstab
/dev/mapper/root                          /     ext4   defaults  0 1
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /boot ext4   defaults  0 2
/dev/mapper/swap                          none  swap   defaults  0 0

加密/home逻辑卷

[编辑 | 编辑源代码]

由于本方案使用LVM作为第一层,dm-crypt作为第二层,每个加密逻辑卷都需要单独进行加密解密配置。此外,显然,和临时文件系统可采用临时随机密钥加密不同,/home对应的逻辑卷应该采用持久不变的密钥。下列命令假定你已经重启进入了安装好的系统。否则,需要调整相应路径。

为了避免在系统启动时输入两次密码,创建密钥文件

# dd bs=512 count=4 if=/dev/random iflag=fullblock | install -m 0600 /dev/stdin /etc/cryptsetup-keys.d/home.key

/home逻辑卷将采用上述密钥文件加密:

# cryptsetup luksFormat -v /dev/MyVolGroup/crypthome /etc/cryptsetup-keys.d/home.key
# cryptsetup -d /etc/cryptsetup-keys.d/home.key open /dev/MyVolGroup/crypthome home

在解密后的设备上创建文件系统,并挂载到对应挂载点。例如,要创建Ext4文件系统:

# mkfs.ext4 /dev/mapper/home
# mount /dev/mapper/home /home

解密并挂载该文件系统需要配置crypttabfstab

/etc/crypttab
home	/dev/MyVolGroup/crypthome   none
/etc/fstab
/dev/mapper/home        /home   ext4        defaults        0       2

在软RAID上配置LUKS

[编辑 | 编辑源代码]

下例基于真实的工作站笔记本设置,该工作站有两块大小相同的SSD及一块大容量机械硬盘。在本配置中,对所有磁盘采用LUKS加密(包括/boot),并将两块SSD组成了RAID0阵列。系统启动时,在GRUB中输入正确的密码后,将用解密出的密钥文件解密所有分区。

本方案采用的分区配置非常简单,组成的RAID阵列挂载在/(没有单独的/boot 分区),解密后的机械硬盘挂载在/data

注意对于本方案,定期的备份非常重要。若两块SSD中的任何一块损坏,整个RAID阵列中的数据都将丢失。若要求较高的容错能力,应选择其它RAID级别

本配置中的加密方式不是可抵赖加密。

在之后的命令中,假定采用如下块设备设置:

/dev/sda = 第一块SSD
/dev/sdb = 第二块SSD
/dev/sdc = 机械硬盘
+---------------------+---------------------------+---------------------------+ +---------------------+---------------------------+---------------------------+ +---------------------------+
| BIOS boot分区       | EFI系统分区               | LUKS加密的分区           | | BIOS 启动分区       | EFI系统分区               | LUKS加密的分区           | | LUKS加密的分区           |
|                     |                           |                           | |                     |                           |                           | |                           |
|                     | /efi                      | /                         | |                     | /efi                      | /                         | | /data                     |
|                     |                           |                           | |                     |                           |                           | |                           |
|                     |                           | /dev/mapper/root          | |                     |                           | /dev/mapper/root          | |                           |
|                     +---------------------------+---------------------------+ |                     +---------------------------+---------------------------+ |                           |
|                     | RAID1 array (part 1 of 2) | RAID0 array (part 1 of 2) | |                     | RAID1 array (part 2 of 2) | RAID0 array (part 2 of 2) | |                           |
|                     |                           |                           | |                     |                           |                           | |                           |
|                     | /dev/md/ESP               | /dev/md/root              | |                     | /dev/md/ESP               | /dev/md/root              | | /dev/mapper/data          |
|                     +---------------------------+---------------------------+ |                     +---------------------------+---------------------------+ +---------------------------+
| /dev/sda1           | /dev/sda2                 | /dev/sda3                 | | /dev/sdb1           | /dev/sdb2                 | /dev/sdb3                 | | /dev/sdc1                 |
+---------------------+---------------------------+---------------------------+ +---------------------+---------------------------+---------------------------+ +---------------------------+

在之后的操作中,需要根据实际情况替换上述配置。

准备磁盘

[编辑 | 编辑源代码]

在创建分区前,应先查看dm-crypt/准备磁盘,了解安全地擦除整个磁盘的重要性,并掌握相关方法。

对于使用GPT分区表的BIOS启动的系统,需创建一个大小为1MiB的BIOS启动分区,GRUB将在此存储第二阶段的BIOS引导加载程序。不要挂载该分区。

对于UEFI启动的系统,需创建大小适当的EFI 系统分区,并挂载到/efi

对于设备上的剩余空间,创建一个用于"Linux RAID"的分区(本例中为/dev/sda3)。对于MBR分区表,选择fd分区类型ID;对于GPT分区表,选择A19D880F-05FC-4D3B-A006-743F0F84911E分区类型GUID。

一旦在/dev/sda上创建好了分区,可使用下列命令将它们的配置克隆到/dev/sdb上:

# sfdisk -d /dev/sda > sda.dump
# sfdisk /dev/sdb < sda.dump

对于机械硬盘,创建单个占据整个磁盘的Linux分区(/dev/sdc1)。

构建RAID阵列

[编辑 | 编辑源代码]

创建用于两块SSD的RAID阵列:

注意:
  • 对于两块SSD,EFI系统分区必须能在每块SSD上单独访问,因此只能存放在RAID1上。
  • 必须通过--metadata=1.0选项将RAID superblock放置在EFI系统分区的后部,否则固件将不能访问EFI系统分区。
# mdadm --create --verbose --level=1 --metadata=1.0 --raid-devices=2 /dev/md/ESP /dev/sda2 /dev/sdb2

对于根分区,本例采用了RAID0。可根据实际偏好与需要选择其它RAID级别。

# mdadm --create --verbose --level=0 --metadata=1.2 --raid-devices=2 /dev/md/root /dev/sda3 /dev/sdb3

准备块设备

[编辑 | 编辑源代码]

dm-crypt/准备磁盘中介绍了通过使用随机密钥创建加密卷,并向加密卷中写入/dev/zero产生的全零数据来随机擦除设备的方法。此外,也可使用dd/dev/random/dev/urandom来擦除,不过速度较慢。

# cryptsetup open --type plain --sector-size 4096 --key-file /dev/urandom /dev/md/root to_be_wiped
# dd if=/dev/zero of=/dev/mapper/to_be_wiped bs=1M status=progress
# cryptsetup close to_be_wiped

对本例中的机械硬盘(/dev/sdc1)也需重复上述操作。

/dev/md/root设置加密:

警告:GRUB对LUKS2的支持并不完善,详见GRUB#加密的/boot。对于需要由GRUB解密的分区,建议使用PBKDF2密钥派生函数(cryptsetup luksFormat --pbkdf pbkdf2)。
# cryptsetup -v luksFormat --pbkdf pbkdf2 /dev/md/root
# cryptsetup open /dev/md/root root

在解密后的设备上创建文件系统。例如,要创建Ext4文件系统:

# mkfs.ext4 /dev/mapper/root

将根分区挂载到/mnt

# mount /dev/mapper/root /mnt

对机械硬盘,类似的:

# cryptsetup -v luksFormat /dev/sdc1
# cryptsetup open /dev/sdc1 data
# mkfs.ext4 /dev/mapper/data
# mount --mkdir /dev/mapper/data /mnt/data

对于UEFI启动的系统,还需设置EFI系统分区:

警告:只有在EFI系统分区是在安装Arch Linux的分区步骤中创建的情况下,才应当格式化该分区。否则,若EFI系统分区是由其它系统创建的,则重新格式化将导致其它系统的引导程序丢失。
# mkfs.fat -F32 /dev/md/ESP
# mount --mkdir /dev/md/ESP /mnt/efi

配置GRUB

[编辑 | 编辑源代码]

对于本例中通过LUKS加密的系统,编辑/etc/default/grub以配置GRUB

GRUB_CMDLINE_LINUX="cryptdevice=/dev/md/root:root"
GRUB_ENABLE_CRYPTODISK=y

对于较新的设备,可能需要使用USB键盘在GRUB中输入密码。这需要启用固件中的”legacy USB support“,或在/etc/default/grub中添加:

GRUB_TERMINAL_INPUT="usb_keyboard"
GRUB_PRELOAD_MODULES="usb usb_keyboard ohci uhci ehci"

否则在提示输入LUKS密码时可能无法使用键盘。详见Dm-crypt/系统配置#内核参数GRUB#加密的/boot

将GRUB安装到两块SSD上(事实上,仅安装到/dev/sda也是可行的):

# grub-install --target=i386-pc /dev/sda
# grub-install --target=i386-pc /dev/sdb
# grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB
# grub-mkconfig -o /boot/grub/grub.cfg

配置密钥文件

[编辑 | 编辑源代码]

进行如下步骤可避免在启动时需输入两次密码(第一次发生在GRUB解密LUKS设备,第二次发生在initramfs接管系统时)。首先要创建密钥文件,然后将该密钥文件加入到initramfs镜像中以便encrypt钩子解密根分区。详见dm-crypt/设备加密#在_initramfs_中嵌入密钥文件

  • 创建密钥文件并向其中添加/dev/md/root的密码。
  • 创建另一个密钥文件以便于在启动时解密机械硬盘(/dev/sdc1)。为了便于以后可能的需要恢复的情况,不要移动/删除上述密钥文件。接下来编辑/etc/crypttab以在启动时解密机械硬盘。详见Dm-crypt/系统配置#使用密钥文件解密

配置系统

[编辑 | 编辑源代码]

配置fstab以挂载根分区、data分区、EFI系统分区:

/dev/mapper/root  /	  ext4	rw,noatime 	   0 1
/dev/mapper/data  /data   ext4	defaults           0 2
/dev/md/ESP       /efi     vfat	rw,relatime,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,tz=UTC,errors=remount-ro  	0 2

保存RAID配置:

# mdadm --detail --scan >> /etc/mdadm.conf

编辑mkinitcpio.conf,包含密钥文件,并添加所需的钩子:

FILES=(/crypto_keyfile.bin)
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block mdadm_udev encrypt filesystems fsck)

详见Dm-crypt/系统配置#mkinitcpio

Plain dm-crypt

[编辑 | 编辑源代码]

与LUKS不同,dm-crypt的plain模式无需在加密设备前附加LUKS头,本方案利用该特点在未分区的硬盘上设置加密的系统。对于他人,将无法区分用该方式加密的硬盘与与用随机数据填充的硬盘,即所谓可抵赖加密。详见wikipedia:Disk encryption#Full disk encryption

注意,除非需要将整个硬盘全部加密,否则,无论是加密整个系统还是部分分区,使用之前小节中介绍的基于LUKS的方法都是更好的选择。因为在plain模式中,无法使用LUKS特有的功能,例如支持多个密码、密钥文件的密钥管理,主密钥备份,原位重新加密。

由于不依赖主密钥,可避免主密钥损坏或被销毁导致的单点故障,plain模式对数据损坏的承受能力更强。此外,若尤为在意对SSD的TRIM支持,也可以使用plain模式。然而,在plain模式下,要到达与LUKS模式相同的加密强度,需要手动配置加密选项。详见静态数据加密#加密的元数据

提示:若需要使用无LUKS头的加密但仍想使用KDF的相关功能,可尝试如下两种替代方案:
  • 通过cryptsetup--header选项使用分离的LUKS头。注意若使用该方案则不能使用标准的"encrypt"钩子,不过可对该钩子进行修改。
  • tcplay 在无LUKS头加密模式下提供了PBKDF2函数。

本方案使用了两个U盘:

  • 一个用于引导设备,同时存储用于解密plain加密设备的配置选项;
  • 一个用于密钥文件,将按原始比特位存储,故不了解加密方案的攻击者只能看到一串仿佛随机的数据,而非可见的普通文件。详见Wikipedia:Security through obscurity。要准备密钥文件,参见dm-crypt/Device encryption#Keyfiles

磁盘布局如下:

+----------------------+----------------------+----------------------+ +----------------+ +----------------+
| 逻辑卷 1     | 逻辑卷 2     | 逻辑卷 3     | | 启动设备    | | 密钥 |
|                      |                      |                      | |                | | 存储设备   |
| /                    | [SWAP]               | /home                | | /boot          | | (在本例中 |
|                      |                      |                      | |                | | 未分区)    |
| /dev/MyVolGroup/root | /dev/MyVolGroup/swap | /dev/MyVolGroup/home | | /dev/sdb1      | | /dev/sdc       |
|----------------------+----------------------+----------------------| |----------------| |----------------|
| /dev/sda 使用plain模式加密并配置LVM             | | U盘 1    | | U盘 2    |
+--------------------------------------------------------------------+ +----------------+ +----------------+
提示:
  • 也可以只使用一个U盘,如下为两种方式:
    • 在U盘(/dev/sdb)的另一个分区(/dev/sdb2)上存储密钥。
    • 直接复制密钥文件到initramfs中。例如,在/etc/mkinitcpio.conf中设置FILES=(/etc/cryptsetup-keys.d/root.key)将复制/etc/cryptsetup-keys.d/root.key密钥文件到initramfs镜像中。要使得encrypt钩子从initramfs镜像中读取密钥文件,在文件名前添加rootfs:前缀,例如,cryptkey=rootfs:/etc/cryptsetup-keys.d/root.key
  • 此外,也可使用足够安全的密码解密。

准备磁盘

[编辑 | 编辑源代码]

向解密后的映射设备中填充随机数据是非常重要的。尤其是在本例中。

详见dm-crypt/准备磁盘dm-crypt/准备磁盘#dm-crypt_专用方案

准备分区(除boot)

[编辑 | 编辑源代码]

详见dm-crypt/设备加密#plain模式的加密选项

在本例中,使用/dev/sda,并使用aes-xts加密算法,密钥长度为512位,并使用密钥文件加密:

 # cryptsetup open --type plain --cipher=aes-xts-plain64 --offset=0 --key-file=/dev/sdc --key-size=512 --sector-size 4096 /dev/sda cryptlvm

与使用LUKS不同,每次要解密设备时必须使用上述“完整”的命令,故一定要牢记加密算法、密钥文件相关信息。

检查有关/dev/mapper/cryptlvm的映射条目已建立:

# fdisk -l
提示:
  • 若无需使用LVM提供的功能,cryptsetup FAQ提倡直接在解密后的设备上创建文件系统,而不创建LVM。
  • 若LVM卷组中包含ext4文件系统的逻辑卷,为了便于使用e2scrub(8)工具,至少在卷组中保留256MiB的空闲空间。若使用-l 100%FREE参数创建了最后一个逻辑卷,可以使用lvreduce -L -256M MyVolGroup/home留出256MiB的空闲空间。

接下来,在解密后产生的映射设备上设置LVM逻辑卷,详见Install Arch Linux on LVM

# pvcreate /dev/mapper/cryptlvm
# vgcreate MyVolGroup /dev/mapper/cryptlvm
# lvcreate -L 32G MyVolGroup -n root
# lvcreate -L 4G MyVolGroup -n swap
# lvcreate -l 100%FREE MyVolGroup -n home

格式化并挂载上述分区并激活swap,详见文件系统#创建文件系统

# mkfs.ext4 /dev/MyVolGroup/root
# mkfs.ext4 /dev/MyVolGroup/home
# mount /dev/MyVolGroup/root /mnt
# mount --mkdir /dev/MyVolGroup/home /mnt/home
# mkswap /dev/MyVolGroup/swap
# swapon /dev/MyVolGroup/swap

准备boot分区

[编辑 | 编辑源代码]

可直接将单独的U盘(通常使用FAT32文件系统)作为/boot分区。或者,若要手动分区,使用分区工具创建大小为1GiB的小分区,并建立文件系统

警告:只有在EFI系统分区是在安装Arch Linux的分区步骤中创建的情况下,才应当格式化该分区。否则,若EFI系统分区是由其它系统创建的,则重新格式化将导致其它系统的引导程序丢失。
# mkfs.fat -F32 /dev/sdb1
# mount --mkdir /dev/sdb1 /mnt/boot

配置mkinitcpio

[编辑 | 编辑源代码]

确保已安装lvm2

若使用基于busybox的initramfs,在mkinitcpio.conf中添加keyboardencryptlvm2钩子。此外,若要使用非标准键盘布局,添加keymap钩子;若要自定义控制台字体,添加consolefont钩子。

HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt lvm2 filesystems fsck)

保存上述修改后,重新生成initramfs。其它可能需要用到的钩子以及配置细节参见Dm-crypt/系统配置#mkinitcpio

配置引导加载程序

[编辑 | 编辑源代码]

要从加密的根分区启动,需通过引导加载程序设置如下内核参数(注意512位对应64字节):

cryptdevice=/dev/disk/by-id/disk-ID-of-sda:cryptlvm:sector-size=4096 cryptkey=/dev/disk/by-id/disk-ID-of-sdc:0:64 crypto=:aes-xts-plain64:512:0:

disk-ID-of-disk表示相应磁盘的id,详见块设备持久化命名

对于其它可能需要的内核参数,详见Dm-crypt/系统配置#内核参数

提示:若使用GRUB,可将其安装到/boot分区所在的U盘上。

对于BIOS启动的系统:

# grub-install --target=i386-pc --recheck /dev/sdb

对于UEFI启动的系统:

# grub-install --target=x86_64-efi --efi-directory=/boot --removable

安装完成后的操作

[编辑 | 编辑源代码]

或许希望在系统启动后移除启动用的U盘。由于/boot分区并不常用,可在/etc/fstab的相应行中添加noauto选项:

/etc/fstab
# /dev/sdb1
UUID=XXXX-XXXX /boot vfat noauto,rw,noatime 0 2

然而,若需要更新initramfs、内核、引导加载程序使用的相关文件时,则必须挂载/boot分区。由于fstab中存在相关条目,只需执行如下命令即可挂载:

# mount /boot

加密的boot分区(GRUB)

[编辑 | 编辑源代码]

本配置使用与#在LUKS上配置LVM相同的分区结构和配置。但使用了GRUB引导加载程序,其能从LVM逻辑卷和LUKS加密的/boot上启动系统。详见GRUB#加密的/boot

本例中的磁盘结构如下:

+---------------------+----------------------+----------------------+----------------------+----------------------+
| BIOS boot分区       | EFI系统分区          | 逻辑卷 1             | 逻辑卷 2             | 逻辑卷 3             |
|                     |                      |                      |                      |                      |
|                     | /efi                 | /                    | [SWAP]               | /home                |
|                     |                      |                      |                      |                      |
|                     |                      | /dev/MyVolGroup/root | /dev/MyVolGroup/swap | /dev/MyVolGroup/home |
| /dev/sda1           | /dev/sda2            |----------------------+----------------------+----------------------+
| 未加密              | 未加密               | /dev/sda3 使用LUKS加密并配置LVM                                   |
+---------------------+----------------------+--------------------------------------------------------------------+
提示:
  • 所有提供的案例仅用作示例。可按需与其它方案结合使用。此外,可参见#在LUKS上配置LVM中介绍的两种变形。
  • 可以使用cryptbootAUR中的cryptboot脚本简化加密boot分区的管理(包括挂载、卸载、软件包更新)。此外,该脚本与UEFI安全启动配合还可抵御邪恶女佣攻击。更多信息及存在的问题见cryptboot project

准备磁盘

[编辑 | 编辑源代码]

在创建分区前,应先查看dm-crypt/准备磁盘,了解安全地擦除整个磁盘的重要性,并掌握相关方法。

对于UEFI启动的系统,创建大小合适的EFI 系统分区,将挂载该分区到/efi

对于BIOS + GPT启动的系统,创建大小为1MiB的BIOS启动分区,GRUB将在该分区中存储第二阶段引导加载程序,不要手动挂载该分区。

对于BIOS + MBR启动的系统,无需创建BIOS启动分区。

创建一个类型为8309的分区用于加密的LVM。

创建LUKS加密容器:

警告:GRUB对LUKS2的支持并不完善,详见GRUB#加密的/boot。对于需要由GRUB解密的分区,建议使用PBKDF2密钥派生函数(cryptsetup luksFormat --pbkdf pbkdf2)。
 # cryptsetup luksFormat --pbkdf pbkdf2 /dev/sda3

关于加密选项的更多信息,在执行上述命令前参见dm-crypt/设备加密#LUKS 模式的加密选项

分区结构应与下述相似:

# gdisk -l /dev/sda
...
Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048            4095   1024.0 KiB  EF02  BIOS boot partition
   2            4096         2101247   1024.0 MiB  EF00  EFI system partition
   3         2101248        69210111   32.0 GiB    8309  Linux LUKS

打开LUKS加密容器:

# cryptsetup open /dev/sda3 cryptlvm

解密后的容器将在/dev/mapper/cryptlvm

准备逻辑卷

[编辑 | 编辑源代码]

本例中逻辑卷的结构与#在LUKS上配置LVM中的相同。因此,只需遵循#准备逻辑卷中的步骤并按需调整。

对于UEFI启动的系统,将EFI 系统分区挂载到/efi,以与接下来的grub-install指令相匹配。

# mount --mkdir /dev/sda2 /mnt/efi

现在,在/mnt下应挂载有如下分区与逻辑卷:

$ lsblk
NAME                  MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda                   8:0      0   200G  0 disk
├─sda1                8:1      0     1M  0 part
├─sda2                8:2      0   550M  0 part  /mnt/efi
└─sda3                8:3      0   100G  0 part
  └─cryptlvm          254:0    0   100G  0 crypt
    ├─MyVolGroup-swap 254:1    0     4G  0 lvm   [SWAP]
    ├─MyVolGroup-root 254:2    0    32G  0 lvm   /mnt
    └─MyVolGroup-home 254:3    0    60G  0 lvm   /mnt/home

继续执行安装指南#开始安装系统及之后的步骤。请使用本文中的对应内容替换安装指南的Initramfs安装引导加载程序步骤。

配置mkinitcpio

[编辑 | 编辑源代码]

确保已安装lvm2

若使用基于busybox的initramfs,在mkinitcpio.conf中添加keyboardencryptlvm2钩子。此外,若要使用非标准键盘布局,添加keymap钩子;若要自定义控制台字体,添加consolefont钩子。

HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt lvm2 filesystems fsck)

若使用基于systemd的initramfs,在mkinitcpio.conf中添加keyboardsd-encryptlvm2钩子。此外,若要使用非标准键盘布局,或要自定义控制台字体,添加sd-vconsole钩子。

HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck)

保存上述修改后,重新生成initramfs。其它可能需要用到的钩子以及配置细节参见Dm-crypt/系统配置#mkinitcpio

配置GRUB

[编辑 | 编辑源代码]

配置GRUB以从LUKS加密的/boot启动:

/etc/default/grub
GRUB_ENABLE_CRYPTODISK=y

设置内核参数以便initramfs解密加密的根分区。 若使用encrypt钩子:

/etc/default/grub
GRUB_CMDLINE_LINUX="... cryptdevice=UUID=device-UUID:cryptlvm ..."

若使用sd-encrypt钩子:

/etc/default/grub
GRUB_CMDLINE_LINUX="... rd.luks.name=device-UUID=cryptlvm ..."

详见Dm-crypt/系统配置#内核参数GRUB#加密的/bootdevice-UUID应为LUKS superblock的UUID(在本例中为/dev/sda3,该分区包含了含有根分区的LVM)。详见块设备持久化命名

对于UEFI启动的系统,安装GRUB到挂载的EFI系统分区:

# grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB --recheck

对于BIOS启动的系统,安装GRUB

# grub-install --target=i386-pc --recheck /dev/sda

生成GRUB配置文件

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

若上述所有命令都成功执行,在下次重启后GRUB应提示输入密码解锁/dev/sda3

避免需输入两次密码

[编辑 | 编辑源代码]

尽管在上述操作后,GRUB会要求输入密码解密LUKS加密的分区,但密码并不会传递到initramfs中。因此,需要在启动时输入两次密码:一次用于GRUB,一次用于initramfs。

可通过在initramfs中嵌入密钥文件避免输入两次密码。

首先,创建一个密钥文件,将其添加到LUKS key中:

# dd bs=512 count=4 if=/dev/random iflag=fullblock | install -m 0600 /dev/stdin /etc/cryptsetup-keys.d/cryptlvm.key
# cryptsetup -v luksAddKey /dev/sda3 /etc/cryptsetup-keys.d/cryptlvm.key

将密钥文件添加到initramfs镜像:

/etc/mkinitcpio.conf
FILES=(/etc/cryptsetup-keys.d/cryptlvm.key)

重新生成initramfs镜像。

设置如下内核参数以通过密钥文件解密LUKS分区。 若使用encrypt钩子:

GRUB_CMDLINE_LINUX="... cryptkey=rootfs:/etc/cryptsetup-keys.d/cryptlvm.key"

若使用sd-encrypt钩子,将默认使用/etc/cryptsetup-keys.d/name.key密钥文件,因此无需手动设置内核参数。

若由于某些原因密钥文件解密boot分区失败,systemd会要求手动输入密码。输入正确的密码后,系统启动将正常进行。

提示:若想加密/boot分区以抵御离线攻击/boot分区的威胁,可使用dm-crypt/特殊应用#mkinitcpio-chkcryptoboot钩子。

使用USB设备解锁 /boot

[编辑 | 编辑源代码]

使用存储在单独USB设备上的密钥文件可避免使用密码(若密码太复杂,则难以记忆;若太简单,则容易被猜中)。从安全性角度考虑,在未使用时,存储有密钥文件的USB设备必须与需解密的设备分开保存。

首先,按照#避免需输入两次密码中的步骤创建新的密钥文件。不要复用initramfs中使用的密钥文件,否则,若USB设备丢失或密钥泄露,需要修改嵌入到initramfs中的密钥文件。

将创建的密钥文件复制到USB设备,并创建GRUB配置文件:

/boot/grub/grub-pre.cfg
set crypto_uuid=UUID-of-the-luks-volume
set key_disk=UUID-of-the-volume-with-the-key
cryptomount -u $crypto_uuid -k ($key_disk)/the-location-of-the-key-on-your-usb
set root=UUID-of-the-unlocked-volume-as-in-grub.cfg
set prefix=($root)/boot/grub
insmod normal
normal

创建并安装GRUB镜像(依文件系统设置而定,可能不需要在镜像中包含某些模块):

# grub-mkimage -p /boot/grub -O x86_64-efi -c /boot/grub/grub-pre.cfg -o /tmp/grubx64.efi  part_gpt  part_msdos cryptodisk  luks  gcry_rijndael gcry_sha512 lvm ext2 ntfs fat exfat
# install -v /tmp/grubx64.efi /efi/EFI/GRUB/grubx64.efi

Root on ZFS

[编辑 | 编辑源代码]

要将dm-crypt与ZFS一同使用,参见ZFS#Encryption in ZFS using dm-crypt

此外,ZFS具有原生加密支持,可用于加密根分区(不包含引导加载程序和文件系统元数据)。详见:

对于UEFI启动的系统,在安装后可通过安全启动验证引导加载程序。