如果当初冠希哥有用dm-crypt硬盘进行加密意识的话,广大人民群众无疑要少了很多的乐趣:)最近在ChinaUnix论坛上,一个自称买了我书的读者向网友求助,如何用dm-crypt对ramdisk中的数据进行加解密,当然他的需求不仅仅这么简单。说实话,关于dm-crypt这东西我还是第一次听说,虽然并没有为读者解决现实问题的义务,不过好在磁盘数据加密这种事情还不算太枯燥。我先google了一把,通过cryptsetup这个用户空间的工具却也莫名其妙稀里糊涂地完成了对ramdisk的加密。
接下来我大概看了一下dm-crypt在内核中的源码,初步感觉这个东西有点类似VPN的某种实现,dm-crypt应该是介于Linux块子系统和实际物理块设备驱动之间的一个东西,通过拦截发送到实际物理设备驱动程序的带着bio参数的读写请求,利用内核所提供的crypto API对数据进行加密,然后写回到实际的块设备中。按照dm-crypt的官方文档的说法,它接管一个虚拟的块层,应该就对应/dev/mapper目录下所生成的虚拟设备了。
我实验用的系统是ubuntu 11.10, 3.1.6 x86_64的内核,按照网上找来的文档,要利用dm-crypt完成对块设备数据的加解密,系统首先必须得加载这个内核模块,我的系统启动时已经自动加载了该模块,而且/dev/mapper目录都是现成的,但是cryptsetup这个工具却需要自己手动去安装,apt-get install一下就可以了。ramdisk来自于我早先的帖子“通过ramdisk内核模块研究Linux文件系统”,所以在insmod ramhd_mkreq.ko之后,系统里有了两个ramdisk设备/dev/ramhda和/dev/ramhdb。
首先通过cryptsetup --verbose --cipher "aes" --key-size 256 --verify-passphrase luksFormat /dev/ramhda命令将ramhda盘给初始化成LUKS格式(LUKS: Linux Unified Key Setup),估计是出于后续加解密的需要,该命令需要输入密码两次(我估摸着这条命令可能会把输入的密码以元数据的方式写到ramdisk的partition header中),命令输出截屏如下(点击放大):
![](https://i-blog.csdnimg.cn/blog_migrate/1b0fcfe18083efdd1d275c095bce35dd.png)
这步仅是某种形式的初始化,dm-crypt还没有介入,所以接下来要把ramhda给挂到/dev/mapper目录下,这样Linux内核中块子系统与ramhda的数据交互才会经由dm-crypt中转,后者才有可能通过内核提供的crypto API对数据进行加解密动作。
下面应该是dm-crypt出手了,否则前面那步就白做了(另外我忘了说一点,前面那一步可能会破坏磁盘中的数据,所以打算照做的同学最好仔细检查一下你的U盘,看看里面是不是有什么宝贝),仍然是通过cryptsetup这个工具,命令输出截屏如下(点击放大):
![](https://i-blog.csdnimg.cn/blog_migrate/c84d0d9abe6c9d301c27a612519f65db.png)
cryptsetup luksOpen命令需要输入前面第一步中的密码,完了之后在/dev/mapper下会生成一个符号链接virtualdisk,指向/dev/dm-0,后者在我的系统中是一个主次设备号分别是253,0的一个块设备,应该就是所谓的虚拟块设备了,作为块子系统和ramhda之间数据中转层,所以为了让dm-crypt为我们做磁盘数据加解密的任务,接下来所有对/dev/ramhda块设备的操作都应该通过/dev/dm-0进行。理论上这步完成后,对/dev/mapper/virtualdisk的读写操作都会被透明地加密和解密。因为现在ramhda上还没有文件系统,所以可以通过mkfs工具在上面做个文件系统出来,如果mkfs的命令通过/dev/mapper/virtualdisk进行,那么往ramhda设备上写的文件系统数据也会被加密,这样一旦我们将来把ramhda从/dev/mapper/virtualdisk中断开,那么ramhda上的数据将不能被块子系统正确解读,因而其上的文件系统也不会被系统所识别,等下我们可以验证一下。在/dev/mapper/virtual设备上使用mkfs.ext3过程此处忽略掉了。。。
现在可以把/dev/mapper/virtualdisk挂载到一个挂载点,比如/mnt:"mount /dev/mapper/virtualdisk /mnt", 之后我们就可以利用ext3文件系统接口在上面进行文件操作,比如新增文件删除目录等等,所有这些发往ramdhda上的数据都是经过加密了的,换句话说,以后若想读取ramhda中的数据,必须得经过/dev/mapper这一中间层,否则除非有特殊手法,ramhda中的数据将不会被Linux的文件系统所识别,所以现在可以放心地把冠希哥的作品放到/mnt目录下了。
作为某种验证的方法,我们用以下的命令将ramhda从/dev/mapper中摘除:
root@build-server#umount /mnt
root@build-server#cryptsetup luksClose virtualdisk
上述命令执行后,/dev/mapper中的virtualdisk符号链接就消失掉了,现在ramhda将直接面对Linux内核中的块子系统,不妨将其mount到/mnt上面看看有什么结果(预期的结果是,mount命令应该显示ramhda上没有能被识别的文件系统之类的错误),下面是命令输出的截屏:
![](https://i-blog.csdnimg.cn/blog_migrate/fc585a1cb9f5dda37a9d0b327162a2fc.png)
显示的错误信息是:unknown filesystem type 'crypto_LUKS',这符合我们的预期:ramhda中的数据是经过加密的,自然无法被块子系统所识别。如果想读取其中的数据,必须得通过cryptsetup luksOpen来为ramhda重新生成一个中间层,此时需要输入第一步中的口令。
最后,CU上那位网友的需求是,除了对ramdisk中的数据进行加密外,他希望“在ramdisk中创建文件后并写入数据自动形成密文。只有指定用户方能查看该文件的明文,其他用户只能看到密文”,通过上面的分析与推测,结论是:ramdisk中通过dm-crypt创建文件会自动生成密文,这是毫无疑问的,但是对应的明文是不存在的。所以他的需求可以进一步转变成,指定用户通过正确的口令由dm-crypt中间层负责解密,让用户看到明文,其他用户直接去读ramdisk看到的自然是密文(实际的情况极可能是因为没有文件系统的支持,其他用户通过/dev/mapper对ramdisk的访问将被拒绝:No key available with this passphrase.)。看来他应该考虑的是文件层面的加密方法,也就是只对单个文件内容进行加密,而不是整个磁盘上的数据。
接下来我大概看了一下dm-crypt在内核中的源码,初步感觉这个东西有点类似VPN的某种实现,dm-crypt应该是介于Linux块子系统和实际物理块设备驱动之间的一个东西,通过拦截发送到实际物理设备驱动程序的带着bio参数的读写请求,利用内核所提供的crypto API对数据进行加密,然后写回到实际的块设备中。按照dm-crypt的官方文档的说法,它接管一个虚拟的块层,应该就对应/dev/mapper目录下所生成的虚拟设备了。
我实验用的系统是ubuntu 11.10, 3.1.6 x86_64的内核,按照网上找来的文档,要利用dm-crypt完成对块设备数据的加解密,系统首先必须得加载这个内核模块,我的系统启动时已经自动加载了该模块,而且/dev/mapper目录都是现成的,但是cryptsetup这个工具却需要自己手动去安装,apt-get install一下就可以了。ramdisk来自于我早先的帖子“通过ramdisk内核模块研究Linux文件系统”,所以在insmod ramhd_mkreq.ko之后,系统里有了两个ramdisk设备/dev/ramhda和/dev/ramhdb。
首先通过cryptsetup --verbose --cipher "aes" --key-size 256 --verify-passphrase luksFormat /dev/ramhda命令将ramhda盘给初始化成LUKS格式(LUKS: Linux Unified Key Setup),估计是出于后续加解密的需要,该命令需要输入密码两次(我估摸着这条命令可能会把输入的密码以元数据的方式写到ramdisk的partition header中),命令输出截屏如下(点击放大):
![](https://i-blog.csdnimg.cn/blog_migrate/1b0fcfe18083efdd1d275c095bce35dd.png)
这步仅是某种形式的初始化,dm-crypt还没有介入,所以接下来要把ramhda给挂到/dev/mapper目录下,这样Linux内核中块子系统与ramhda的数据交互才会经由dm-crypt中转,后者才有可能通过内核提供的crypto API对数据进行加解密动作。
下面应该是dm-crypt出手了,否则前面那步就白做了(另外我忘了说一点,前面那一步可能会破坏磁盘中的数据,所以打算照做的同学最好仔细检查一下你的U盘,看看里面是不是有什么宝贝),仍然是通过cryptsetup这个工具,命令输出截屏如下(点击放大):
![](https://i-blog.csdnimg.cn/blog_migrate/c84d0d9abe6c9d301c27a612519f65db.png)
cryptsetup luksOpen命令需要输入前面第一步中的密码,完了之后在/dev/mapper下会生成一个符号链接virtualdisk,指向/dev/dm-0,后者在我的系统中是一个主次设备号分别是253,0的一个块设备,应该就是所谓的虚拟块设备了,作为块子系统和ramhda之间数据中转层,所以为了让dm-crypt为我们做磁盘数据加解密的任务,接下来所有对/dev/ramhda块设备的操作都应该通过/dev/dm-0进行。理论上这步完成后,对/dev/mapper/virtualdisk的读写操作都会被透明地加密和解密。因为现在ramhda上还没有文件系统,所以可以通过mkfs工具在上面做个文件系统出来,如果mkfs的命令通过/dev/mapper/virtualdisk进行,那么往ramhda设备上写的文件系统数据也会被加密,这样一旦我们将来把ramhda从/dev/mapper/virtualdisk中断开,那么ramhda上的数据将不能被块子系统正确解读,因而其上的文件系统也不会被系统所识别,等下我们可以验证一下。在/dev/mapper/virtual设备上使用mkfs.ext3过程此处忽略掉了。。。
现在可以把/dev/mapper/virtualdisk挂载到一个挂载点,比如/mnt:"mount /dev/mapper/virtualdisk /mnt", 之后我们就可以利用ext3文件系统接口在上面进行文件操作,比如新增文件删除目录等等,所有这些发往ramdhda上的数据都是经过加密了的,换句话说,以后若想读取ramhda中的数据,必须得经过/dev/mapper这一中间层,否则除非有特殊手法,ramhda中的数据将不会被Linux的文件系统所识别,所以现在可以放心地把冠希哥的作品放到/mnt目录下了。
作为某种验证的方法,我们用以下的命令将ramhda从/dev/mapper中摘除:
root@build-server#umount /mnt
root@build-server#cryptsetup luksClose virtualdisk
上述命令执行后,/dev/mapper中的virtualdisk符号链接就消失掉了,现在ramhda将直接面对Linux内核中的块子系统,不妨将其mount到/mnt上面看看有什么结果(预期的结果是,mount命令应该显示ramhda上没有能被识别的文件系统之类的错误),下面是命令输出的截屏:
![](https://i-blog.csdnimg.cn/blog_migrate/fc585a1cb9f5dda37a9d0b327162a2fc.png)
显示的错误信息是:unknown filesystem type 'crypto_LUKS',这符合我们的预期:ramhda中的数据是经过加密的,自然无法被块子系统所识别。如果想读取其中的数据,必须得通过cryptsetup luksOpen来为ramhda重新生成一个中间层,此时需要输入第一步中的口令。
最后,CU上那位网友的需求是,除了对ramdisk中的数据进行加密外,他希望“在ramdisk中创建文件后并写入数据自动形成密文。只有指定用户方能查看该文件的明文,其他用户只能看到密文”,通过上面的分析与推测,结论是:ramdisk中通过dm-crypt创建文件会自动生成密文,这是毫无疑问的,但是对应的明文是不存在的。所以他的需求可以进一步转变成,指定用户通过正确的口令由dm-crypt中间层负责解密,让用户看到明文,其他用户直接去读ramdisk看到的自然是密文(实际的情况极可能是因为没有文件系统的支持,其他用户通过/dev/mapper对ramdisk的访问将被拒绝:No key available with this passphrase.)。看来他应该考虑的是文件层面的加密方法,也就是只对单个文件内容进行加密,而不是整个磁盘上的数据。