Qemu镜像安全加密测试
文章目录
- 简介
- 1.已经过时的qemu自带的加密方式介绍
- 1.1.创建secret uuid的xml
- 1.2.产生uuid
- 1.3.给secret赋值
- 1.4.创建一个存储池
- 1.5.在存储池中创建一个镜像
- 1.6.在虚拟机中使用该镜像
- 2.弃用以上加密方式
- 2.1.原作者Daniel Berrange的观点
- 2.2.Markus Armbruster更深入的操作
- 3. LUKS(Linux Unified Key Setup)加密简介
- 4.Libvirt对镜像进行LUKS加密
- 4.1.需要的文件
- 4.2.步骤
- 4.3.结论
- Reference
简介
本文介绍两种qemu镜像加密方式,一种是已经过时的方式,另外一种是luks方式,作为对比和学习使用。
1.已经过时的qemu自带的加密方式介绍
这种加密方式已经被原作者(Daniel P. Berrange berrange@redhat.com)废除(deprecated),本章节先介绍一下这种方式的基本操作和废除原因123,以避免日后使用使用方式或者研究思路有错误。
1.1.创建secret uuid的xml
# cat demo-secret.xml
<secret ephemeral='no' private='no'><uuid>0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f</uuid><usage type='volume'><volume>/home/VirtualMachines/demo.qcow2</volume></usage>
</secret>
ephemeral是短暂的意思,如果设置为yes,则vm重启之后,加密就会消失,这一般应用于有第三方加密管理的情况下,这里选择no。
privacy是表明是否libvirt可以给用户看到与该uuid关联的secret信息,如果设置为yes,就是writeonly的。
uuid就是一个secret的唯一标识,如果不指定uuid,下一步会随机生成一个。
1.2.产生uuid
# virsh secret-define demo-secret.xmlSecret 1a81f5b2-8403-7b23-c8d6-21ccc2f80d6f created
1.3.给secret赋值
# MYSECRET=`echo "open seseme" | base64`# virsh secret-set-value 0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f $MYSECRETSecret value set
base64是一种编码格式,这样,一个拥有唯一标识符uuid的secret就产生完整了。
1.4.创建一个存储池
#virsh pool-dumpxml VirtualMachines
<pool type='dir'><name>VirtualMachines</name><source></source><target><path>/home/VirtualMachines</path></target>
</pool>
这是一个目录类型的存储池,必须先用mkdir创建/home/VirtualMachines目录
#virsh pool-define xxxx.xml
1.5.在存储池中创建一个镜像
# cat demo-disk.xml
<volume><name>demo.qcow2</name><capacity>5368709120</capacity><target><format type='qcow2'/><encryption format='qcow'><secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/></encryption></target>
</volume>
# virsh vol-create VirtualMachines demo-disk.xml
Vol demo.qcow2 created from demo-disk.xml
可以查看该demo.qcow2的信息
# file demo.qcow2
demo.qcow2: QEMU QCOW Image (v2), 5368709120 bytes, AES-encrypted.
这里注意,该’passphrase’ 并没有按照例子设置具体值,也能正常工作。
1.6.在虚拟机中使用该镜像
# cat demo-guest.xml
<domain type='qemu'><name>demo</name><memory>500200</memory><vcpu>4</vcpu><os><type arch='i686' machine='pc'>hvm</type><kernel>/home/vmlinuz-PAE</kernel><initrd>/home/initrd-PAE.img</initrd><boot dev='hd'/></os><devices><emulator>/usr/bin/qemu-kvm</emulator><disk type='file' device='disk'><driver name='qemu' type='qcow2'/><source file='/home/VirtualMachines/demo.qcow2'/><target dev='hda' bus='ide'/><encryption format='qcow'><secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/></encryption></disk><input type='tablet' bus='usb'/><input type='mouse' bus='ps2'/><graphics type='vnc' port='-1' autoport='yes'/></devices>
</domain>
这是一个空硬盘,可以直接用内核文件vmlinuz和initrd做PXE启动。
2.弃用以上加密方式
2.1.原作者Daniel Berrange的观点
A. AES-CBC加密算法本身很脆弱,容易受到选择明文攻击
B. 本实现直接用的1.3小节中的passphrase当作加密密钥,密钥的选择不安全,太短并且缺乏随机性
C. 当加密被入侵之后,没有机制可以修改密钥,镜像安全得不到保证
2.2.Markus Armbruster更深入的操作
首先创建三个文件4
[root@localhost home]# qemu-img create -f raw backing.img 4m
Formatting 'backing.img', fmt=raw size=4194304
[root@localhost home]# qemu-img create -f qcow2 -o encryption,backing_file=backing.img,backing_fmt=raw geheim.qcow2 4m
Formatting 'geheim.qcow2', fmt=qcow2 size=4194304 backing_file=backing.img backing_fmt=raw encryption=on cluster_size=65536 lazy_refcounts=off refcount_bits=16
[root@localhost home]# qemu-img create -f qcow2 -o backing_file=backing.img, backing_fmt=raw normal.qcow2 4m
Formatting 'normal.qcow2', fmt=qcow2 size=4194304 backing_file=backing.img backing_fmt=raw encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
这里qemu-img执行了三次,可以看到,出现了一个backing_file参数,如果“-o”选项中使用了backing_file这个选项来指定其后端镜像文件,那么这个创建的镜像文件仅记录与后端镜像文件的差异部分。后端镜像文件不会被修改,除非在QEMU monitor中使用“commit”命令或者使用“qemu-img commit”命令去手动提交这些改动。这种情况下,size参数不是必须需的,其值默认为后端镜像文件的大小。另外,直接使用“-b backfile”参数也与“-o backing_file=backfile”效果相同。
剩下的操作,现在的QEMU版本已经不支持,会提示报错
[root@localhost home]# qemu-system-x86_64 -nodefaults -display none -monitor stdio geheim.qcow2
qemu-system-x86_64: -monitor stdio: Use of AES-CBC encrypted qcow2 images is no longer supported in system emulators
剩下的分析可以查看附录[2],当前QEMU版本推荐的硬盘加密方式是LUKS(Linux Unified Key Setup)。
3. LUKS(Linux Unified Key Setup)加密简介
#用vmware添加一块新磁盘,/dev/sdc,然后进行加密
[root@localhost ~]# cryptsetup -v -y -c aes-cbc-plain luksFormat /dev/sdcWARNING!
========
This will overwrite data on /dev/sdc irrevocably.Are you sure? (Type uppercase yes): YES
Enter passphrase:
Verify passphrase:
Command successful.
#映射分区,需要输入密码,之后就不用了
[root@localhost ~]# cryptsetup luksOpen /dev/sdc test_disk //把sdb1映射为test_disk
Enter passphrase for /dev/sdc:
[root@localhost ~]# ll -d /dev/mapper/test_disk
lrwxrwxrwx. 1 root root 7 Oct 19 02:02 /dev/mapper/test_disk -> ../dm-2
#查看映射分区状态
[root@localhost ~]# cryptsetup status /dev/mapper/
cl-root cl-swap control test_disk
[root@localhost ~]# cryptsetup status /dev/mapper/cl-root
[root@localhost ~]# cryptsetup status /dev/mapper/cl-swap
[root@localhost ~]# cryptsetup status /dev/mapper/control
/dev/mapper/control is inactive.
[root@localhost ~]# cryptsetup status /dev/mapper/test_disk
/dev/mapper/test_disk is active.type: LUKS1cipher: aes-cbc-plainkeysize: 256 bitsdevice: /dev/sdcoffset: 4096 sectorssize: 10481664 sectorsmode: read/write
可以看到,未加密的映射分区是没有加密信息的,其中有个/dev/mapper/control不知道是做什么的,以后再研究。可以看到/dev/mapper/test_disk分区的加密信息,使用的aes-cbc-plain加密算法,用qemu-img命令生成的加密镜像,从qemu报错可以看出,现在的qemu版本不支持这种aes-cbc算法,目前无法确定用LUKS生成的加密镜像如果用这种算法,qemu会不会报错,猜测是会报错的,后面再进行验证。
#挂载分区
[root@localhost home]# mkfs.xfs /dev/mapper/test_disk
meta-data=/dev/mapper/test_disk isize=512 agcount=4, agsize=327552 blks= sectsz=512 attr=2, projid32bit=1= crc=1 finobt=0, sparse=0
data = bsize=4096 blocks=1310208, imaxpct=25= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal log bsize=4096 blocks=2560, version=2= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[root@localhost home]# mount /dev/sdc /home/crypto_test/
mount: unknown filesystem type 'crypto_LUKS' //不能直接挂载,要挂载在映射设备上
[root@localhost home]# mount /dev/mapper/test_disk /home/crypto_test/
[root@localhost home]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/test_disk 5.0G 33M 5.0G 1% /home/crypto_test
挂载成功。
#关闭映射,先卸载后关闭
[root@localhost home]# umount /home/crypto_test/
[root@localhost home]# cryptsetup status /dev/mapper/test_disk
/dev/mapper/test_disk is active.type: LUKS1cipher: aes-cbc-plainkeysize: 256 bitsdevice: /dev/sdcoffset: 4096 sectorssize: 10481664 sectorsmode: read/write
[root@localhost home]# cryptsetup luksClose test_disk
[root@localhost home]# cryptsetup status /dev/mapper/test_disk
/dev/mapper/test_disk is inactive.
4.Libvirt对镜像进行LUKS加密
4.1.需要的文件
参考第1节,步骤和需要的文件几乎完全一样,只是加密方式不同。本节只标出不同的地方,其他步骤参考第1节5。
需要的文件为:demo-disk.xml demo-pool.xml demo-secret.xml
#demo-secret.xml
<secret ephemeral='no' private='yes'><uuid>0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f</uuid><usage type='volume'><volume>/home/crypto-test/twofish.luks</volume></usage>
</secret>#demo-pool.xml
<pool type='dir'><name>test-pool</name><source></source><target><path>/home/crypto-test</path></target>
</pool>#demo-disk.xml
<volume><name>twofish.luks</name><capacity>3111111111</capacity><target><format type='raw'/><encryption format='luks'><secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/><cipher name='twofish' size='256' mode='cbc' hash='sha256'/><ivgen name='plain64' hash='sha256'/></encryption></target>
</volume>
差异在于
<format type='raw'/>和<encryption format='luks'>
4.2.步骤
#查看镜像文件格式
[root@localhost crypto-test]# file twofish.luks
twofish.luks: LUKS encrypted file, ver 1 [twofish, cbc-plain64:sha256, sha256] UUID: c46eef30-b6c2-473a-959d-84d941b0d893
#虚拟机disk配置
<disk type='file' device='disk'><driver name='qemu' type='raw'/><source file='/home/crypto-test/twofish.luks'/><backingStore/><target dev='hda' bus='ide'/><encryption format='luks'><secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/></encryption><alias name='ide0-0-0'/><address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<disk type='file' device='cdrom'><driver name='qemu' type='raw'/><source file='/home/ubuntu-14.04.1-server-amd64-20170531.iso'/><backingStore/><target dev='hdc' bus='ide'/><readonly/><alias name='ide0-1-0'/><address type='drive' controller='0' bus='1' target='0' unit='0'/>
</disk>
在使用加密镜像的时候,由于实验中建立的是一个空镜像,里面没有操作系统,因此要带上一个cdrom,系统安装好之后,测试把<encryption format='luks'>
删除,会找不到硬盘,加密生效。
故意将passphrase的最后一个字母从f改成e,再启动虚拟机
<encryption format='luks'><secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6e'/>
</encryption>
[root@localhost home]# virsh start vm_test_2
error: Failed to start domain vm_test_2
error: Secret not found: no secret with matching uuid '0a81f5b2-8403-7b23-c8d6-21ccc2f80d6e'
4.3.结论
使用了LUKS之后,libvirt配置的passphrase不再用来当作生成加密密钥,仅仅用来解锁加密密钥,并且可以随时更改[3]。并且在demo-disk.xml的encryption标签里面,还可以配置成其他的选项来选择加密算法和密钥生成方式。
Reference
Using QCow2 disk encryption with libvirt in Fedora 12(deprecated) ↩︎
[Qemu-devel] [PULL 03/17] block: Deprecate QCOW/QCOW2 encryption ↩︎
QEMU QCow2 built-in encryption: just say no. Deprecated now, to be deleted soon ↩︎
KVM虚拟机磁盘镜像文件管理命令qemu-img介绍及简单使用总结 ↩︎
Secret XML format ↩︎
相关文章:

