dm-crypt/准备磁盘
在加密一个驱动器前,建议先用随机的数据将设备内容覆写来安全地擦除磁盘内容。要想避免加密攻击或不必要的文件恢复,写入的数据最好与之后 dm-crypt 写入的数据难以区分。关于更深入的讨论,请见静态数据加密#准备磁盘。
安全擦除驱动器数据
在决定使用何种方式安全擦除驱动器数据时,记住:如果驱动器要持续地作为加密设备使用,这只需要执行一次。
- 继续操作前,请检查您的先进格式化设备是否采用最佳逻辑扇区大小。出于加密性能的考虑,cryptsetup 强烈推荐将磁盘的逻辑扇区大小改为 4096 字节。
- 在数 TB 的设备上,填充加密驱动器的过程可能需要耗费一整天。为了不让机器在操作过程中无法使用,从已经安装在另一个驱动器上的系统中执行此操作,比在 Arch 安装用的 live 系统中执行此操作要好。
- 对于固态硬盘,要想尽量减少闪存的缓存,可以考虑按 固态硬盘记忆单元清理 中的 优先 节执行。
通用方案
关于如何擦除并准备好驱动器的详细指导,参考安全地擦除磁盘#闪存。
dm-crypt 专用方案
下面两个方案专门用于 dm-crypt ,之所以提到它们是因为它们很快而且可以在分区设置后执行。
cryptsetup 常见疑问(item 2.19 "How can I wipe a device with crypto-grade randomness?")提到了一个非常简单的操作可以使用一个已存在的 dm-crypt 卷,像一个简单的伪随机数生成器生成随机数据来擦除一个底层块设备上所有可访问的空闲空间。而且据说这可以避免使用方式的暴露。这是因为加密数据实际上与随机数据难以区分。
dm-crypt 擦除空设备或分区
首先,在待加密的单个分区(格式为 sdXY)或整个设备(格式为 sdX)上创建临时加密容器:
# cryptsetup open --type plain --key-file /dev/urandom --sector-size 4096 /dev/block-device to_be_wiped
可以这样验证它是否存在:
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 1.8T 0 disk └─to_be_wiped 252:0 0 1.8T 0 crypt
用0擦除容器。不需要使用 if=/dev/urandom 因为加密密钥已经将数据变成随机的了。
# dd if=/dev/zero of=/dev/mapper/to_be_wiped status=progress bs=1M
dd: writing to ‘/dev/mapper/to_be_wiped’: No space left on device
blockdev --getsize64 /dev/mapper/container 可以作为 root 获取准确的容器大小。在容器被关闭后 od 可以用于检查擦除操作是否覆盖了被清零的分区。举个例子,执行命令 # od -j $((containersize - blocksize)) /dev/nvme0n1 来从头至尾检查擦除是否执行。最后,关闭临时的容器:
# cryptsetup close to_be_wiped
在加密整个系统时,下一步是#分区。如果只是加密一个分区,继续按照加密非 root 文件系统#分区执行。
dm-crypt 在安装后擦除可用空间
在安装前没时间执行擦除步骤的用户,即使在加密系统已启动,文件系统已挂载的情况下也可以做到类似的效果。但请注意相关文件系统是否有保留空间,例如,对于 root 用户,或即使是 root 用户执行的擦除操作也会被限制的其他磁盘配额机制:底层块设备的一些部分可能完全不会写入。
要想执行擦除操作,通过在加密容器写入一个文件来临时填充分区的剩余可用空间:
# dd if=/dev/zero of=/file/in/container status=progress
dd: writing to ‘/file/in/container’: No space left on device
缓存同步到磁盘,然后删除文件来回收可用空间。
# sync # rm /file/in/container
对每个块设备的分区和其中的文件系统都要重复一次以上操作。举个例子,设置 LUKS 上的 LVM 时,对每个逻辑卷都要执行这个操作。
dm-crypt 在安装后擦除可用空间(通过重新加密)
作为替代,对于想要在不重新安装的情况下完全擦除可用空间的用户,可以通过重新加密 LUKS 设备来达成。需要在每个 LUKS 设备上执行一次。但是请注意这个过程可能很慢(在桌面 HDD 上大约 50MB/s)。
擦除 LUKS header
使用 LUKS 的分区由两部分组成:标头和加密数据。标头包含密钥和加密参数,如果没有这些密钥和参数,几乎不可能恢复数据。如果创建新分区或停用硬盘,只需删除该部分而无需擦除整个设备。注意事项参见本小节末。
要想擦除所有密钥,使用下列命令:
# cryptsetup erase device
通过以下命令确保没有激活的密钥槽:
# cryptsetup luksDump device
此外,通过在密钥被擦除后调用 arch:wipefs 可以移除 LUKS header 本身以避免 cryptsetup 之后检测到它:
# wipefs -a device
加密数据保留在原位。截至2020年,没有已知的实用方法解密这些数据,但是在未来可能会有所不同。由用户来衡量安全,隐私与正确擦除整个设备的时间。
在某些存储介质(尤其是闪存介质)上,可能无法可靠地覆盖数据。带有密钥的 LUKS 标头可能会保存在操作系统无法访问的位置(如驱动器缓存)。如果担心出现这种情况,则必须使用ATA 安全擦除。该操作会擦除设备上的所有区块,包括软件看不到的区块。详情请参见 cryptsetup FAQ 5.19。
分区
只有在加密整个系统时,才需用到本节。在安全地覆写驱动器后,必须慎重选择一个恰当的分区方案:要考虑到 dm-crypt 的要求,以及各种抉择对管理目标系统的影响。
还要考虑另一个重要因素:如何处理交换分区和系统挂起?参见 Dm-crypt/交换分区加密。
启动分区与 EFI 系统分区
在几乎所有情况下,必须单独留一个盛装内核与 initramfs 的未加密分区,以供引导加载程序访问(启动过程各部分的详情,参见Arch_的启动流程) 。
鉴于 mkinitcpio 默认把内核与 initramfs 置于 /boot/ 下,因而通常把这个未加密的分区挂载在 /boot 下。对于 /boot 分区的要求与限制的解释,见于分区##/boot。
在 UEFI 系统上,可以把 EFI 系统分区挂载在 /boot 下。鉴于按照定义,EFI 系统分区必须是主分区表中的未加密物理分区,这样做可以避免创建额外的未加密分区。EFI 系统分区特有的要求与限制,见于 EFI 系统分区一文。将 EFI 系统分区挂载在 /boot 下时,其同时也受 boot 分区的要求制约。
如果您仍然担忧留一个未加密分区的安全问题,参见 Dm-crypt/特殊应用#保护未加密的boot分区.
物理分区
在最简单的情况下,加密层可以直接基于物理分区;对于如何创建物理分区,请见分区。就像在未加密系统中,一个 root 分区就足够了,此外还需要一个上述的 /boot 分区。使用这个方法可以选择哪些分区加密,哪些分区不加密,无论涉及的磁盘数量多少,都可以正常工作。之后还可以添加或移除分区,但是调整分区的大小会被分区所基于的磁盘限制。最后请注意每个加密分区的开启都需要单独的密钥,即使这可以通过使用 crypttab 文件在启动时自动化,请见 Dm-crypt/系统配置#crypttab。
堆叠块设备
如果需要更高的灵活性,dm-crypt 可以和其他例如 LVM 和 RAID的堆叠块设备共存。加密容器可以位于其他堆叠块设备的之下或基于其他堆叠块设备上:
- 如果 LVM/RAID 设备创建在加密层上,那么在同一加密分区中可以自由地添加,移除文件系统和调整文件系统大小,所有的存储设备都只需要一个密钥或密码。因为加密层基于物理分区,但是这样就不能使用 LVM 和 RAID 跨越多个磁盘的能力。
- 如果加密层创建在 LVM/RAID 设备上,它之后依然有可能重组文件系统,但是复杂性会提高,因为加密层需要相应地调整。而且,每个加密设备的打开都需要一个密钥或密码。不过这是在跨越多个磁盘上创建加密文件系统的唯一选择。
Btrfs 子卷
Btrfs 的内建子卷功能可以和 dm-crypt 一起使用,如果不需要其他文件系统,则完全取代对 LVM 的需求。
加密的启动分区 (GRUB)
无需未加密分区的例外情况:在 BIOS/MBR 上使用 GRUB 时。此时 GRUB (未加密地)储存在 MBR 引导代码区域,而 MBR 之后的间隔,以及其他分区均可加密。