What You See Is What You Get Element

使用 ZFS 加密

适用于 Oracle Solaris 11.1

作者:Alexandre Borges

本文是系列文章的第 5 部分,介绍 Oracle Solaris 11.1 中 ZFS 的关键特性,并提供分步过程说明如何使用这些特性。本文重点介绍加密和解密文件、文件系统和池的不同方法。


2014 年 7 月发布


右箭头 第 1 部分 — 使用 COMSTAR 和 ZFS 配置虚拟化存储环境
右箭头 第 2 部分 — 使用交换监视和使用 ZFS 卷扩大交换空间
右箭头 第 3 部分 — 使用 ZFS 影子迁移
右箭头 第 4 部分 — 将 ZFS 数据集委托给非全局区域
右箭头 第 5 部分 — 使用 ZFS 加密
右箭头 第 6 部分 — 使用 ZFS 快照

想对本文发表评论吗?请将链接发布在 Facebook 的 OTN Garage 页面上。有类似文章要分享?请将其发布在 Facebook 或 Twitter 上,我们来进行讨论。

Oracle Solaris 11 支持在 ZFS 上采用原生方式加密来保护关键数据,无需依赖外部程序。它还与 Oracle Solaris 加密框架集成,后者提供了多种对称和非对称算法来加密文件和整个文件系统,使加密更轻松、更快速。此外,在新建的文件系统上启用 ZFS 加密时,所有后代文件系统将自动继承加密。为了提高灵活性,加密文件系统可以与非加密文件系统共处同一池中。

以下是支持的对称算法及其各自机制:

root@solaris11-1:~# encrypt -l
Algorithm       Keysize:  Min   Max (bits)
------------------------------------------
aes                       128   256
arcfour                     8  2048
des                        64    64
3des                      128   192

root@solaris11-1:~# cryptoadm list -m provider=aes
aes: CKM_AES_ECB,CKM_AES_CBC,CKM_AES_CTR,CKM_AES_CCM,CKM_AES_GCM,CKM_AES_GMAC,
CKM_AES_CFB128,CKM_AES_XTS,CKM_AES_XCBC_MAC
root@solaris11-1:~#

在可用选项中,128 位 AES CCM 模式为默认值。如果在某些文件系统上使用重复数据删除,结合使用加密和重复数据删除时需要采用 CCM 模式。

在运行 Oracle Solaris 11 的系统上可以用多种方法使用 ZFS 加密。下面将逐一介绍。

方法一

我们可以使用相同的算法加密单个文件或整个文件系统。下面是加密单个文件的示例:

root@solaris11-2:/tmp# cp /etc/hosts /tmp/
root@solaris11-2:/tmp# cd /tmp/
root@solaris11-2:/tmp# encrypt -a aes -i /tmp/hosts -o /tmp/hosts.aes
Enter passphrase:
Re-enter passphrase:

root@solaris11-2:/tmp# file hosts*
hosts:       ascii text
hosts.aes:   data

输入密码 oracle123!,一切顺利。可以看出,文件已加密。

如果要解密文件,可以使用以下命令:

root@solaris11-2:/tmp# decrypt -a aes -i /tmp/hosts.aes -o /tmp/hosts.decrypted
Enter passphrase:

root@solaris11-2:/tmp# file hosts*
hosts:           ascii text
hosts.aes:       data
hosts.decrypted: ascii text

root@solaris11-2:/tmp# more hosts.decrypted
#
# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# Internet host table
#
::1 solaris11-1 localhost
127.0.0.1 solaris11-1 solaris11.example.com localhost loghost
192.168.1.105 solaris11-1.example.com solaris11-1
192.168.1.102 solaris11-2.example.com solaris11-2
192.168.1.250 freenas.example.com freenas
root@solaris11-1:/tmp#

很简单。可以执行类似以下操作加密整个文件系统:

root@solaris11-2:~# zpool create pool_encr c8t3d0
root@solaris11-2:~# zfs create -o encryption=on pool_encr/fs_encr_1
Enter passphrase for 'pool_encr/fs_encr_1':
Enter again:
root@solaris11-2:~#

默认情况下,ZFS 加密会提示输入密码短语,如以上示例所示。

输入同样的密码短语 (oracle123!)。如果我们新建一个后代文件系统,将从父文件系统继承密码短语。

首先要注意,文件系统的解密方式不可能与单个文件的解密方式一样。另一个区别是,我们必须采用交互方式输入密码短语。对某些文件系统而言,这不是问题,但在大型环境中部署时,以交互方式输入密码短语的确是个问题。

更好的办法是将密码短语存储在计算机之外:

root@solaris11-1:/# zpool destroy pool_encr          
root@solaris11-1:/# zpool create pool_encr c8t3d0
root@solaris11-1:/# echo "oracle123" > /media/ORA_PENDRIV/oracle_encryption_key
root@solaris11-1:/# more /media/ORA_PENDRIV/oracle_encryption_key
oracle123
root@solaris11-1:/# zfs create -o encryption=on \
-o keysource=passphrase,file:///media/ORA_PENDRIV/oracle_encryption_key pool_encr/fs_encr_2

