QEMU networking on macOS

krjakbrjak

Nikita Vakula

Posted on June 18, 2024

QEMU networking on macOS

Introduction

Setting up virtual machines (VMs) that can communicate with each other and are accessible from your host network is essential for various scenarios, such as managing Kubernetes clusters or setting up distributed computing environments. In this article, I explore how QEMU's vmnet support simplifies this process, allowing you to configure VMs effectively to meet your networking needs. Discover how you can enhance your workflow and improve collaboration between virtual instances and your host system.

QEMU networking

QEMU is an excellent open-source project that enables users to work on various projects across multiple platforms. Starting a VM instance with QEMU is straightforward. On my old Intel-based Mac, the following command will launch an Ubuntu cloud image:

qemu-system-x86_64 \
    -machine q35 -accel hvf -m 2048 \
    -nographic -hda ./jammy-server-cloudimg-amd64.img \
    -smbios type=1,serial=ds='nocloud;s=http://192.168.178.37:8000/'
Enter fullscreen mode Exit fullscreen mode

QEMU supports networking by emulating several popular network cards. According to the documentation, there are two parts to networking within QEMU:

  1. The virtual network device provided to the guest.
  2. The network backend that interacts with the emulated NIC.

By default, QEMU creates a SLiRP user network backend and an appropriate virtual network device for the guest, equivalent to using -net nic -net user on the command line. This network setup allows access to both the host and the internet, making it suitable for many use cases.

The primary drawback is that the VM cannot be accessed from the host or other VM instances. While port forwarding can be configured, it is inconvenient as it requires configuration for each port in the instance. For example:

qemu-system-x86_64 \
    -machine q35 -accel hvf -m 2048 \
    -nographic -hda ./jammy-server-cloudimg-amd64.img \
    -smbios type=1,serial=ds='nocloud;s=http://192.168.178.37:8000/' \
    -netdev user,id=mynet0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
    -device e1000,netdev=mynet0
Enter fullscreen mode Exit fullscreen mode

From the host, one can perform tasks like ssh -p 2222 user@localhost or curl localhost:8080.

However, it would be much more convenient to have a VM instance accessible on the host network. This setup would allow spawning multiple VM instances that can be accessed from the host and communicate with each other.

On macOS, the vmnet framework facilitates this, and it is already supported by QEMU. This feature was added in net-pull-request to the QEMU git tree. To utilize this functionality, the original command must be modified as follows:

qemu-system-x86_64 \
    -machine q35 -accel hvf -m 2048 -nographic \
    -hda ./jammy-server-cloudimg-amd64.img \
    -smbios type=1,serial=ds='nocloud;s=http://192.168.178.37:8000/' \
    -netdev vmnet-bridged,id=net0,ifname=en0 \
    -device virtio-net,netdev=net0
Enter fullscreen mode Exit fullscreen mode

See qemu-system-x86_64 -netdev help for more details.

Conclusion

The vmnet support in QEMU offers a straightforward method to create VM instances that can easily communicate with each other and are accessible from your network. This capability is particularly valuable in scenarios such as managing a Kubernetes cluster, where you need seamless interaction between a control plane and multiple worker nodes. Take advantage of these tools to streamline your virtual environment setup and enhance your workflow.

💖 💪 🙅 🚩
krjakbrjak
Nikita Vakula

Posted on June 18, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related