Virtualization on Linux

Today's entry is about how to set up a virtualization environment in Linux. There are many benefits to virtualization:

The three primary advantages I'm looking for are experimentation with new environments, central administration and isolation. I'd like to host a service that requires data backup as well as isolation from other users on the network.

Goals

It's worth noting some goals:

  1. The hypervisor should run on a headless server running a flavour of Red Hat. The primary selection criteria for the distribution is simple experience.
  2. The guest machines should be usable over the network from a client.
  3. The network access must be secure.
  4. The network controls must be external. Things like VLANs and DHCP should exist external to this implementation.

Dependencies

Some external dependencies that exist and worth calling out:

  1. Custom certificate authority. Worth a later entry, but I have implemented a custom CA that provides any number of certificate+key pairs.
  2. DHCP / DNS server. Using dnsmasq all known endpoints on the network are handed an IP address; others are not.
  3. Enough storage/disk space for the installed OS as well as the install media.
  4. Spare cores/memory for the host OS + each guest OS.

Install

  1. $ sudo dnf install @virtualization - Install the named group of packages for virtualization.
  2. $ sudo dnf install bridge-utils - Install utilities needed for goal number 4.

Configure

  1. /etc/libvirt/libvirtd.conf Configure libvirtd to enable TLS over the network. This install depends on using an existing certificate authority and establishing trust of the CA on both the client and server.
# TLS x509 certificate configuration
...
key_file = path-to-pem-encoded-key
cert_file = path-to-pem-encoded-certificate
ca_file = path-to-pem-encoded-authority-certificate
...
  1. /etc/libvirt/qemu.conf Configure QEMU to listen on the public/routable address for both VNC, as well as SPICE.
# VNC is configured to listen on 127.0.0.1 by default.
# To make it listen on all public interfaces, uncomment
# this next option.
#
# NB, strong recommendation to enable TLS + x509 certificate
# verification when allowing public access
#
...
vnc_listen = "0.0.0.0"
...
# SPICE is configured to listen on 127.0.0.1 by default.
# To make it listen on all public interfaces, uncomment
# this next option.
#
# NB, strong recommendation to enable TLS + x509 certificate
# verification when allowing public access
#
spice_listen = "0.0.0.0"
  1. /etc/sysconfig/libvirtd Configure libvirtd to listen on TCP/IP sockets in addition to the local socket. When troubleshooting connectivity or other service issues adding: --verbose can be useful for generating log output.
--listen
  1. /etc/NetworkManager/system-connections/bridge0.nmconnection Configure a network bridge:
[connection]
id=bridge0
uuid=819a28c5-75e0-4b74-9ff7-aa3f6291e2d0
type=bridge
autoconnect-ports=1
interface-name=bridge0

[ethernet]

[bridge]

[ipv4]
method=auto

[ipv6]
addr-gen-mode=default
method=auto

[proxy]
  1. /etc/NetworkManager/system-connections/eth0.nmconnection Configure the connection being bridged:
[connection]
id=eth0
uuid=9c2f71f0-c8d7-4d4a-8609-8e25bf396848
type=ethernet
autoconnect-priority=-999
controller=bridge0 # see step 4
interface-name=eth0
port-type=bridge
timestamp=1764793260

[ethernet]

[bridge-port]

Run

  1. $ sudo systemctl enable --now libvirtd-tls.socket
  2. $ sudo systemctl enable --now libvirtd

Connect and New

In addition to encryption; libvirt uses TLS for authentication. In order to use the running service; we need to set the CA as well as provide a certificate from the client:

Once libvirtd-tls.socket is up and running you can use Virtual Machine Manager as a user interface to build your botnet:

  1. File -> Add Connection... -> Hypervisor: Custom URI qemu://qemu.example.com/system - This will add a row in the interface.
  2. qemu.example.com -> Right Click -> Details -> Storage -> Add Pool -> Type: dir: Filesystem Directory path-to-media-stored-on-the-server - This will enable you to create VMs from media files stored on the server.
  3. qemu.example.com -> Right Click -> Details -> Storage -> Add Pool -> Type: dir: Filesystem Directory path-to-images-stored-on-the-server - This will enable you to store the image files used by QEMU on the filesystem.
  4. qemu.example.com -> Right Click -> New -> Choose how... Local install media... - This will create the VM and walk through the boot media and hardware selection process.

Epilogue

This setup worked well enough move my development workstation into a VM running Fedora 43. I have no issues with latency (everything is on a wired LAN) and can replicate all most engineering workflows.

What does not work:

Refs

Top