Qemu镜像安全加密测试
文章目录 简介1.已经过时的qemu自带的加密方式介绍1.1.创建secret uuid的xml1.2.产生uuid1.3.给secret赋值1.4.创建一个存储池1.5.在存储池中创建一个镜像1.6.在虚拟机中使用该镜像 2.弃用以上加密方式2.1.原作者Daniel Berrange的观点2.2.Markus Armbruster更深入的操作 3. LU…...

Ubuntu 18.04 LTS中cmake-gui编译opencv-3.4.16并供Qt Creator调用
一、安装opencv 1.下载opencv-3.4.16的源码并解压 2.在解压后的文件夹内新建文件夹build以及opencv_install 3.启动cmake-gui并设置 sudo cmake-gui(1)设置界面中source及build路径 (2)点击configure,选择第一个def…...
SpringBoot (2) yaml,整合项目
目录 1 YAML配置文件 1.1 书写规则 1.2 代码示例 1.3 用yaml进行复杂数据绑定 2 整合日志 2.1 日志配置 3 整合web 3.1 默认配置 3.2 web应用开发方式 3.2.1 全自动 3.2.2 全手动 3.2.3 手自一体(推荐) 4 整合mybatis 4.1 导包 4.2 application.yaml 4.3 dao接…...

django建站过程(2)创建第一个应用程序页面
创建第一个应用程序页面 设置第一个页面【settings.py,urls.py,views.py】settings.pyurls.pyviews.py django是由一系列应用程序组成,协同工作,让项目成为一个整体。前面已创建了一个应用程序baseapp,使用的命令 python manage.py startapp baseapps这…...

