在Windows上运行虚拟机的开源解决方案:QEMU、MSYS2和Emacs

本文详细介绍了如何在Windows系统上使用开源工具QEMU、MSYS2和Emacs来创建和运行虚拟机,包括安装配置、性能优化以及处理VMware虚拟机文件的转换方法。

QEMU, MSYS2和Emacs:在Windows上运行虚拟机的开源解决方案

| Dave Blandford

渗透测试工程师。开发者。纯粹的GNU/Linux手机爱好者。

作为一名测试人员,我所有的工作都在虚拟机(VM)中进行。最近,我遇到了需要在Windows PC上运行虚拟机的情况。问题是,我不想在Broadcom创建账户或使用VirtualBox。我需要让QEMU(https://www.qemu.org/)运行起来。QEMU是开源的(这在我的书中总是加分项!),并且可以从qcow2镜像运行虚拟机。

这开启了我寻找一个像样的QEMU入门指南的旅程,但并没有找到,所以我决定自己写一个。

QEMU既是一个模拟器,也是一个虚拟化工具。作为模拟器,QEMU可以运行与主机不同架构的虚拟机。例如,Android Virtual Device(AVD)使用QEMU来运行基于ARM的Android系统,无论主机的物理架构是什么。这一特性在处理IoT固件时尤其有用,因为在两种架构之间转换指令可能非常困难/繁琐/不可能。

作为虚拟化工具,QEMU利用主机的硬件虚拟化来创建虚拟机。

无论你的需求是什么,QEMU都能胜任!

接下来是如何在Windows上使用QEMU。我可以直接在Windows PC上安装QEMU,但这需要手动配置和管理依赖项。我想要一个简单的解决方案。我还想使用开源项目来完成这一任务。这时MSYS2(https://www.msys2.org/)就派上用场了。作为一个开源项目,MSYS2为我提供了设置QEMU所需的UNIX shell,这更符合QEMU的设计。MSYS2自动处理依赖项,节省时间。此外,它还有Arch Linux的风格,并使用Pacman包管理器,所以加分!需要注意的是,安装MSYS2时,会安装多个终端。在本文中,我们使用的是MSYS2 MinGW 64位shell。这个shell为我们提供了原生的Windows环境。

安装MSYS2非常简单,只需下载安装程序并运行即可。安装完成后,打开MSYS2终端,更新包数据库并安装QEMU:

更新:

1
pacman -Syu

安装:

1
pacman -S mingw-w64-x86_64-qemu

验证安装:

1
qemu-system-x86_64 --version

太棒了——QEMU已经安装并运行了。接下来,下载你最喜欢的GNU Linux发行版(我想你也可以用Windows,还有BSD用户,但我们坚持用GNU Linux)。本文中,我们下载了一个64位的Kali虚拟机镜像,这将为我们提供一个虚拟化环境。

下载Kali qcow2镜像后,如果需要,可以创建一个快照。你可能需要以管理员身份运行MSYS2控制台:

1
qemu-img create -f qcow2 -F qcow2 -b "C:\path\to\image\kali-linux-2024.2-qemu-amd64.qcow2" "C:\path\to\snapshot\kali-snapshot.qcow2"

然后,运行以下命令将启动一个Kali虚拟机。注释中提供了标志的说明:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
qemu-system-x86_64 \
        #使用现代PC芯片组模型并启用Windows Hypervisor Platform
        -machine type=q35,accel=whpx \
        #基本的x86_64 CPU模型。
        -cpu qemu64 \
        #为虚拟机分配2个CPU核心
        -smp 2 \
        #4GB内存
        -m 4G \
        #qcow2镜像的路径。MSYS2也接受这种格式:/c/Path/to/snapshot
        -drive file="C:\Path\to\your\kali-snapshot.qcow2",format=qcow2,if=virtio \
        #使用virtio GPU以提高性能
        -vga virtio \
        #使用SDL显示
        -display sdl \
        #设置此选项可改善鼠标性能和集成
        -device usb-tablet \
        #为虚拟机提供网络
        -netdev user,id=net0 \
        -device virtio-net-pci,netdev=net0

这是我用于提高性能的命令。根据你的主机,效果可能会有所不同。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
qemu-system-x86_64 \
    -name "Kali Qemu" \
    -machine type=q35,accel=whpx,kernel-irqchip=off \
    -cpu qemu64,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time \
    -smp cores=2,threads=1 \
    -m 4G \
    -drive file="C:\Path\to\your\kali-snapshot.qcow2",format=qcow2,if=virtio \
    -boot menu=on \
    -vga virtio \
    -display sdl,gl=off \
    -device usb-tablet \
    -usb \
    -device usb-ehci,id=ehci \
    -device nec-usb-xhci,id=xhci \
    -netdev user,id=net0 \
    -device virtio-net-pci,netdev=net0 \
    -audiodev id=audio1,driver=dsound \
    -device ich9-intel-hda \
    -device hda-output,audiodev=audio1 \
    -device virtio-balloon-pci \
    -monitor stdio

这样,我们就有了一个使用QEMU运行的工作虚拟机。

预打包的VM配置为VMWare包,包括一个VDMK文件和VMWare配置文件(VMX)。没有可用的qcow2镜像。

我们可以使用QEMU的磁盘映像工具将VDMK文件转换为qcow2文件。仅文件转换并不能让你在QEMU中运行VM,因为它没有解决VMX文件中定义的虚拟机配置问题。

1
qemu-img convert -f vmdk -O qcow2 /c/path/to/sof.vmdk /c/path/SOF-ELK.qcow2

VMX文件可以用你选择的文本编辑器查看。我使用Emacs,我也鼓励你使用Emacs!我们需要查看VMX配置,以确保在QEMU运行时匹配这些设置。

在配置文件的更下方,有一个关于UEFI BIOS设置的引用。由于MSYS2使用Arch的Pacman包管理器,我们需要解决一个已知问题(https://bugs.archlinux.org/task/64175),即libvirt无法定位OVMF镜像。OVMF是一个开源的UEFI固件实现,用于虚拟化环境,这是运行SOF-ELK所必需的。然而,当时Arch Linux使用的edk2-ovmf包在Pacman中不可用。

有多种解决方法——这是我的方法。在这个仓库(https://www.kraxel.org/repos/jenkins/edk2/)中,我们可以获取包含OVMF文件的x64 RPM。

下载完成后,我们需要提取RPM并访问其中的文件。我使用bsdtar(https://man.archlinux.org/man/bsdtar.1)来提取RPM文件。在下面的示例中,文件保存在MSYS2路径中,而不是Windows路径。

提取RPM文件后,我们现在可以访问路径中的OVMF文件:/usr/share/edk2.git/ovmf-x64。OVMF文件是使用UEFI而非BIOS启动VM所需的UEFI固件镜像。OVMF文件可以通过.fd扩展名识别。虽然有多个.fd文件,但我使用了OVMF-pure-efi.fd镜像,并将其移动到我的工作目录。

现在我们有了UEFI启动解决方案,我们需要将指令与虚拟机匹配,以符合VMWare配置。下面的命令反映了重要的VMWare配置值。注释显示了为匹配VMX文件而添加的指令。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
qemu-system-x86_64 \
  -name "SOF-ELK" \
  -machine q35 \
  #匹配AMD配置
  -cpu EPYC,hv_vendor_id=AuthenticAMD \
  #匹配4个CPU核心
  -smp cores=4,threads=1,sockets=1 \
  #VMX中的内存设置
  -m 4096 \
  -drive file=SOF-ELK.qcow2,if=none,id=hd0,format=qcow2 \
  #VMX使用SATA,无法1:1匹配——提供一个兼容的磁盘接口
  -device ide-hd,drive=hd0,bus=ide.0 \
  -device vmxnet3,netdev=net0 \
  -netdev user,id=net0 \
  #原始VMX文件中的USB支持
  -device usb-ehci \
  -device usb-tablet \
  #设置VMX文件中的音频
  -device intel-hda \
  -device hda-duplex \
  #模拟VMWare图形
  -vga vmware \
  -display gtk \
  #设置启动顺序从硬盘开始——在VMX文件中设置
  -boot order=c,menu=on \
  #使用UEFI固件的OVMF文件
  -bios "OVMF-pure-efi.fd" \
  #使用主机本地时间——VMWare处理时间的方式
  -rtc base=localtime,clock=host \
  -serial stdio
  #设置VMX文件中定义的MAC地址
  -device vmxnet3,netdev=net0,mac=00:0c:29:ae:1b:b0 -netdev user,id=net0

运行这个命令后,我们就有了一个使用QEMU运行的SOF-ELK虚拟机!

记住,QEMU是高度可定制的,所以研究你的主机限制和需求,充分利用这个开源的机器虚拟化和模拟替代方案。

在排除故障时,需要注意以下几点:

  1. 如果启用了Hyper-V,它将成为根虚拟机监控程序。Hyper-V可能会减慢QEMU的速度,特别是在不使用Windows Hypervisor Platform(WHPX)加速器时。QEMU的默认加速器Hardware Accelerated Execution Manager(HAXM)在启用Hyper-V时不起作用。
  2. 当将物理USB设备连接到虚拟机时,可能需要以管理员身份打开MSYS2终端。
  3. 为了提高性能,根据主机的CPU、GPU和内存定制QEMU命令。
  4. 对于网络,virtio-net驱动程序提供更好的性能。Virtio-net驱动程序与模拟网络适配器相比减少了开销,特别是在使用多个核心时尤其有用。
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计