管理加密的ZFS文件系统:更换密钥和备份

2020-09-01 Technical Salty Fish 0条

本文是关于我在这篇文章中创建的加密ZFS文件系统的日常管理的技术笔记。

更换加密ZFS文件系统的密钥

上次在处理密钥的时候有几次操作不够谨慎,导致密钥在一些磁盘上留下了痕迹(忘了使用shred安全抹除),好在我们看到的密钥[并不是]()ZFS真正用来加密信息的encryption key,而是用于管理encryption keywrapping key,因此只要换掉这个密钥就可以了,非常方便。

A wrapping key is used to encrypt the actual data encryption keys. A wrapping key is either in a file (in raw or hex format) or it is derived from a passphrase. ——Managing ZFS File Systems in Oracle® Solaris 11.3

更换密钥的过程非常简单,首先用dd命令生成新key,然后:

# zfs change-key -o keyformat=raw -o keylocation=file:///etc/zfs/data.key data/mailserver

另外要提几点:

  • 在ZoL的实现中,默认的加密方式是aes-256-ccm,这比Solaris ZFS里的默认值aes-128-ccm安全了很多倍。在量子计算的时代背景下,256位的AES加密仍然被认为是安全的,而128位就不那么安全了。但是相比于gcm,ccm的安全性又要差一些。所以建议有能力的朋友上aes-256-gcm
  • ZoL里的wrapping key一定是256位,即使你用的加密方式是128位或192位的。
  • encryption key也是允许更换的,但是新key只用于写入新数据,旧数据还是由旧key保护。

备份加密的ZFS文件系统

使用ZFS快照

ZFS快照是一种copy-on-write快照,也就是说创建之初是不额外占用磁盘空间的,我喜欢。

创建ZFS快照相当简单:

zfs snapshot data/mailserver@snapshot

其中后面的snapshot是快照名。我更喜欢用时间命名快照:

