sVirt概述
前面已经对seLInux的基本原理做了分析,seLinux主要就是基于主体和客体的安全上下文,进行访问决策。那么安全上下文是不是又可以理解为一个标签呢?
基于以上seLInux的特性,便可以考虑吧seLinux这种基于标签的思想应用到保障Hypervisor的安全上,这里主要是解决两个问题:
- 恶意虚拟机攻击Hypervisor
- 恶意虚拟机攻击其他虚拟机
准确来说就是在Libvirt中添加了一个安全架构插件,这样Libvirt会自动给镜像文件配置标签并且保证虚拟机以正确的标签启动。这些标签是无法更改的。这样管理员就不需要去记复杂的标签,提高了易用性。默认情况下,在F11中的虚拟机是svirt_t,镜像文件时svirt_image_t。
而seLinux的策略仅仅允许sVIrt_t的进程读写sVIrt_image_t的文件和设备。
这种情况下虚拟机便不能肆意访问宿主机,也就解决了第一个问题,但是这样并不能阻止虚拟机间的恶意访问,即第二个问题。
基于此,开发者便考虑我们要保证虚拟机和镜像的标签一致,同时不能让VM1访问具有相同标签的VM2的镜像文件。
这样便出现了MCS(Multiple Category Security)
这在red hat 5上默认提供支持,类似于MLS,MCS在seLInux的安全上下文中添加了第四个字段,其实之前我们也介绍过MCS和MLS的区别,MCS只不过是只采用一个敏感度,而MLS又多个敏感度,二者的侧重点是不同的,MCS重在分类,而MLS貌似重在等级。
这样MCS便可以用于分离以同一seLinux类型运行的虚拟机,Libvirt在加入支持后,同样也可以自动为虚拟机和其镜像文件分配随机MCS标签,同时保证标签的唯一性。
例如Libvirt为两台虚拟机分配的标签:
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/9551a7cc-36d0-4d51-a284-552ad9b5d054.png)
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923205729887-1006968835.png)
这样seLinux阻止了VM1( system_u:system_r:svirt_t:s0:c0,c10) 访问VM2的镜像文件 (system_u:object_r:svirt_image_t:s0:c101,c230) ,也就阻止了VM间的相互攻击。
如下是Livvirt分配的标签:
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923205825762-1704049519.png)
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/b2a428e8-ae71-41a8-903a-ff123e694eb7.png)
同时对sVirt也加入了静态标签的特性,用户可以为虚拟机选择特定的标签。这样虚拟机便一直以这个标签启动,但是设置静态标签的用户需要为镜像文件设置相应的标签。而Libvirt也永远不会去修改静态配置的标签,这样sVIrt便可以运行于MLS的环境,管理员就可以运行多个不同安全级别的虚拟机。
二、sVirt在seLInux中的使用
sVIrt其实最主要的还是给虚拟机打标签的过程,而目前主要有静态标签和动态标签两种方式
动态分配:
默认状态下,虚拟机运行在自己的被动态配置的域和image文件下,因此和其他的VM隔离开来(每个虚拟机会被随机分配MCS标签用于限制虚拟机活动在自己的域中),这种模式的实现方式如下:
a) 一个对进程的初始上下文是从/etc/selinux/<SELINUXTYPE>/contexts/virtual_domain_context 文件获得,意味着开启虚拟机后,代表虚拟机的qemu进程的安全上下文就是从这个文件中获取的。
b)一个对image镜像文件的安全上下文时从/etc/selinux/<SELINUXTYPE>/contexts/virtual_image_context 文件获得的,那么刚才不是说镜像文件在建立时已经有了安全上下文么??这里我也不太清楚,在虚拟机启动后,镜像文件的类型会被重新标记,至于原因,后续有待考究。
c)当一个镜像文件被用于启动一个虚拟机,selinux系统就生成一个随机的MCS level 并添加到相应qemu进程的安全上下文和image镜像文件的安全上下文。进程和image文件随后被libseLinux API 分别调用 setfilecon 和setexeccon来实现转化到相应的安全上下文(可以参考libvirt源代码中的security_selinux.c文件)。
下面的例子显示了两个运行的VM的安全上下文:
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/6efe744f-ce83-4156-bdbe-f65eaa8ad809.png)
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923205858543-1814871772.png)
上面是Vm运行起来后,虚拟机进程和image镜像文件的安全上下文。
用命令查看VM运行状态和关机状态的相关信息:
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/3449feeb-752c-40b1-bb19-5e90d8a492d5.png)
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/42637489-d510-4a3d-b0a3-1607d33a74a7.png)
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923205916809-1519097712.png)
那么观察上面的结果大致可以得到下面结论:
1、在虚拟机启动之前,镜像文件的类型是virt_image_t,而在虚拟机启动之后,镜像文件的类型是svirt_image_t.
2、在虚拟机启动之前是没有配置MCS标签的
3、虚拟机启动之后进程和镜像文件的MCS标签存在一一对应的关系,故因此保证独立性。
静态分配:
动态分配的方式很简单,只要系统安装了selinux模块,并设置seLInux的相关配置文件,建议设置seLinux-Type = targeted,此模式下会默认对网络和虚拟机设置访问控制,假如设置mls的话要考虑的事情太多,系统很有可能起不来(前车之鉴)。
那么静态分配的话就是手动给某个虚拟机分配标签,一般在用户层的虚拟机管理工具都会提供这个功能,以virt-manager为例:
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923205956996-74459448.png)
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/dbe8562a-dbbf-4b96-908b-ca3c614b4a1b.jpg)
这样配置后,在虚拟机对应的配置文件中会自动添加对标签:
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923210016168-1168886969.png)
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/c85782ce-7785-46c9-a35f-27bc40d9a750.png)
启动虚拟机会以所配置的安全上下文启动,但是注意,因为前面提到过虚拟机运行起来后,镜像文件的安全上下文会被重新标记,而在静态方式下,镜像文件的安全上下文并不自动更改,那那么假如我们不手动修改镜像文件的安全上下文,虚拟机就会因为权限不足而无法启动。
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923210038434-34734517.png)
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/1668d372-91c1-45bd-90cc-16a783f479bc.jpg)
那么出现这样情况也是意料之中,我们可以通过添加allow规则或者手动修改镜像文件的类型来解决。目前还没有掌握添加allow规则的方式,所以只能通过chcon命令修改镜像文件的类型。
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923210058152-776221237.png)
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/485770c7-7fe8-40a9-8f56-42b831015a41.png)
这样设置便可以启动系统,但是为了保证镜像文件的安全性,还要把镜像文件的安全上下文设置和VM进程一样的MCS标签。
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/c1ade5da-9232-41ec-bb0a-3c107ae99280.png)
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923210111137-1755731640.png)
这样VM便可以正常启动了。
然而当我么设置静态标签的域类型为unconfined_t时,即使不修改image镜像文件的安全上下文也可以正常启动,因为unconfined类型具有所有的访问权限。
所以我们再看下两个虚拟机的进程和镜像文件的安全上下文:
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/2182e87e-6d7b-4a17-9fc9-01dab4c4777e.png)
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923210126043-758232208.png)
然后查看系统运行和关闭状态,安全上下文的区别:
![](file:///C:/Users/chen/Documents/My%20Knowledge/temp/0479ca5a-2c11-488a-a558-3928311b32b1_4_files/4bf1c274-674d-476d-aa01-7c160d0329fc.png)
![](https://images2015.cnblogs.com/blog/758933/201609/758933-20160923210139402-1828942022.png)
注意:并不是所有的virt-manager版本都有静态标签设置的项,在centos下的virt-manager就没有这一项,那么我们可以通过直接修改xml文件的方式给虚拟机指定标签,但是静态标签的实际意义不大,至少我目前没有想到什么需求必须要使用静态标签,毕竟svirt的出现的目的就是要保证虚拟机之间的隔离性,没有必要非要指定一个静态标签。