竞赛 深度学习人体语义分割在弹幕防遮挡上的实现 - python
文章目录 1 前言1 课题背景2 技术原理和方法2.1基本原理2.2 技术选型和方法 3 实例分割4 实现效果5 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习人体语义分割在弹幕防遮挡上的应用 该项目较为新颖,适合作为竞…...

网络编程开发及实战(下)
一、IO模型 一、基本概念 (一)I/O基本概念 1、基本概念 1)一个完整I/O分为两个阶段: 用户进程空间->内核空间 内核空间->设备空间(磁盘、网卡) 2)内存I/O(无名管道&…...

(H5轮播)vue一个轮播里显示多个内容/一屏展示两个半内容
效果图 : html: <div class"content"><van-swipeclass"my-swipe com-long-swipe-indicator":autoplay"2500"indicator-color"#00C4FF"><van-swipe-itemclass"flex-row-wrap"v-for"(items, index) in M…...

【Proteus仿真】【Arduino单片机】蜂鸣器
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器,使用蜂鸣器等。 主要功能: 系统运行后,蜂鸣器播放音乐。 二、软件设计 /* 作者:嗨小易(QQ&#x…...
seatunnel web ui 构建时报错
报错内容如下 Failed to execute goal com.diffplug.spotless:spotless-maven-plugin:2.29.0:check (default) on project seatunnel-web: The following files had format violations:Failed to execute goal com.diffplug.spotless:spotless-maven-plugin:2.29.0:check (defa…...
Js使用ffmpeg在视频中添加png或gif
Js使用ffmpeg在视频中添加png或gif ffmpeg 使用场景是需要在web端对视频进行编辑 添加图片和gif。 注意: 以下所有的使用案例均基于vue3 setup。 同时由于ffmpeg版本不同会导致使用的api不同,使用案例前需要注意ffmpeg版本问题。 如果使用的是0.12需要使用新的…...
多线程 Leetcode 打印零与奇偶数
现有函数 printNumber 可以用一个整数参数调用,并输出该整数到控制台。 例如,调用 printNumber(7) 将会输出 7 到控制台。 给你类 ZeroEvenOdd 的一个实例,该类中有三个函数:zero、even 和 odd 。ZeroEvenOdd 的相同实例将会传递…...
杭电oj--数列有序
有n(n<100)个整数,已经按照从小到大顺序排列好,现在另外给一个整数x,请将该数插入到序列中,并使新的序列仍然有序。 输入数据包含多个测试实例,每组数据由两行组成,第一行是n和m,第二行是已…...

PHPEXCEL解决行数超过65536不显示问题
起因自然是导出数据到excel文件时,数据缺少现象。 百度讲解是将xls文件另存为xlsx文件。 除了这里的原因,还有一点是phpExcel存在两个写入类PHPExcel_Writer_Excel2007和PHPExcel_Writer_Excel5,而只有PHPExcel_Writer_Excel2007支持超过65…...

新媒体时代如何做好新型的网络口碑营销?
从人类开始交换商品的时代开始,口碑营销就已经存在,是靠口耳传播的营销方式。小马识途认为进入当今移动互联网时代,口碑营销又有了新的发展,网络口碑营销推广开始普及。营销人员将传统口碑营销与移动互联网营销相结合,…...
MySQL中InnoDB插入缓冲区(Insert Buffer)
一、插入缓冲区的基本原理 插入缓冲区(Insert Buffer,也称作 Change Buffer),是InnoDB存储引擎的一种内部机制,它允许系统将对非聚集索引页的写操作(例如插入、删除和更新)暂时缓存在内存中&am…...

VUE前端判断是电脑端还是移动端
背景需求 ruoyi框架,前后端分离。现在要在用户访问的时候根据不同的设备跳转到不同的登录页面。 教程 router/index.js 修改src/router/index.js,在这里增加自己的要跳转的页面 permission.js 在白名单中添加自己的登录页面 增加以下识别的代码 le…...

OpenGL —— 2.8、漫游之摄像机飞行移动(附源码,glfw+glad)
源码效果 C源码 纹理图片 需下载stb_image.h这个解码图片的库,该库只有一个头文件。 具体代码: vertexShader.glsl #version 330 corelayout(location 0) in vec3 aPos; layout(location 1) in vec2 aUV;out vec2 outUV;uniform mat4 _modelMatrix; …...
AM@麦克劳林公式逼近以及误差分析
abstract 麦克劳林公式及其近似表示的应用误差估计和分析 Lagrange型泰勒公式的估计误差 由Lagrange型余项泰勒公式可知,多项式 p n ( x ) p_n(x) pn(x)近似表达函数 f ( x ) f(x) f(x)时,其误差为 ∣ R n ( x ) ∣ |R_{n}(x)| ∣Rn(x)∣ R n ( x ) R_{n}(x) Rn(x) f …...
gitlab 离线安装问题解决:NOKEY,signature check fail
1,rpm安装gitlab问题 test1:/opt # rpm -ivh gitlab-ce-16.0.3-ce.0.el7.x86_64.rpm --force warning: gitlab-ce-16.0.3-ce.0.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID f27eab47: NOKEY error: [upel]: gitlab-ce NOKEY error: [upel]: gitlab-ce …...

uniapp使用uQRCode绘制二维码,下载到本地,调起微信扫一扫二维码核销
1.效果 2.在utils文件夹下创建uqrcode.js // uqrcode.js //--------------------------------------------------------------------- // github https://github.com/Sansnn/uQRCode //---------------------------------------------------------------------let uQRCode {…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...