cryptsetup - setup cryptographic volumes for dm-crypt (including LUKS extension)

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
密钥管理服务KMS,1000个密钥,100个凭据,1个月
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介:
前面几篇BLOG介绍了PostgreSQL 数据传输的加密. 数据传输加密可以防止数据在传输过程中泄露.

本篇主要介绍一下数据存储的加密.
存储加密的好处是, 不用担心因为硬盘被盗导致的数据泄露.
存储加密的方法很多, 有些硬件厂商就提供了硬件层面的加密.
本文主要介绍一下Linux下面的卷加密的软件cryptsetup.
还有很多其他加密手段请参考本文末尾wiki.
需要用到 cryptsetup-luks-1.0.3-8.el5这个包.
[root@db-172-16-3-33 postgresql-9.3beta1]# which cryptsetup
/sbin/cryptsetup
[root@db-172-16-3-33 postgresql-9.3beta1]# rpm -qf /sbin/cryptsetup
cryptsetup-luks-1.0.3-8.el5
cryptsetup-luks-1.0.3-8.el5
[root@db-172-16-3-33 postgresql-9.3beta1]# rpm -ql cryptsetup-luks-1.0.3-8.el5
/sbin/cryptsetup
/usr/lib64/libcryptsetup.so.0
/usr/lib64/libcryptsetup.so.0.0.0
/usr/share/doc/cryptsetup-luks-1.0.3
/usr/share/doc/cryptsetup-luks-1.0.3/AUTHORS
/usr/share/doc/cryptsetup-luks-1.0.3/COPYING
/usr/share/doc/cryptsetup-luks-1.0.3/ChangeLog
/usr/share/doc/cryptsetup-luks-1.0.3/INSTALL
/usr/share/doc/cryptsetup-luks-1.0.3/NEWS
/usr/share/doc/cryptsetup-luks-1.0.3/README
/usr/share/locale/de/LC_MESSAGES/cryptsetup-luks.mo
/usr/share/man/man8/cryptsetup.8.gz

注意本例是磁盘级加密, 不是文件系统加密, 也不是文件级的加密.
Linux Unified Key Setup or LUKS is a disk-encryption specification