zfs snapshot data/mailserver@`date +%Y%m%d-%H%M%S-%N

创建好后,就可以在/data/mailserver/.zfs/snapshot/(快照名)中看到刚刚创建的快照了。里面的内容和/data/mailserver/完全一样,不过是只读的。

这里的.zfs是一个特殊的目录,它在ls -a /data/mailserver中是看不见的,但是可以cd进去。你可以通过zfs set snapdir=visible data/mailserver来显示这个目录,然后就可以在ls -a中看见它了。不过一直显示它不是一个好主意,因为会让find等命令变得。把snapdir属性设置成hidden就可以重新隐藏.zfs了。

注:ZFS提供了细致的权限管理,因此有一些命令并不需要在root环境下执行。我给了自己账户部分权限,一些不常用的命令没有给。你可以根据需要调节这些权限来避免每次都要sudo

ZFS快照是atomic的,不会给服务造成downtime,也不存在快照数据不consistent的风险,非常适合作为备份策略采用。

备份快照里的内容

ZFS原生有一个很棒的功能:zfs send。这个命令可以把一整个ZFS文件系统导出成可以由zfs recv命令接收的stream。其中-w参数指定raw导出,保留ZFS的加密。zfs send还可以通过-i参数指定增量输出:指定两个快照,zfs send会比较两个快照,输出有改动的部分。这个增量信息也可以由zfs recv在较旧的快照基础上接收,从而将旧的快照更新为较新的版本。

这样一来,强大的ZFS帮我解决了三件大事:打包、加密、增量备份。接下来是实际操作,假设已经有了一个快照:

~ > zfs list -o name,mountpoint
NAME                                       MOUNTPOINT
data                                       /data
data/mailserver                            /data/mailserver
data/mailserver@20200217-141330-016045667  -
~ > zfs send -w data/mailserver@20200217-141330-016045667 |gzip >[email protected]
~ > ls
[email protected]

为了节省空间,我采用gzip压缩备份文件。这个文件现在就可以在gzip解压缩后由ZFS导入,我们来试一下:

~ > gzip -cd [email protected] | sudo zfs recv data/mailserver_recovered
~ > zfs list -o encryption,name,mountpoint
 ENCRYPTION  NAME                                                 MOUNTPOINT
        off  data                                                 /data
aes-256-ccm  data/mailserver                                      /data/mailserver
aes-256-ccm  data/mailserver@20200217-141330-016045667            -
aes-256-ccm  data/mailserver_recovered                            /data/mailserver_recovered
aes-256-ccm  data/mailserver_recovered@20200217-141330-016045667  -
~ > ls /data
mailserver
~ > zfs load-key -a
Key load error: Cannot enter raw keys on the terminal
Key load error: Cannot enter raw keys on the terminal
Key load error: Cannot enter raw keys on the terminal
0 / 1 key(s) successfully loaded
~ > zfs get keyformat,keylocation data/mailserver_recovered
NAME                       PROPERTY     VALUE        SOURCE
data/mailserver_recovered  keyformat    raw          -
data/mailserver_recovered  keylocation  prompt       local

可以看到,第一条命令从备份文件新建了一个data/mailserver_recovered文件系统,并且保留了原文件系统的加密。需要加载key才能挂载这个刚导入的文件系统,不过因为send过程没有保留keylocation属性,需要自己设置一下。我临时把密钥文件放到了家目录下一份。

~ > sudo zfs set keylocation=file:///home/saltyfish/data.key data/mailserver_recovered
~ > sudo zfs load-key -a
1 / 1 key(s) successfully loaded
~ > sudo zfs mount -a
~ > ls /data
mailserver  mailserver_recovered

挂载成功,检查一下可以确认mailserver_recoveredmailserver原来的内容完全一样。测试成功,# zfs destroy -r data/mailserver_recovered,然后随手用随机数据覆写50次销毁密钥。

上传到云端

我有个用edu邮箱白嫖的Onedrive for Business,有如下特征:

  • 5T空间,大!
  • 不被神秘魔法影响
  • 不要钱 不限速
  • 数据安全没有保障

用来备份太合适了,毕竟备份不需要经常访问,加密储存不会不方便,可以很好地克服数据不安全的问题。

我最开始打算用duplicati直接备份snapshot目录,但是这样实现增量备份就比较麻烦,虽然duplicati内置增量备份功能,但我要增量备份的不是snapshot目录啊!把备份源改来改去,太麻烦;保持快照名不变,更麻烦。更重要的是,duplicati里的SharePoint不好使,测试了很多版本都不行。据作者说是巨硬提供的接口有问题,那这咱没办法。另外,zfs send它不香吗(滑稽)~

四处找了一圈,似乎用rclone是一个不错的连接Onedrive for Business的方法。rclone非常小巧,使用也简单,配置好后一句rclone copy 就能把文件上传到Onedrive for Business。首先安装rclone,用apt install就可以了。然后执行rclone config,跟着提示走就可以了。其中授权步骤需要一个浏览器,不过rclone很贴心地提供了在自己电脑上获取授权码并粘贴进terminal的方式,方便了配置headless机器的用户。

配置好之后,就可以使用rclone上传备份了:

~ > rclone copy [email protected] 1drv:server_backups/mailserver/ -P
Transferred:          11.059M / 11.059 MBytes, 100%, 470.755 kBytes/s, ETA 0s
Transferred:            1 / 1, 100%
Elapsed time:        24.0s

其中-P参数指定显示进度。当然,rclone copy也可以从云端下载文件。目前还不是很方便,需要定期手动执行备份,大一点的文件可能就需要丢到screen去挂着。过段时间可能会写个脚本实现自动备份(自挖大坑)。

网速较快的环境下,可以观察到rclone会在10M处卡一段时间。我又做了一些测试,发现较大的文件会在每一个10M倍数处都卡一段时间。研究了一下发现有这样一个参数:--onedrive-chunk-size,其默认值是10M。我把它调成了240M,上传速度得到了极大的提升。没有设成更大的值是因为我的Onedrive接受的最大请求只有250M。关于这个参数的细节,参见rclone官网上的说明

结语

本文探讨了加密ZFS文件系统的一些日常管理,包括修改密钥和完整的备份方案。很惭愧,就做了一点微小的工作,谢谢大家!