使用 ZFS 原生加密保护数据
作者:Roller Angel
ZFS 原生支持加密数据集,能让你轻松地使用行业标准的密码套件来保护数据。与磁盘的全盘加密相比,将数据集加密的主要优势在于,当未使用数据集时,可以将其卸载,而全盘加密要求在静止状态下加密时,磁盘必须关闭。请记住,ZFS 原生加密有加载和卸载密钥的概念。仅仅卸载加密的数据集是不够的,你还必须卸载与该数据集关联的密钥。如果密钥仍然处于加载状态,数据集可以被挂载并且数据将可用。卸载密钥会使挂载操作失败。加载密钥是挂载数据集的前提。嵌套的子数据集会继承其父数据集的加密密钥,但这并非必须。即使父数据集使用不同的加密设置,也可以使用不同的加密密钥和密码套件。最后,更改密钥就像在数据集上执行 zfs change-key
命令一样简单。
这些是开始使用的基础概念。
为新创建的数据集启用加密参数,再设置密钥格式就足够了。如果未指定加密密码套件,则默认使用 aes-256-gcm。默认值可能会随着未来新增密码套件而变化。现有数据集的加密属性是只读的,无法修改未加密的数据集的属性来启用加密。要指定加密属性,你需要了解有哪些参数可用。我建议阅读 zfsprops
手册页,你可以输入命令 man zfsprops
来查看。我还建议阅读 zfs-load-key
的手册页。对于我们的第一个加密数据集,我们将使用默认的密码套件、口令密钥格式,来创建一个名为 secrets
的数据集。我使用的是我实验室中创建的 FreeBSD jail 机器,名为 alice。实验室中的所有 jail 都位于名为 lab
的 zpool 上。我已将叫 zroot
的 zpool 分配给 jail 。在 jail 中,我必须使用完整路径 lab/alice/zroot
作为 zpool 名称,以便在其中创建数据集。作为对比,我的笔记本电脑上,我可以直接使用我的 zpool 名称并在那里创建数据集。以下是创建加密数据集的命令,适用于 alice jail 和我的笔记本电脑。同其他 ZFS 数据集一样,设置挂载点是一个好主意,但请记住 ZFS 是个分层文件系统,因此不要使用现有路径作为新数据集的挂载点。
alice jail:
我的笔记本:
在运行 zfs create
命令后,提示我输入一个足够长的口令。现在,我有了一个已挂载的加密数据集,可以在其中存储需要保护的数据。当数据集处于挂载状态时,我可以像使用其他未加密的数据集一样使用它。当我完成机密数据的添加后,我可以通过输入命令 zfs unmount -u lab/alice/zroot/secrets
一次性卸载数据集和密钥。要解密、重新挂载数据,只需运行命令 zfs mount -l lab/alice/zroot/secrets
。这会提示我输入口令,加载密钥,然后挂载数据集。如果在卸载命令中省略参数 -u
,只会卸载数据集,密钥仍然会保持加载状态。数据集仍然可以通过 zfs mount lab/alice/zroot/secrets
挂载,而无需输入口令。要在数据集已卸载后卸载密钥,我运行 zfs unload-key lab/alice/zroot/secrets
。现在,之前的挂载命令将失败,因为密钥没有加载,并且我未提供参数 -l
来让 ZFS 在挂载之前加载密钥。要加载密钥且允许挂载数据集,我会运行 zfs load-key lab/alice/zroot/secrets
。系统会提示我输入口令,之前的挂载命令现在会成功,因为密钥已经加载。要检查密钥是否已加载,可以查看数据集的属性。当我运行命令 zfs list -o name,mountpoint,encryption,keylocation,keyformat,keystatus,encryptionroot lab/alice/zroot/secrets
时,会显示一些有用的属性。KEYSTATUS
列显示为 "available" 时,表示密钥已加载。要查看所有数据集属性,可以使用 zfs get all lab/alice/zroot/secrets
。
接下来,我在 secrets
数据集下创建一个嵌套的数据集,并使用不同的密码套件和密钥格式。这次,我将使用密钥文件而非口令。要创建使用密钥文件的数据集,我首先需要生成密钥并将其存储在文件中。我通过输入命令 dd if=/dev/urandom bs=32 count=1 of=/media/more-secrets.key
来完成。由于密钥文件要求长度为 32 字节,因此我使用了 bs=32
。输出路径选择 /media
,因为我在此路径下挂载了一个便携式 USB 驱动器,还使用 dd
命令生成了密钥文件,再将其直接存储到驱动器上。这样,当我卸载密钥并卸载和移除 USB 驱动器时,密钥文件就不会留在我的机器上。我建议将密钥文件存储在多个 USB 驱动器上,以防某个 USB 驱动器损坏。现在,密钥文件已经生成,我可以通过运行命令 zfs create -o encryption=aes-256-ccm -o keyformat=raw -o keylocation=file:///media/more-secrets.key -o mountpoint=/secrets/more-secrets lab/alice/zroot/secrets/more-secrets
来创建使用 AES-256-CCM 密码套件的嵌套数据集。查看这个新数据集的属性时,我可以看到 ENCROOT
列设置为 lab/alice/zroot/secrets/more-secrets
。我可以使用与 secrets
数据集相同的方法来卸载和卸载密钥。当我拥有更多数据集和密钥时,我可能想考虑使用 zfs unload-key -a
卸载所有密钥,或使用 zfs unload-key -r lab/alice/zroot/secrets
来仅卸载 secrets
数据集及其所有后代数据集的密钥。而且,如果我想加载 secrets
数据集及其所有后代数据集的密钥子集,可以运行 zfs load-key -r lab/alice/zroot/secrets
。
如果我后来决定 more-secrets
数据集中的数据不需要单独的密钥文件,而是希望它继承父数据集 secrets
的设置(即从自定义生成的密钥文件切换到之前配置的口令),我只需要运行命令 zfs change-key -i lab/alice/zroot/secrets/more-secrets
。再次查看属性,注意到 ENCROOT
、KEYLOCATION
和 KEYFORMAT
都已经发生了变化。然而,密码套件不会改变,因为密码套件只能在数据集创建时设置。由于 more-secrets
是包含在 secrets
中的,它将作为卸载 secrets
数据集的一部分被卸载。虽然挂载 secrets
数据集不会自动挂载 more-secrets
,但它需要单独挂载。不过,由于它们共享相同的密钥,所以密钥只需要加载一次。要切换回使用密钥文件,我运行命令 zfs change-key -o keyformat=raw -o keylocation=file:///media/more-secrets.key lab/alice/zroot/secrets/more-secrets
。如果我想永久销毁 more-secrets
中的数据,我只需卸载数据集、卸载密钥,并销毁密钥文件及我所做的任何备份副本。现在,数据将无法恢复。然后,我可以运行命令 zfs destroy lab/alice/zroot/secrets/more-secrets
来移除该数据集。
最后,我想分享的一点是关于加密数据的备份。如你所见,ZFS 原生加密能轻松地使用加密来保护数据。加密数据集的快照可以以加密形式传输到不受信任的备份服务器上。没有密钥,远程备份服务器就无法挂载该数据集。可以使用 zfs send
命令的参数 --raw
来实现这一点。有关更多细节,我建议阅读 zfs-send
的手册页,以了解其工作原理,然后获取《ZFS Mastery: Advanced ZFS》一书,深入研究具体细节,并学习一系列技巧,以进一步提升你的 ZFS 技能。
希望你喜欢这篇操作指南,并且开始使用 ZFS 文件系统提供的原生加密来保护你的敏感数据。
Roller Angel 大部分时间都在帮助人们学习如何使用技术实现他们的目标。他是一位热衷于 FreeBSD 系统管理的 Python 爱好者,喜欢学习开源技术(尤其是 FreeBSD 和 Python)解决问题的神奇方法。他坚信人们可以学习所有他们愿意去做的事情。Roller 总是在寻找创造性的解决方案,享受解决问题的挑战。他有很强的学习动机,喜欢探索新想法,并保持技能的敏锐。他喜欢参与研究社区,并分享自己的想法。
最后更新于