1. Overview
QEMU enables us to run various guest operating systems within our host environment. But how do we effectively interact with the virtual machines and host? Luckily, the Secure Shell (SSH) protocol is helpful here. OpenSSH helps us in setting the communication path between the two.
In this tutorial, we’ll see how to establish SSH connectivity from our host machine to a guest OS running under QEMU.
2. Prerequisites
Before getting started, some prerequisites must be met:
- the host has QEMU/KVM installed and configured
- the guest VM image is created in qcow2 format
- the guest OS has an OpenSSH server installed and enabled
- user accounts exist on both the host and guest
Specifically, we’re using a qcow2 format Parrot OS for our guest machine. We’ve chosen the qcow2 format due to its support for advanced features. For instance, these features include snapshotting, copy-on-write, and compression.
Other possible options, for example, raw and vmdk, are less suitable for QEMU setups. For example, raw images lack compression and snapshotting capabilities. While vmdk (VMware Disk Format) doesn’t support incremental data processing. Moreover, it has limited interoperability and feature availability in QEMU environment.
Also, Ubuntu 22.04 is our host machine.
3. Using QEMU Command-Line Options
QEMU comes with a basic bridge network configuration out of the box. This enables the VM to be connected to any other computer on the local network. However, we can also create a new one.
Let’s see how to configure a QEMU bridge network on our host machine.
3.1. Creating a Bridge Interface
To create a bridge network, first, we create a bridge interface using the brctl command.
Let’s name this bridge br0:
$ sudo brctl addbr br0
Next, we attach our host’s network interface (e.g., enp0s3) to the bridge:
$ sudo brctl addif br0 enp0s3
This step effectively bridges the host’s network connection with the virtual machines.
Then, we bring up the bridge interface:
$ sudo ip link set up dev br0
Finally, we add the bridge interface, br0, to the 192.168.141.101/24 network:
$ sudo ip addr add dev br0 192.168.141.101/24
This new network coincides with the host network. Thus, both the guest and host machine can use the same network.
3.2. ACL Configuration
To use the new bridge interface, we need to set the minimum permissions to the /etc/qemu/bridge.conf file on the host machine.
Let’s create the file and add a basic rule enabling connections to the bridge br0:
$ cat /etc/qemu/bridge.conf
allow br0
Moving on, we set the required permission:
$ sudo chmod 644 /etc/qemu/bridge.conf
Specifically, we can also allow all bridges if we want to.
3.3. Launching the VM
We’re now ready to launch the VM with the qemu-system-x86_64 command:
$ sudo qemu-system-x86_64 \
-drive file=/var/lib/libvirt/images/Parrot.qcow2,format=qcow2 \
-m 4G \
-smp 2 \
-enable-kvm \
-netdev bridge,id=mynet0,br=br0 \
-device virtio-net,netdev=mynet0
Let’s break down the above options:
- -drive file=/var/lib/libvirt/images/Parrot.qcow2,format=qcow2: the path to our VM image
- -m 4G: the RAM size for the VM
- -smp 2: sets the number of virtual CPU cores
- -netdev bridge,id=mynet0,br=br0: configures a network device using the br0 bridge.
- -device virtio-net,netdev=mynet0: associates the VM with the mynet0 network device using the virtio-net model
- -enable-kvm: enable KVM hardware virtualization
Consequently, this launches a KVM virtual machine with 4GB RAM, 2 CPUs, bridged networking, and Parrot OS.
3.4. Testing the SSH Connectivity
Let’s check the VM’s IP once it has fully booted:
$ip a
...
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu ...
inet 192.168.141.107/24 brd 192.168.141.255 ...
...
Next, we connect through SSH:
$ ssh [email protected]
The authenticity of host '192.168.141.107...
Thus, the SSH connection is successful.
Alternatively, QEMU can be used directly from the graphical interface. This provides more flexibility than the command line option.
4. Using virt-manager
The virt-manager GUI provides an easy way to create and manage KVM VMs. We’ll launch a VM through it and connect with OpenSSH.
4.1. Setting up VM and Configuring Networking
First, we’ll use the same bridge network interface, br0, which we used earlier with the QEMU command.
Further, we open the virtual machine manager from the Application menu:
Next, we select the Import existing disk image option:
Then, we choose the storage path for the disk image of Parrot OS:
Also, we select the OS type as Ubuntu 22.04 from the bottom search box:
Further, we select the Memory and CPU for the VM:
Finally, we select Bridge device under the Network selection option. Then, we enter br0 for Device name and click Finish:
The br0 interface is the same one we used earlier with the QEMU command line option.
4.2. Launching the VM
Finally, the virtual machine starts and we can log in to it.
Let’s check the assigned IP address to the machine using the ip command:
$ip a
...
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu ...
inet 192.168.141.115/24 brd 192.168.141.255 ...
...
We can now use this IP to connect to the VM from the host over SSH.
4.3. Testing SSH Connectivity
We now head to the host machine to start an SSH session to the guest VM.
Let’s use the ssh command to connect to the VM:
$ ssh [email protected]
The authenticity of host '192.168.141.115 (192.168.141.115)' can't be established.
...
[email protected]'s password:
Linux parrot 6.1.0-1parrot1-amd64 #1 SMP PREEMPT_DYNAMIC Parrot ...
____ _ ____
| _ \ __ _ _ __ _ __ ___ | |_ / ___| ___ ___
| |_) / _` | '__| '__/ _ \| __| \___ \ / _ \/ __|
| __/ (_| | | | | | (_) | |_ ___) | __/ (__
|_| \__,_|_| |_| \___/ \__| |____/ \___|\___|
...
Consequently, the connection is successful.
5. Conclusion
In this article, we discussed launching QEMU/KVM VMs using either virt-manager or QEMU command line option. In both cases, bridged networking and SSH connectivity enable remote management of the headless VM guest from the host. This is a vital technique for working with Linux VMs.