在这种情况下,我们还需要保护可移动设备(捷盘),因为密码短语保存在上面。注意,只有当系统能够访问可移动设备时,才会在启动过程中挂载文件系统,但即便没有加密密钥,系统仍可以启动。

重要事项:最后提醒一下,Oracle Solaris 11 不能 按照解密单个加密文件的方式解密加密的文件系统。

方法二

另一种办法是使用封装密钥。封装密钥用于加密执行加密所用的真正(对称)密钥。换句话说,使用封装密钥时,我们将对称密钥存储在密钥库中,使用封装密钥对其加密,然后在需要对称密钥加密文件系统时,访问密钥并使用封装密钥以非交互模式对其解密。

封装密钥可以是密码短语(类似于密码),也可以是原始密钥,仅在初始挂载文件系统时才需要。

与第一种方法不同,为了提供进一步的保护,我们可以将封装密钥存储在 Oracle Solaris 加密框架中,后者是一种由软令牌加密的密钥库。该密钥库的初始密码短语为 changeme,需要更改:

root@solaris11-2:/# pktool setpin
Enter token passphrase: changeme
Create new passphrase: borges123
Re-enter new passphrase: borges123
Passphrase changed.
root@solaris11-2:/#	

执行以下命令查看可用令牌:

root@solaris11-2:~# pktool tokens
Flags: L=Login required  I=Initialized  X=User PIN expired  S=SO PIN expired
Slot ID  Slot Name                    Token Name                        Flags     
-------  ---------                    ----------                        -----     
1        Sun Crypto Softtoken         Sun Software PKCS#11 softtoken    LI     

我们来创建一些密钥,然后将它们列出:

root@solaris11-2:~# pktool genkey keytype=aes keylen=192 label=otn1
Enter PIN for Sun Software PKCS#11 softtoken: borges123

root@solaris11-2:~# pktool genkey keytype=aes keylen=256 label=otn2
Enter PIN for Sun Software PKCS#11 softtoken:

root@solaris11-2:~# pktool list objtype=key
Enter PIN for Sun Software PKCS#11 softtoken:
Found 2 symmetric keys.
Key #1 - AES:  otn1 (192 bits)
Key #2 - AES:  otn2 (256 bits)

可以看出,第一条 pktool genkey 命令使用 192 位 AES 算法创建一个名为 otn1 的新密钥,第二条 pktool genkey 命令使用 256 位 AES 算法创建一个名为 otn2 的密钥。

这次,我们使用 Oracle Solaris 加密框架重复上述过程对文件加密:

root@solaris11-2:~# cp /etc/hosts /tmp/
root@solaris11-2:~# cd /tmp/
root@solaris11-2:/tmp# encrypt -a aes -K otn2 -i /tmp/hosts -o /tmp/hosts.aes256
Enter PIN for Sun Software PKCS#11 softtoken: borges123


root@solaris11-2:/tmp# file /tmp/hosts*
/tmp/hosts:         ascii text
/tmp/hosts.aes256:  data

我们做到了!没有人知道真正的密码,只是知道它存储在 Oracle Solaris 11 密钥库中。使用密码短语 (borges123) 加密示例文件(/etc/hosts 的副本)。这样很好:我们不知道对称密钥本身,因为只需输入密钥库的 PIN(密码短语)。

然后,可以使用相同的方法解密文件:

root@solaris11-2:/tmp# decrypt -a aes -K otn2 -i /tmp/hosts.aes256 \
-o /tmp/hosts.decrypted
Enter PIN for Sun Software PKCS#11 softtoken:

root@solaris11-2:/tmp# file /tmp/host*
/tmp/hosts:            ascii text
/tmp/hosts.aes256:     data
/tmp/hosts.decrypted:  ascii text

开始加密文件系统之前,必须提到的是,密钥可以存储在密钥库之外。在本例中,由我们负责管理密钥:

root@solaris11-2:/tmp# pktool genkey keystore=file outkey=/mykeys/otn3 \
keytype=aes keylen=256
root@solaris11-2:/tmp# ls -al /mykeys/otn3
-r--------   1 root     root          32 Dec  9 19:14 /mykeys/otn3
root@solaris11-2:/tmp# file /mykeys/otn3
/mykeys/otn3:    data
root@solaris11-2:/tmp# pktool list objtype=key
Enter PIN for Sun Software PKCS#11 softtoken: borges123
Found 2 symmetric keys.
Key #1 - AES:  otn1 (192 bits)
Key #2 - AES:  otn2 (256 bits)
root@solaris11-2:/tmp#

我们可以从输出中看到,密钥未存储在 Oracle Solaris 11 密钥库(软令牌)。

要使用 PKCS#11 方法(软密钥)加密整个文件系统,请执行以下操作:

root@solaris11-2:~# zpool create softtoken_pool c8t4d0

root@solaris11-2:~# zfs create -o encryption=aes-256-ccm \
-o keysource=raw,pkcs11:object=otn2 softtoken_pool/fs_softtoken_1
Enter PKCS#11 token PIN for 'softtoken_pool/fs_softtoken_1': borges123

root@solaris11-2:~# zfs list -r softtoken_pool               
NAME                            USED  AVAIL  REFER  MOUNTPOINT
softtoken_pool                 140K  3.91G    32K  /softtoken_pool
softtoken_pool/fs_softtoken_1   33K  3.91G    33K  /softtoken_pool/fs_softtoken_1

好棒。对称密钥存储在 PKCS#11 密钥库内。然后,zfs create 命令使用它创建和加密 softtoken_pool/fs_softtoken_1 文件系统。

试试收集有关文件系统加密的进一步信息:

root@solaris11-2:~# zfs get encryption softtoken_pool/fs_softtoken_1
NAME                            PROPERTY   VALUE        SOURCE
softtoken_pool/fs_softtoken_1  encryption  aes-256-ccm  local

root@solaris11-2:~# zfs get keysource softtoken_pool/fs_softtoken_1
NAME                            PROPERTY  VALUE                   SOURCE
softtoken_pool/fs_softtoken_1  keysource  raw,pkcs11:object=otn2  local

使用另一个密钥创新建文件系统很简单:

root@solaris11-2:~# zfs create -o encryption=aes-192-ccm \
-o keysource=raw,pkcs11:object=otn1 softtoken_pool/fs_softtoken_2
Enter PKCS#11 token PIN for 'softtoken_pool/fs_softtoken_2': borges123

root@solaris11-2:~# zfs get encryption softtoken_pool/fs_softtoken_2
NAME                            PROPERTY   VALUE        SOURCE
softtoken_pool/fs_softtoken_2  encryption  aes-192-ccm  local

root@solaris11-2:~# zfs get keysource softtoken_pool/fs_softtoken_2
NAME                            PROPERTY  VALUE                   SOURCE
softtoken_pool/fs_softtoken_2  keysource  raw,pkcs11:object=otn1  local

root@solaris11-2:~# zfs list -r softtoken_pool
NAME                            USED  AVAIL  REFER  MOUNTPOINT
softtoken_pool                 194K  3.91G    33K  /softtoken_pool
softtoken_pool/fs_softtoken_1   33K  3.91G    33K  /softtoken_pool/fs_softtoken_1
softtoken_pool/fs_softtoken_2   33K  3.91G    33K  /softtoken_pool/fs_softtoken_2

最后,可以加密整个池(并不仅限于某些文件系统):

root@solaris11-2:~# zpool create -o encryption=on \
-o keysource=raw,pkcs11:object=otn1 softtoken_pool_2 c8t5d0
Enter PKCS#11 token PIN for 'softtoken_pool_2': borges123

root@solaris11-2:~# zfs create softtoken_pool_2/fs_softtoken_3
root@solaris11-2:~# zfs create softtoken_pool_2/fs_softtoken_4

非常有趣:创建了加密池,且需要 pin 号(即密钥库的密码短语),但在创建后代文件系统(fs_softtoken_3fs_softtoken_4)时,不会提示输入密码短语,因为后代文件系统继承了父文件系统的加密密钥。运行以下命令即可验证:

root@solaris11-2:~# zfs get encryption,keysource softtoken_pool_2/fs_softtoken_3 \
softtoken_pool_2/fs_softtoken_3
NAME                             PROPERTY    VALUE                   SOURCE
softtoken_pool_2/fs_softtoken_3  encryption  on                      inherited from softtoken_pool_2
softtoken_pool_2/fs_softtoken_3  keysource   raw,pkcs11:object=otn1  inherited from softtoken_pool_2
softtoken_pool_2/fs_softtoken_3  encryption  on                      inherited from softtoken_pool_2
softtoken_pool_2/fs_softtoken_3  keysource   raw,pkcs11:object=otn1  inherited from softtoken_pool_2

令人惊叹。跟我们预测的完全一样。

另请参见

以下是我撰写的其他一些文章的链接:

以下是有关 Oracle Solaris 11 的一些资源:

关于作者

Alexandre Borges 是一位 Oracle ACE,曾于 2001 至 2010 年任职于 Sun Microsystems,并担任签约讲师,主要负责讲授 Oracle Solaris、Oracle Solaris Cluster、Oracle Solaris 安全性、Java EE、Sun 硬件和 MySQL 课程。目前,他为 Symantec、Oracle 合作伙伴、Hitachi 和 EC-Council 提供课程教学,并且讲授一些关于信息安全的非常专业的课程。此外,他还是 Linux Magazine Brazil 的特约撰稿人和专栏作家。

修订版 1.0,2014 年 7 月 15 日

关注我们:
博客 | Facebook | Twitter | YouTube