Some Study on Virtualization
针对虚拟化技术以及相关课题的调研。
1. 虚拟化技术
虚拟化是云计算的基础。简单的说,虚拟化使得在一台物理的服务器上可以跑多台虚拟机,虚拟机共享物理机的 CPU、内存、IO 硬件资源,但逻辑上虚拟机之间是相互隔离的。 物理机我们一般称为宿主机(Host),宿主机上面的虚拟机称为客户机(Guest)。
虚拟化是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。
虚拟化技术可以扩大硬件的容量,简化软件的重新配置过程。CPU 的虚拟化技术可以单 CPU 模拟多 CPU 并行,允许一个平台同时运行多个操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。
1.1. 虚拟化技术的分类
- 模拟(Emulation):QEMU、Bochs 等;
- 完全虚拟化(Full Virtualization):VMWare Workstation、VirtualBox、KVM 等;
- 半虚拟化(Para-Virutalization):Xen 等;
- 容器级虚拟化:libcontainer 等;
- 库级别虚拟化:Wine 等;
- 程序级虚拟化:JVM 等。
1.2. CPU 虚拟化
- 模拟类型(Emulation);
- 通过软件模拟 Ring0/1/2/3 层,虚拟机的架构与物理平台的架构可以不同,但是性能差。
- 虚拟类型(Virtualization)。
- 完全虚拟化(full-virt);
- 只虚拟出 Ring0 层;
- BT(Binary Translation):将模拟的 CPU 直接翻译成特权指令,限定虚拟结构平台和底层物理架构必须保持一致;
- 优点:不用修改 GuestOS 内核可以直接使用,应用广泛;
- 缺点:在 VMM 捕获特权指令和翻译过程会导致性能的下降。
- HVM(Hardware Assisted Virtualization):采用 5 个指令环,在 Ring0 的底层加了 Ring-1,将 Ring0 的特权指令给了 Ring-1。
- 半虚拟化(para-virt)。
- GuestOS 明确知道自己运行于虚拟技术中,在执行特权指令时直接向 Hypercall 调用。
- 优点:性能相对来说更高,省去了特权指令的翻译过程;
- 缺点:需要对 GuestOS 内核的修改,应用有限制。
- GuestOS 明确知道自己运行于虚拟技术中,在执行特权指令时直接向 Hypercall 调用。
- 完全虚拟化(full-virt);
硬件级物理 CPU 虚拟化技术:
- 英特尔硬件虚拟化技术:Intel-VT;
- AMD 硬件虚拟化技术:AMD-V。
1.3. 内存虚拟化
内存虚拟化是虚拟机实现中的重要部分。在虚拟机中,虚拟出来的 Guest OS 和 Host OS 用的是相同的物理内存,却不能让它们相互影响到。如果 OS 在物理机上运行,只要 OS 提供页表,MMU 会在访存时自动做虚拟地址(Virtual Address,VA)到物理地址(Physical Address,PA)的转化。而在虚拟机上运行时,Guest OS 经过地址转化得到的“物理地址”并不是真实物理内存上的地址(GVA->GPA
),因此还需要使用软件将其转化为真实物理内存地址(HPA)。也就是说 Guest OS 要访问 VA 需要经过 GVA->GPA->HPA
的转化。
- MMU Virtualization:MMU 是 Memory Management Unit 的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权,多用户多进程操作系统;
- Guest OS 完成
GVA->GPA
第一层转化,硬件同时完成GPA->HPA
第二层转化。第二层转化对于 Guest OS 来说是透明的。Guest OS 访问内存时和在物理机运行时是相同的,所以可以实现全虚拟化。这种特性 Intel 和 AMD 都有支持。Intel 称之为 Extended Page Tables(EPT),AMD 称之为 Nested Page Tables(NPT)。其优点是 Hypervisor 节省了工作,缺点是需要硬件支持。
- Guest OS 完成
- TLB Virtualization:TLB 是 Translation Lookaside Buffer 的缩写,中文名是转换后缓存存储器。
- 原生只存储
VA->PA
的对应关系。所以在虚拟内存中的两次转换会导致 TLB 的命中率失效。致使性能降低。所以在硬件内存中添加标识虚拟机标签机制(tagged TLB),它缓存了 Guest 对象和GVA->HPA
的对应关系,需要 CPU 的支持。
- 原生只存储
硬件级内存虚拟化(硬件级物理内存映射到虚拟机):
- 英特尔硬件虚拟化技术 EPT,Extended Page Table;
- AMD 硬件虚拟化技术 NTP,Nested Page Table。
1.4. I/O 虚拟化
- I/O 全虚拟化技术
- 完全使用软件通过 VMM 模拟 I/O 设备(磁盘和网卡等)实现虚拟化,性能很差;
- Guest OS 所能看到就是一组统一的 I/O 设备。VMM 截获 Guest OS 对 I/O 设备的访问请求,然后通过软件模拟真实的硬件。这种方式对 Guest OS 而言非常透明,无需考虑底层硬件的情况。
- I/O 半虚拟化技术(virtio)
- 通过前端(I/O Frontend)和后端(I/O Backend)的模拟实现虚拟化,通常仅适用于硬盘和网卡;
- Guest OS 中的驱动程序为前端,VMM 提供的与 Guest OS 通信的驱动程序为后端。前端驱动将 Guest OS 的请求通过与 VMM 间的特殊通信机制发送给 VMM 的后端驱动,后端驱动在处理完请求后再发送给物理驱动。
- I/O 透传技术(I/O Through)
- 设备透传就是向一个特定客户操作系统提供一种设备隔离,直接给虚拟机分配物理设备,使用设备透传可以获得近乎本机的性能。
VMM 对 I/O 的驱动有三种模式:
- 自主 VMM:由 VMM 自行提供驱动和控制台;
- 混合 VMM:借助于 OS 提供驱动;
- 依赖于外部 OS 实现特权域;
- 自我提供特权域。
- 寄宿式 VMM。
1.5. 网络虚拟化
用软件的方式给每个虚拟机虚拟一块网卡和 MAC 地址,当通信时使用同一块物理网卡,网卡通讯有排队方式,在同一台物理网卡上,排队执行任务。(将物理网卡设为混杂模式;无论是不是发向本机物理网卡的内容都给与接收);此时将物理网卡也虚拟化一个 MAC 地址,把物理网卡当作交换机来使用。
- 桥接(Bridge):把原宿主机上的网卡当交换机;然后虚拟出一个桥来接收发往宿主机的数据包;
- (Isolation):仅 Guest 之间通信;不与外部网络和宿主机通信;
- (Routed):与外部主机通信;依赖于静态路由指定到各 Guest 需经过 pnet0。
- (Host-only):不与外部主机通信。
- NAT:地址转换;在虚拟网卡和物理网卡之间建立一个 NAT 转发服务器;对数据包进行源地址转换。
1.6. 虚拟化实现的方式(Hypervisor 的类型)
- Type-I:Hypervisor 直接运行于硬件(如 Xen 等);
- Type-II:Hypervisor 运行 Host OS 之上(如 VMware Workstation 等)。
1.7. 容器级级虚拟化
- 缺点:相较于主机级虚拟化隔离的不彻底;
- 方案:LXC、libcontainer、runC、OpenVZ;
- Linux 内核运行在物理设备上,在内核上运行多个操作系统(如:CentOS、Ubuntu 等)。因为他们都是基于 Linux 内核来开发的不同操作系统,底层运行的内核是相同的。在每个操作系统上在运行每个应用。在内核上运行一个软件来创建和管理容器,是一个很小的软件,基本不消耗性能;
- 共享内核:由于多个操作系统使用的是同一个内核,当在操作系统上执行关机命令,就会将内核关闭,所以需要将每个操作系统隔离开来,关掉的只是自身容器本身而已。各个操作系统之间的操作互不干扰。
2. KVM
KVM 是(Kernel-based Virtual Machine)的简称,是一个开源的系统虚拟化模块,由以色列 Qumranet 公司研发,后被 RedHat 公司收购。自 Linux 2.6.20 之后集成在 Linux 的各个主要发行版本中。它使用 Linux 自身的调度器进行管理,所以相对于 Xen,其核心源码很少。KVM 的虚拟化需要硬件支持(如 Intel-VT 技术或者 AMD-V 技术),是基于硬件的完全虚拟化。而 Xen 早期则是基于软件模拟的 Para-Virtualization,新版本则是基于硬件支持的完全虚拟化。但 Xen 本身有自己的进程调度器,存储管理模块等,所以代码较为庞大。
- KVM 只支持 x86 平台;
- 依赖于 HVM、Intel-VT、AMD-V。
2.1. 工作原理
KVM 是基于虚拟化扩展(Intel VT 或者 AMD-V)的 X86 硬件的开源的 Linux 原生的全虚拟化解决方案。KVM 中,虚拟机被实现为常规的 Linux 进程,由标准 Linux 调度程序进行调度;虚机的每个虚拟 CPU 被实现为一个常规的 Linux 进程。这使得 KMV 能够使用 Linux 内核的已有功能。
但是,KVM 本身不执行任何硬件模拟,需要客户空间程序通过 /dev/kvm
接口设置一个客户机虚拟服务器的地址空间,向它提供模拟的 I/O,并将它的视频显示映射回宿主的显示屏。目前这个应用程序是 QEMU。
2.2. 核心组件
- 内核模块(
kvm.ko
); - 用户空间工具(QEMU-KVM);
- 交互工具(libvirt)。
2.3. 运行模式
- 内核模式:Guest OS 执行 I/O 类的操作时,或其它的特殊指令操作时的模式,也被称为“Guest-Kernel”模式;
- 用户模式:Host OS 的用户空间,用于代为 Guest OS 发出 I/O 请求;
- 来宾模式:Guest OS 的用户模式,所有的非 I/O 类请求。
2.4. KSM 机制
扫描物理内存,发现多个虚拟机实例有相同的内存空间,合并成为一个共享内存空间,节省内存。
2.5. 工具集
- QEMU
- QEMU-KVM
- QEMU-IMG
- libvirt
- GUI:virt-manager、virt-viewer
- CLI:virsh、virt-install
- 集群工具
- libvirtd
3. Linux 对软件行为检测
3.1. So preload
Linux 提供了一个 so preload 的机制,它允许定义优先加载的动态链接库,方便使用者有选择地载入不同动态链接库中的相同函数。可以通过 so preload 来覆盖 libc.so 中的 execve 等函数来监控进程的创建。
- 优点
- 轻量级,只修改库函数代码,不与内核进行交互;
- 缺点
- 只能影响在 preload 之后创建的进程,这就需要检测 Agent 安装得越早越好,尽量在其他应用进程启动之前就完成安装;
- 无法监控静态链接的程序,目前一些蠕虫木马为了降低对环境的依赖性都是用静态链接,不会加载共享库,这种情况下这种监控方式会失效;
- 容易被攻击者发现并篡改,目前一些蠕虫木马本身也会向
/etc/ld.so.preload
中写入后门,以方便其对机器的持久掌控,这种情况下这种监控方式也会失效; - 攻击者可通过
int 80h
绕过 libc 直接调用系统调用,这种情况下这种监控方式也会失效。
3.2. Netlink connector
Netlink 是一个套接字家族(socket family),它被用于内核与用户态进程以及用户态进程之间的 IPC 通信,我们常用的 ss 命令就是通过 Netlink 与内核通信获取的信息。Netlink Connector 是一种 Netlink ,它的 Netlink 协议号是 NETLINK_CONNECTOR,其代码位于 linux/drivers/connector 中,其中 connectors.c 和 cnqueue.c 是 Netlink Connector 的实现代码,而 cnproc.c 是一个应用实例,名为进程事件连接器,我们可以通过该连接器来实现对进程创建的监控。
- 优点
- 轻量级,在用户态即可获得内核提供的信息;
- 缺点
- 仅能获取到 pid,详细信息需要查
/proc/<pid>/
,这就存在时间差,可能有数据丢失。
- 仅能获取到 pid,详细信息需要查
3.3. Audit
Linux Audit 是 Linux 内核中用来进行审计的组件,可监控系统调用和文件访问
- 优点
- 组件完善,使用 auditd 软件包中的工具即可满足大部分需求,无需额外开发代码;
- 相比于 Netlink Connector ,获取的信息更为全面,不仅仅是 pid。
- 缺点
- 性能消耗随着进程数量提升有所上升,需要通过添加白名单等配置来限制其资源占用。
3.4. Syscall hook
通过修改 sys_call_table(Linux 系统调用表)来实现,具体原理就是系统在执行系统调用时是通过系统调用号在 sys_call_table 中找到相应的函数进行调用,所以只要将 sys_call_table 中 execve 对应的地址改为我们安装的内核模块中的函数地址即可。
- 优点
- 高定制化,从系统调用层面获取完整信息。
- 缺点
- 开发难度大;
- 兼容性差,需针对不同发行版和内核版本进行定制和测试。
3.4.1. 内核模块编写
- Kprobe
- Uprobe
- tracepoints
4. KVM 对宿主机中软件行为检测
- perf-kvm;
- libvirt-python:获取 VM 的相关信息;
- libvmi。
5. DeHype 改进
DeHype 系统特点:
- 把 Hypervisor 的特权指令代码的最小子集定义为 OS 扩展,即 HypeLet。其中只包含两万多行代码并仅定义了 10 个系统调用;
- 把其他大多数 Hypervisor 代码放在用户模式执行。用户模式下的 Hypervisor 通过系统调用的方式进入特权模式来执行特权指令。
6. References
KVM 虚拟化技术实现原理
Virtualization-CPU/Memory/IO 虚拟化详解
技术分享 | Linux 入侵检测中的进程创建监控
干货 | Linux 系统行为新型实时监控技术
Linux 内核调试技术——kprobe 使用与实现
CPU 的三种虚拟化机制
QEMU KVM 学习笔记