[举例]
使用/dev/mapper/vgdata01-lv01这个设备作为加密设备.
[root@db-172-16-3-33 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/cciss/c0d0p1      29G   16G   12G  57% /
tmpfs                 6.9G     0  6.9G   0% /dev/shm
/dev/mapper/vgdata01-lv03
                      135G   35G   93G  28% /pgdata/digoal/1921/data03
/dev/mapper/vgdata01-lv04
                      135G   69G   59G  54% /pgdata/digoal/1921/data04
/dev/mapper/vgdata01-lv05
                      135G   85G   44G  66% /pgdata/digoal/1921/data05
[root@db-172-16-3-33 ~]# lvs
  LV   VG       Attr   LSize   Origin Snap%  Move Log Copy%  Convert
  lv03 vgdata01 -wi-ao 136.70G                                      
  lv04 vgdata01 -wi-ao 136.70G                                      
  lv05 vgdata01 -wi-ao 136.70G                                      
  lv06 vgdata01 -wi-a-  99.40G

1. 方法1 : 使用密钥文件解密
随便找一个文件即可. 但是权限最好弄成400.
[root@db-172-16-3-33 ~]# pwd
/root
[root@db-172-16-3-33 ~]# chmod 400 ssl.dmp
-r--------  1 root root     6838 May 22 17:29 ssl.dmp


新建一个device mapper设备.
[root@db-172-16-3-33 ~]# cryptsetup create cry_test1 /dev/mapper/vgdata01-lv06 --cipher aes-cbc-essiv:sha256 --key-file ./ssl.dmp

查看新建好的dm设备状态.
[root@db-172-16-3-33 ~]# cryptsetup status cry_test1
/dev/mapper/cry_test1 is active:
  cipher:  aes-cbc-essiv:sha256
  keysize: 256 bits
  device:  /dev/mapper/vgdata01-lv06
  offset:  0 sectors
  size:    208453632 sectors
  mode:    read/write

通过/dev/mapper/cry_test1新建文件系统.
[root@db-172-16-3-33 ~]# mkfs.ext4 /dev/mapper/cry_test1

修改/etc/fstab
vi /etc/fstab
/dev/mapper/cry_test1  /mnt  ext4  defaults,noatime,nodiratime 0 0

使用mount -a可以挂载
mount -a
df -h
/dev/mapper/cry_test1
                       98G  188M   93G   1% /mnt
[root@db-172-16-3-33 ~]# cd /mnt
[root@db-172-16-3-33 mnt]# ll
total 16
drwx------ 2 root root 16384 May 23 16:17 lost+found
[root@db-172-16-3-33 mnt]# dd if=/dev/zero of=./test.img bs=1024k count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.930429 seconds, 1.2 GB/s
[root@db-172-16-3-33 mnt]# ll
total 1048592
drwx------ 2 root root      16384 May 23 16:17 lost+found
-rw-r--r-- 1 root root 1073741824 May 23 16:25 test.img


重启服务器, 无法自动 挂载/mnt, 原因 :
mount: special device /dev/mapper/cry_test1 does not exist

但是系统能正常进入.

解决办法是编写/etc/crypttab
格式 :
dm-name devic-name keyfile option1=val1,option2=val2,...

详见man crypttab
例如我这里写的是 :
cry_test1 /dev/mapper/vgdata01-lv06 /root/ssl.dmp cipher=aes-cbc-essiv:sha256

再次重启, 自动挂载成功.
[root@db-172-16-3-33 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/cciss/c0d0p1      29G   16G   12G  56% /
tmpfs                 6.9G     0  6.9G   0% /dev/shm
/dev/mapper/cry_test1
                       98G  1.2G   92G   2% /mnt


密钥文件非常重要, 如果与磁盘一起丢失了, 那么也是可以被挂载的.

2. 方法2 : 
当然也可以不使用密钥文件进行解密, 使用passphrase也是可以的.
[root@db-172-16-3-33 ~]# umount /mnt
[root@db-172-16-3-33 ~]# cryptsetup remove cry_test1

[root@db-172-16-3-33 ~]# cryptsetup create cry_test1 /dev/mapper/vgdata01-lv06 --cipher aes-cbc-essiv:sha256
Enter passphrase: 

假设输入digoal
需要重新格式化 :
[root@db-172-16-3-33 ~]# mkfs.ext4 /dev/mapper/cry_test1
mount -a
[root@db-172-16-3-33 ~]# cd /mnt
[root@db-172-16-3-33 mnt]# ll
total 16
drwx------ 2 root root 16384 May 23 16:48 lost+found
[root@db-172-16-3-33 mnt]# touch abc

使用passphrase解密, 在系统重启后无法自动挂载, 原因和前面一样, 需要在系统进入后新建这个dm设备.
可能是crypttab格式不正确.
如果重启后出现挂载失败的话, 需要重新创建一下设备, 但是注意密码要输正确, 否则挂载时会报fs类型不正确.
重新创建, 输入正确的密码即可.
[root@db-172-16-3-33 ~]# mount -a
mount: special device /dev/mapper/cry_test1 does not exist
[root@db-172-16-3-33 ~]# cryptsetup create cry_test1 /dev/mapper/vgdata01-lv06 --cipher aes-cbc-essiv:sha256 
Enter passphrase: 

输入正确的密码.
输入密码错误并不会破坏数据. 重新创建并输入正确即可.
[root@db-172-16-3-33 ~]# mount -a
[root@db-172-16-3-33 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/cciss/c0d0p1      29G   16G   12G  56% /
tmpfs                 6.9G     0  6.9G   0% /dev/shm
/dev/mapper/vgdata01-lv03
                      135G   35G   93G  28% /pgdata/digoal/1921/data03
/dev/mapper/vgdata01-lv04
                      135G   69G   59G  54% /pgdata/digoal/1921/data04
/dev/mapper/vgdata01-lv05
                      135G   85G   44G  66% /pgdata/digoal/1921/data05
/dev/mapper/cry_test1
                       98G  188M   93G   1% /mnt

3. 方法3
cryptsetup还支持LUKS,  Linux  Unified Key Setup扩展.
使用方法与上面两种方法类似.
创建一个加密设备
[root@db-172-16-3-33 ~]# cryptsetup luksFormat /dev/mapper/vgdata01-lv06 --cipher aes-cbc-essiv:sha256

WARNING!
========
This will overwrite data on /dev/mapper/vgdata01-lv06 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase: 
输入digoal
Verify passphrase: 
输入digoal
Command successful.

新建dm设备 : 
[root@db-172-16-3-33 ~]# cryptsetup luksOpen /dev/mapper/vgdata01-lv06 lukstest1
Enter LUKS passphrase for /dev/mapper/vgdata01-lv06: 
输入digoal
key slot 0 unlocked.
Command successful.

初始化文件系统 : 
[root@db-172-16-3-33 ~]# mkfs.ext4 /dev/mapper/lukstest1 

为了能够启动系统时可以自动挂载, 为这个设备添加key文件.
[root@db-172-16-3-33 ~]# cryptsetup luksAddKey /dev/mapper/vgdata01-lv06 /root/dscn1068.jpg
Enter any LUKS passphrase: 输入digoal
Verify passphrase: 输入digoal
key slot 0 unlocked.
Command successful.

在添加2个钥匙
[root@db-172-16-3-33 ~]# cryptsetup luksAddKey /dev/mapper/vgdata01-lv06 /root/pwdfile 
Enter any LUKS passphrase: 输入digoal
Verify passphrase: 输入digoal
key slot 0 unlocked.
Command successful.
[root@db-172-16-3-33 ~]# cryptsetup luksAddKey /dev/mapper/vgdata01-lv06 /root/ssl.dmp
Enter any LUKS passphrase: 输入digoal
Verify passphrase: 输入digoal
key slot 0 unlocked.
Command successful.

最多可以添加8个密钥.
查看luks设备信息 :
[root@db-172-16-3-33 ~]# cryptsetup luksDump /dev/mapper/vgdata01-lv06
LUKS header information for /dev/mapper/vgdata01-lv06

Version:        1
Cipher name:    aes
Cipher mode:    cbc-essiv:sha256
Hash spec:      sha1
Payload offset: 1032
MK bits:        128
MK digest:      eb b0 d4 31 d1 60 99 2c af db cf 72 b0 21 46 ca 7b f5 07 3a 
MK salt:        8c b2 3b 09 ae fd a9 ef 10 87 d7 e2 e8 61 68 44 
                7d 61 bc b0 17 19 e4 a5 01 f4 0a 4d ab 2e 7d 40 
MK iterations:  10
UUID:           ed3427a4-8cc5-4b45-907e-a0b81c562f69

Key Slot 0: ENABLED
        Iterations:             587148
        Salt:                   4e 90 49 da 53 60 dc 39 c2 26 93 83 7a 93 c8 b6 
                                35 b6 28 62 76 a5 c7 1c f6 dc 96 5f f3 bb 89 d7 
        Key material offset:    8
        AF stripes:             4000
Key Slot 1: ENABLED
        Iterations:             589389
        Salt:                   ce e2 9f 5f 27 e6 da 94 f8 9b 6d 91 ab b9 d8 7b 
                                11 c9 99 57 fc 43 00 42 3f 17 b5 be 95 11 15 d7 
        Key material offset:    136
        AF stripes:             4000
Key Slot 2: ENABLED
        Iterations:             582465
        Salt:                   b2 8d 38 84 0c 72 21 56 f4 38 a0 64 f1 be a6 8e 
                                e2 88 f0 dd 4c fd 4f 01 c3 c9 53 c8 e3 4a 0f 7c 
        Key material offset:    264
        AF stripes:             4000
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

自动挂载 : 
vi /etc/fstab

/dev/mapper/lukstest1  /mnt  ext4  defaults,noatime,nodiratime 0 0

vi /etc/crypttab, 任意一把钥匙都可以
lukstest1 /dev/mapper/vgdata01-lv06 /root/pwdfile cipher=aes-cbc-essiv:sha256

如果你觉得现在系统可能被入侵了, 可以赶紧在系统中锁定这个加密设备 : 
[root@db-172-16-3-33 ~]# umount /mnt
[root@db-172-16-3-33 ~]# cryptsetup luksClose lukstest1

锁定后, 要再挂载的话, 需要重新OPEN这个设备.
[root@db-172-16-3-33 ~]# mount -a
mount: special device /dev/mapper/lukstest1 does not exist
[root@db-172-16-3-33 ~]# cryptsetup luksOpen /dev/mapper/vgdata01-lv06 lukstest1
Enter LUKS passphrase for /dev/mapper/vgdata01-lv06: 这里就要输入passphrase了.
key slot 0 unlocked.
Command successful.
[root@db-172-16-3-33 ~]# mount -a

简单的测试一下加密前后的性能 : 
加密前 :
pg93@db-172-16-3-33-> pg_test_fsync 
5 seconds per test
O_DIRECT supported on this platform for open_datasync and open_sync.

Compare file sync methods using one 16kB write:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                                 n/a
        fdatasync                        3078.659 ops/sec     325 usecs/op
        fsync                             122.920 ops/sec    8135 usecs/op
        fsync_writethrough                            n/a
        open_sync                        3159.457 ops/sec     317 usecs/op

Compare file sync methods using two 16kB writes:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                                 n/a
        fdatasync                        2183.032 ops/sec     458 usecs/op
        fsync                             119.158 ops/sec    8392 usecs/op
        fsync_writethrough                            n/a
        open_sync                          82.511 ops/sec   12120 usecs/op

Compare open_sync with different write sizes:
(This is designed to compare the cost of writing 16kB
in different write open_sync sizes.)
         1 * 16kB open_sync write        3159.608 ops/sec     316 usecs/op
         2 *  8kB open_sync writes         82.715 ops/sec   12090 usecs/op
         4 *  4kB open_sync writes         75.105 ops/sec   13315 usecs/op
         8 *  2kB open_sync writes         76.498 ops/sec   13072 usecs/op
        16 *  1kB open_sync writes         66.042 ops/sec   15142 usecs/op

Test if fsync on non-write file descriptor is honored:
(If the times are similar, fsync() can sync data written
on a different descriptor.)
        write, fsync, close               130.770 ops/sec    7647 usecs/op
        write, close, fsync               134.353 ops/sec    7443 usecs/op

Non-Sync'ed 16kB writes:
        write                           162297.029 ops/sec       6 usecs/op

加密后 : 
pg93@db-172-16-3-33-> pg_test_fsync 
5 seconds per test
O_DIRECT supported on this platform for open_datasync and open_sync.

Compare file sync methods using one 16kB write:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                                 n/a
        fdatasync                        1659.743 ops/sec     603 usecs/op
        fsync                              40.495 ops/sec   24694 usecs/op
        fsync_writethrough                            n/a
        open_sync                        1986.934 ops/sec     503 usecs/op

Compare file sync methods using two 16kB writes:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                                 n/a
        fdatasync                         810.707 ops/sec    1233 usecs/op
        fsync                              44.788 ops/sec   22327 usecs/op
        fsync_writethrough                            n/a
        open_sync                          82.907 ops/sec   12062 usecs/op

Compare open_sync with different write sizes:
(This is designed to compare the cost of writing 16kB
in different write open_sync sizes.)
         1 * 16kB open_sync write        1892.044 ops/sec     529 usecs/op
         2 *  8kB open_sync writes         85.417 ops/sec   11707 usecs/op
         4 *  4kB open_sync writes         57.790 ops/sec   17304 usecs/op
         8 *  2kB open_sync writes         66.311 ops/sec   15080 usecs/op
        16 *  1kB open_sync writes         66.290 ops/sec   15085 usecs/op

Test if fsync on non-write file descriptor is honored:
(If the times are similar, fsync() can sync data written
on a different descriptor.)
        write, fsync, close                43.325 ops/sec   23082 usecs/op
        write, close, fsync                40.256 ops/sec   24841 usecs/op

Non-Sync'ed 16kB writes:
        write                           162096.790 ops/sec       6 usecs/op

从测试结果来看, 性能下降比较厉害.

[参考]
2. man cryptsetup
    man crypttab
目录
相关文章
|
Docker 容器
Docker错误:inotify_add_watch(7, /dev/dm-4, 10) failed: No such file or directory
Docker错误:inotify_add_watch(7, /dev/dm-4, 10) failed: No such file or directory
246 1
|
网络协议
VFS: Cannot open root device "nfs" or unknown-block(0,255)错误解决
VFS: Cannot open root device "nfs" or unknown-block(0,255)错误解决
522 0
FAT-fs (mmcblk0p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.
/******************************************************************************** * FAT-fs (mmcblk0p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck. * 说明: * 系统更新的时候遇到这个错误,记录一下处理步骤,其原因是我自己把其umount了 * 导致的问题。
6379 0
|
Linux 虚拟化
【Centos】 kernel panic-not syncing:VFS:Unable to mount root fs on unknown block
背景: VMware虚拟机下 原因: 在命令执行(update)途中,强制中断并直接运行poweroff命令关机。再次开机出现如图所示故障指示: 根据提示信息分析,可能因为执行更新命令未完成导致系统内核信息混乱。
3977 0
|
关系型数据库 数据库 开发工具