Opensuse Leap 15.4 – Online Upgrade from Leap 15.3 on an Encrypted Laptop

After my retirement I was overwhelmed by a lot of typical German bureaucracy. But last weekend I used some time to start the long overdue upgrade of my old laptop from Opensuse Leap 15.3 to Leap 15.4. (The support for Leap 15.3 ended the at the end of 2022.)

I am always a bit afraid of upgrading my old laptop. It has a somewhat complicated configuration:

Its LVM volumes are fully encrypted with LUKS 2. It is an Optimus-System – and in the past it was not always easy to switch from the integrated Intel graphics card to the dedicated Nvidia card. Instead of Bumblebee I have used Opensuse’s Prime-Select with Leap 15.3. I use KDE as my graphical desktop environment. On Leap 15.3 I did not yet apply Wayland – but I intend to switch to Wayland with Leap 15.4. For some of my activities I also use Blender with full OpenGL support in form of a Flatpack installation. Furthermore, the laptop is used for both Machine learning, i.e. Python development, as well Web-development based on LAMP. So, it hosts a variety of services you normally find on servers. In addition we have KVM and VMware WS Pro installations. So, there are a lot of things which can go wrong. The Nvidia card is also an old one – a GT 645M which cannot be run with the latest generation of Nvidia drivers.

The good message is: The upgrade from leap 15.3 to 15.4 went very smoothly. At least regarding the things I was interested in. Below I describe the steps I have taken to upgrade. With some modifications you should be able to adapt it to your situation.

Backup of the encrypted LVM volume mounted on “/”

On my desktop PCs with Opensuse-installations, which I use for daily work, I follow a two-fold “backup”-policy ahead of upgrades: I copy my root-volume/partition to another LVM-volume or partition, and make it bootable in parallel to the existing installation. Reason: I want to be able to quickly switch to my present installation in case of trouble. As I have all of my personal and project data on separate LVM volumes with dedicated backups, the root-volume is the only one which I really must take care of. Therefore, I also copy it to a backup file on an external disk. For all data volumes I have a separate backup routine.

On my laptop I am a bit more relaxed: I just copy the volume mounted on “/” to an external disk. I have no second bootable installation on some other encrypted volume on the laptop. This means that I must boot a Live system or a Rescue system to make a backup of the unmounted “/”-volume.

For my purposes the Leap 15.3 “Rescue System”, which you can find on an DVD-ISO-image for the installation of Leap 15.3, was sufficient. You get the ISO image for such a DVD from opensuse.org and can burn it onto a DVD. The steps afterward were as follows:

  1. Boot your Leap 15.3 system. Check, on which partition or LVM volume your (encrypted) root-filesystem resides. Use e.g. YaST’s partitioner or gparted for this purpose. Shut down.
  2. Insert the DVD, select a boot menu, select the DVD, start from it, select “More …” in the GRUB-like menu, then select the DVD with the “Rescue System” and boot it.
  3. Login as root (no password required). Check that a tmpfs is mounted on / – and not some real partition.
    Note: The root-filesystem of our Leap-installation is NOT mounted on “/” of the rescue system. When I speak of the “root-filesystem” below I always refer to the filesystem containing the operative system of our current Leap 15.3 installation and not the root-fs of the rescue system.
  4. Check with command blkid what the device names of all accessible partitions and LVM volumes are. You should see encrypted and other volumes/partitions of your laptop disks/SSDs there.
  5. Plugin an external backup USB-disk. blkid should now also show the partitions on this disk, too.
  6. Mount the target filesystem of the external disk, where you want to place your backup, onto “/mnt” in your booted rescue system. Check the available space. In my case (with sdc being the external disk) :
    tty1:rescue:~ # mount /dev/sdc2 /mnt
    tty1:rescue:~ # df -h 
    ..
    /dev/sdc2     825G   78G   706G     10%   /mnt 
    ...
    
  7. Locate your Leap 15.3 root-filesystem. In my case the root-filesystem of the laptop is an LUKS2-encrypted LVM available as “/dev/mapper/vgb-lvb2”. Note: You must know in advance, i.e. from your Leap 15.3 setup, where your root-filesystem resides.
  8. We now use the command “dd” to copy the root-filesystem onto a restorable image file. In my case:
    dd status=progress if=/dev/mapper/vgb-lvb2 of=/mnt/root_lap.img  
    

After the backup of the (encrypted) root-fs of our Leap 15.3 installation we shut down the rescue system, remove the DVD and boot Leap 15.3 again.

Check your RPM repositories – refresh and update

On the rebooted Leap 15.3 we check what we have of active repositories. In my case these were quite many:

(Ignore the double “mozilla” entry.)

Recommendation: You should make a similar screenshot and save it somewhere outside your laptop to later be able to restore all of the different repositories for Leap 15.4.

However, the most important repositories required to perform the upgrade are three update repositories:

  • One with renewed RPMs for the OSS,
  • one for Backports (backportet RPMs, e.g. security RPMS backportet from newer kernel or glibc related versions than the presently available versions on Opensuse Leap/SLES)
  • and one for renewed RPMs for the SLES version corresponding to the current Leap.

Update-repositories contain the latest RPMs of an Opensuse distribution. In our upgrade process we still deal with relevant update repositories for Leap 15.3. But we are soon going to exchange them with their Leap 15.4 counterparts.

Look out for the URLs of the current update repositories :

 * https://download.opensuse.org/update/leap/15.3/oss/
 * https://download.opensuse.org/<br>update/leap/15.3/backports/
 * https://download.opensuse.org/<br>update/leap/15.3/sle/ repo-sle-update

Leap 15.3 and 15.4 RPMs are binary compatible to those for the related SLES versions. In my case I had switched most of my Leap 15.3 RPMs to those of the update repo of SLES already a long time ago. If you have not done this yet you should do so now with the help of YaST.

I also directly deleted the repository for games as I regard it unimportant during an Upgrade.

Now, we refresh the lists of available RPMs and update to the latest versions. You can use the graphical YaST2 for this purpose or the command line:

mytuxlap:~ # zypper refresh

Then we perform an update of our Leap 15.3 RPMs to the latest available versions:

mytuxlap:~ # zypper update

In my case some of my Leap 15.3 repositories (for games, graphics, xfce and for snappy) were no longer available and could not be refreshed. I just had waited too long with my upgrade. But this resulted in no major problems during the upgrade.

After the update reboot and verify that your Leap 15.3 system still works.

Change repository URLs to contain the ${releasever} instead of an explicit version number

We change the URLs of our repositories now to contain ${releasever} instead of an explicit “15.3” in the URLs. It is easy to do this on the command line:

mytuxlap:~ # sed -i 's/15.3/${releasever}/g' /etc/zypp/repos.d/*.repo
mytuxlap:~ # sed -i 's/$releasever/${releasever}/g' /etc/zypp/repos.d/*.repo

The second command is just for being on the save side of the shell interpreter. I had previously already changed some of the repo URLs to include $releasever, but I want everything to consistently use ${releasever}.

Refresh for Leap 15.4 repository content – and eliminate some repositories

Next we start switching to the repositories for Leap 15.4. The first step is a refresh on the command line, but now for the Leap 15.4 repos. We can do this with the help of the variable ${releasever} in the following form:

mytuxlap:~ # zypper --releasever=15.4 refresh

Note that this does not yet change our repositories themselves, yet, but just the local content information. It gets replaced by lists about the contents of the Leap 15.4 repositories.

In my case this refresh process lead to errors. The reason was that some of the repositories which I used on Leap 15.3 had got a different path structure of the respective web resource below “download.opensuse.org/” for Leap 15.4. You have to ask the Opensuse people why they changed this.

mytuxlap:~ # zypper --releasever=15.4 refresh
Warning: Enforced setting: $releasever=15.4
Retrieving repository 'nVidia Graphics Drivers' metadata ...........................................[done]
Building repository 'nVidia Graphics Drivers' cache ................................................[done]
Retrieving repository 'Packman Repository' metadata ................................................[done]
Building repository 'Packman Repository' cache .....................................................[done]
Retrieving repository 'Update 15.4' metadata .......................................................[done]
Building repository 'Update 15.4' cache..... .......................................................[done]
Retrieving repository 'graphics' metadata .........................................................[error]
Repository 'graphics' is invalid.
[openSUSE_Leap_${releasever}_1|https://download.opensuse.org/repositories/graphics/openSUSE_Leap_15.4/] Valid metadata not found at specified URL
History:
 - [openSUSE_Leap_${releasever}_1|https://download.opensuse.org/repositories/graphics/openSUSE_Leap_15.4/] Repository type can't be determined.

Please check if the URIs defined for this repository are pointing to a valid repository.
Skipping repository 'graphics' because of the above error.
Retrieving repository 'mozilla' metadata ...........................................................[done]
Building repository 'mozilla' cache ................................................................[done]
Retrieving repository 'XFCE' metadata .............................................................[error]
Repository 'XFCE' is invalid.
[openSUSE_Leap_${releasever}_3|https://download.opensuse.org/repositories/X11:/xfce/openSUSE_Leap_15.4/] Valid metadata not found at specified URL
History:
 - [openSUSE_Leap_${releasever}_3|https://download.opensuse.org/repositories/X11:/xfce/openSUSE_Leap_15.4/] Repository type can't be determined.

Please check if the URIs defined for this repository are pointing to a valid repository.
Skipping repository 'XFCE' because of the above error.
Retrieving repository 'Libdvdcss Repository' metadata ..............................................[done]
Building repository 'Libdvdcss Repository' cache ...................................................[done]
Retrieving repository 'Update repository of openSUSE Backports' metadata ...........................[done]
Building repository 'Update repository of openSUSE Backports' cache ................................[done]
Retrieving repository 'Non-OSS Repository' metadata ................................................[done]
Building repository 'Non-OSS Repository' cache .....................................................[done]
Retrieving repository 'openSUSE-Leap-15.4-Oss' metadata ............................................[done]
Building repository 'openSUSE-Leap-15.4-Oss' cache .................................................[done]
Retrieving repository 'Update repository with updates from SUSE Linux Enterprise 15' metadata ......[done]
Building repository 'Update repository with updates from SUSE Linux Enterprise 15' cache ...........[done]
Retrieving repository 'Aktualisierungs-Repository (Nicht-Open-Source-Software)' metadata ...........[done]
Building repository 'Aktualisierungs-Repository (Nicht-Open-Source-Software)' cache ................[done]
Retrieving repository 'snappy' metadata ............................................................[done]
Building repository 'snappy' cache .................................................................[done]
Some of the repositories have not been refreshed because of an error.

Then I changed again to the repository administration of YaST and simply deleted the problematic repos. We will care for their new URL later.

Note: The fact that we may have RPMs from missing repos during the upgrade is later on compensated by allowing for a “vendor change” – which means a repository change. See below.

After having eliminated problematic repos we get a successful refresh for the contents of remaining 15.4 repositories on the command line:

mytuxlap:~ # zypper --releasever=15.4 refresh
Warning: Enforced setting: $releasever=15.4
Repository 'nVidia Graphics Drivers' is up to date.                                     
Repository 'Packman Repository' is up to date.                                          
Repository 'mozilla' is up to date.                                                     
Repository 'Libdvdcss Repository' is up to date.                                        
Repository 'Update repository of openSUSE Backports' is up to date.                     
Repository 'Non-OSS Repository' is up to date.                                          
Repository 'openSUSE-Leap-15.4-Oss' is up to date.                                      
Repository 'Update repository with updates from SUSE Linux Enterprise 15' is up to date.
Repository 'Aktualisierungs-Repository (Nicht-Open-Source-Software)' is up to date.     
Repository 'snappy' is up to date.                                                      
All repositories have been refreshed.

Download of the RPMs without applying them, yet

The next step is to download the RPMs from the Leap 15.4 repos and save them in a cache for the later upgrade process. On a TTY or a root terminal window

mytuxlap:~ #  zypper --releasever=15.4 dup --download-only --allow-vendor-change

The option “–download-only” avoids the installation of the new 15.4 RPMs. Also note the option “–allow-vendor-change”: If a RPM cannot be replaced a substitute from other major repositories will be used – if one is found.

Agree to the RPM setup displayed and the license conditions. Some 5 to 10 minutes later, after having downloaded everything, we must deactivate the graphical desktop.

Perform the Upgrade on an ASCII terminal (TTY)

On a system with both an integrated Intel card and a dedicated Nvidia card you may first want to decide which card driver you want to be loaded during the upgrade. You may use the Prime-Select Applet of Opensuse to switch to Intel on your desktop. Then logout and login again and check whether the Nvidia driver is no longer active.

Personally, I just kept the Nvidia card and the respective driver running. The resulting small problems were easy to overcome; see below.

mytuxlap:~ # lsmod | grep nvidia
nvidia_drm             69632  5
nvidia_modeset       1204224  6 nvidia_drm
nvidia              35512320  281 nvidia_modeset
drm_kms_helper        303104  2 nvidia_drm,i915
drm                   634880  10 drm_kms_helper,nvidia,nvidia_drm,i915,ttm
mytuxlap:~ #  

Important: Logout now of the graphical desktop to perform the Upgrade.

Move to an ASCII terminal (e.g. via Ctrl-Alt F1). There login as root. Type in “init 3” to stop your running X- or Wayland server. And then start the real upgrade and the respective rpm installation via “zypper –no-refresh –releasever=15.4 dup –allow-vendor-change” :

mytuxlap:~ # init 3 
mytuxlap:~ # zypper --no-refresh --releasever=15.4 dup --allow-vendor-change

You must again confirm the RPM configuration and the license conditions. Depending on your previous configuration several thousands of packages will then be installed the next 10 minutes or so from the preloaded and cached RPMs.

After all required RPMs have been installed just reboot by typing “init 6” on the command line.

My Leap 15.4 situation after reboot

In may case the systems behavior after reboot was a bit strange.

The good news is:

I experienced no problems with LUKS 2, grub2, initramfs and the second phase of the startup during which all of my other LUKS2-encrypted LVM volumes were decrypted, checked and mounted.

Off topic: Leap uses initramfs, but stores it at /boot/initrd.

The whole startup process worked like before: I get asked for the LUKS2 decryption key directly after starting the boot process, then the graphical grub2 menu comes up and I can start the primary phase of the boot process based on initramfs. In my installation, due to security precautions, I was asked to provide the decryption key once again before the second boot phase on the real root-filesystem started. (Off topic: There are configuration tricks to circumvent the 2nd request for the LuKS2 key, but my personal opinion is that the asking a second time enhances security a bit. I cannot go into the related details of a LUKS 2 configuration here.)

The bad news is:
The behavior of the Optimus environment was not consistent. Although the Nvidia RPMs had been shifted to those from the Nvidia community repository for Leap 15.4 after the reboot the Intel i915 was loaded – and I did not manage to activate the Nvidia driver. Also bbswitch interfered with my trials and shut down the Nvidia card:

The warm reboot directly after the upgrade seemed to work without major error messages (with the exception of an expected VMware related error; see below). The startup process eventually led to graphical login screen of sddm.
After login the applet for Prime-Select told me that Nvidia was active.

However, after shutting the laptop down completely and starting it via a cold boot I saw that the laptop’s LED signalling the activation of Nvidia was off (more precise showing a blue instead a red color). The Intel driver i915 was loaded with the start of the sddm login screen. Afterward the X11-KDE/Plasma combination actually worked perfectly with it. As did the combination Wayland and KDE Plasma; see below.

But at least for work with Blender I do need an active Nvidia card on the desktop. So, how to get it running?

Optimus – and a small problem with the Nvidia card

When I turned to a TTY and issued “init 3” I, actually, could activate the NVidia card via

mytuxlap:~ # tee /proc/acpi/bbswitch <<< ON

And I also could load the Nvidia driver by

mytuxlap:~ # modprobe nvidia 

In addition

mytuxlap:~ # prime-select nvidia 

seemed to be accepted by the system.

However, when I afterward wanted to start the graphical desktop again via “init 5” I experienced that the Nvidia card was directly deactivated and that the Nvidia driver, therefore, could not work or be reloaded.

What a stupid situation! Obviously, the configuration of bbswitch had not been aligned correctly with prime-select and Nvidia during Upgrade.

Solution
In the end the solution was simple: I turned to a TTY, issued “init 3”, activated the Nvidia card, loaded the present driver and used the ASCII version of YaST (not graphical yast2) to reinstall (= update unconditionally) the Nvidia drivers from the Nvidia repository

I had to pick the G05-drivers as my graphics card is rather old. Note that the driver version 470 is also relatively old and has been reported to have some problems with the display manager Wayland.

After reboot everything then already worked as expected:
The Nvidia card was activated from the start and used for the graphical desktop afterwards. And I could use the Prime-Select Applet to switch to the Intel Driver with a subsequent logout from the KDE desktop and then a re-login. With Intel the Nvidia card got deactivated – which is very reasonable as it reduces the power consumption and heat generation of the laptop.

You may also check if things are already OK after a re-installation of the Nvidia drivers. The probably important thing is that during the reinstallation mkinitrd is started in the background and dracut is forced to re-configure the initramfs – this time with a loaded Nvidia driver.

If things still do not work in your case: Check that you have blacklisted the Nouveau driver in file “/etc/modprobe.d/50-blacklist.conf” and/or “/etc/modprobe.d/nvidia-default.conf” with entries

blacklist nouveau
options nouveau modeset=0

Then stop the graphical target again: Go to a terminal (Ctrl-Alt-F1), use “init 3” and try

mytuxlap:~ # init 3 
mytuxlap:~ # tee /proc/acpi/bbswitch <<< ON
mytuxlap:~ # modprobe nvidia

This should work. Then

mytuxlap:~ # mkinitrd

Then reboot. On the graphical desktop (probably still using the Intel driver) open a root terminal window. Try

  
mytuxlap:~ # prime-select nvidia

Log out from the graphical desktop, watch the laptop LED indicating the activation of the Nvidia card (should now show that Nvidia is on), log in and check that the Nvidia driver was loaded:

mytuxlap:~ # lsmod | grep video 

This should give you something like:

mytuxlap:~ # lsmod | grep nvidia
nvidia_drm             69632  7
nvidia_modeset       1204224  16 nvidia_drm
nvidia_uvm           1138688  0
nvidia              35512320  980 nvidia_uvm,nvidia_modeset
drm_kms_helper        303104  2 nvidia_drm,i915
drm                   634880  12 drm_kms_helper,nvidia,nvidia_drm,i915,ttm

Then test the reversion to the Intel driver via Opensuse’s prime-select applet. Should work now.

No cube animation for switching virtual desktops on KDE any more!

I had a brief look at other things on my new Leap 15.4 installation. Regarding KDE on Xorg the only thing I could complain about on Leap 15.4 was that the rotating cube animation for switching between virtual desktops was gone. This is due to decisions of the KDE people. So, Opensuse is NOT to blame for it. Personally, I think the loss of the animation is a pity, but it does not hinder any productivity, either. So, no big thing …

Wayland with KDE 5.24

A switch off the display server from Xorg to Wayland is a major step. I had been reluctant to use Wayland with Leap 15.2 and 15.3. Kernel, KDE and the Nvidia driver – all of their components must support Wayland. Unfortunately, Nvidia has for years been a major hinder in the support process – in contrast to Intel or AMD. So, I was a bit skeptical with Wayland, KDE/Plasma and Nvidia’s 470-driver on my old graphics card.

Positive results: KDE 5 started well. The startup of the desktop took longer time than with Xorg but completed successfully. Afterwards: No flickering of KDE, no problems with switching between virtual desktops or 3D desktop animations. Glxspheres worked. No problems with new windows of browsers like Firefox or Chromium – as were previously reported by others.

Best of all: My flatpack installation of Blender 3.3 did work very well.

Negative results: Nvidia-settings 470 did not work. Also, 3D-animation effects like wobbly windows appeared to have a slightly better performance on Xorg. After a session break (and the display of a protection screen with the option to relogin) a return to the KDE session lead to a strong white-flickering of the background. But this could be stopped by a mouse-click on the flickering background.

All in all: Even on my relatively old laptop I can productively use Wayland with Opensuse Leap 15.4 and KDE/Plasma 5.24 and Nvidia driver 470.

Leap 15.4 repositories with different locations than for 15.3

In general we can find available repositories at “https://download.opensuse.org”. The graphics repository has found a new location at

https://download.opensuse.org/repositories/graphics/15.4/,

the XFCE at

https://download.opensuse.org/repositories/X11:/xfce/15.4/.

Use Yast to add these repositories back to your list of active Leap 15.4 repos.

Still no actual Blender version on Leap 15.4

Note: Blender in a version above 2.82 is still not available for Leap 15.4. Which is a major shame. The glibc version is just too old for Blender 3.x. The only way out of this dilemma is a Flatpack or Snap based installation of Blender 3.4.
Such installations work, however, very well on Leap 15.4 – both with Xorg and Wayland.

Multimedia: Change system packages to RPMs of the packman repository

A broad range of multimedia tools and codecs require the packman repositories. What I typically do is to add a mirror with the packman repository, e.g.

https://ftp.gwdg.de/pub/linux/misc/packman/suse/openSUSE_Leap_${releasever}/    

to the list of repositories, use YaST2 for the display of the contents of this repository and then click on the link “Switch system packages to the versions in this repository (Packman repository)”.

I tested some typical multimedia applications I use: Pulseaudio, PA equalizer, Clementine, VLC and TV channels on browsers. No problems.

What about Python?

My last development work on a desktop machine was done with Python 3.9, Jupyter notebooks and Eclipse. Leap 15.4 offers Python 3.6 as the standard. However, you can in parallel install either Python 3.9 OR Python 3.10. the OR is unfortunately exclusive. (The current Python version is 3.11).

I think I can live for some time with Python 3.10. So, I tested an installation of a virtual Python environment on Leap 15.4. The key to do so is to move to a directory where you want to implement your virtual environment – and install the relevant interpreter plus related basic directories. The following commands show an example:

myself@mytuxlap:~> mkdir /projekte/GIT/ml_5
myself@mytuxlap:~> cd /projekte/GIT/
myself@mytuxlap:/projekte/GIT> virtualenv -p /usr/bin/python3.10 ml_5 
myself@mytuxlap:/projekte/GIT> cd ml_5
myself@mytuxlap:/projekte/GIT/ml_5> source bin/activate
(ml_5) myself@mytuxlap:/projekte/GIT/ml_5> pip install --upgrade pip
Collecting pip
  Using cached pip-23.0.1-py3-none-any.whl (2.1 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 20.2
    Uninstalling pip-20.2:
      Successfully uninstalled pip-20.2
Successfully installed pip-23.0.1
(ml_5)  myself@mytuxlap:/projekte/GIT/ml_5> pip install jupyter      
Collecting jupyter
  Using cached jupyter-1.0.0-py2.py3-none-any.whl (2.7 kB)
...
...
(ml_5) myself@mytuxlap:/projekte/GIT/ml_5> jupyter-notebook 
...

This all works – but there are some (expected) errors regarding the jupyter_nbextensions_configurator. This is all well known – and also what has to be done to configure the jupyter_nbextensions correctly. This is no matter of leap 15.4.
Anyway, a Jupyter notebook will start in your default browser and you can start working with Python 3.10. I systematically added the needed libs and modules afterward with the help of pip. So, no majro problem with Python 3.10 on Leap 15.4!

What about PHP?

Well, Leap 15.4 offers an installation of either PHP7 or PHP8.0. I picked PHP8. But how does PHP 8 work together with a standard Apache2 installation on Leap 15.4?

Answer: It depends!

From the Apache point of view we would like to distribute the web server’s load on multiple Apache processes with a minimum consumption of RAM. Therefore, we would like to run Apache with an event based MPM module or just with the standard MPM-module. The problem is that this does not work with PHP. This problem already existed for lower PHP-versions than PHP 8.

You run into an error message like:

Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP.

There are two solutions to this problem:

  • Switch to a prefork configuration of Apache 2.4 – and ignore the resulting RAM consumption
  • Use FastCGI and php8-fpm.

You also have to decide which method you want to use for changing the Apache2 configuration on Leap 15.4. You can remove RPMs or use a2enmod, a2dismod and maybe a2config, respectively. Relevant commands in our case would be “a2dismod mpm_worker”, a2dismod mpm_event” and a2enmod mpm_prefork”.

The easiest way, however, is to remove the RPMs “apache2-event” and/or “apache2-worker”, depending on what kind of configuration you have installed. I have no time to discuss the specific differences of these types of Multi-process setups of Apache2 here. To be able to activate prefork the RPM apache2-prefork must be installed. A reasonable RPM selection for a prefork variant would then look like this:

With this RPM selection you can just start Apache2 with the following modules successively:

mytuxlap:~ # rcapache2 restart
mytuxlap:~ # a2enmod rewrite 
mytuxlap:~ # a2enmod -l
actions alias auth_basic authn_core authn_file authz_host authz_groupfile authz_core authz_user autoindex cgi dir env expires include log_config mime negotiation setenvif ssl socache_shmcb userdir reqtimeout php8 version mpm_prefork rewrite
mytuxlap:~ # 

I.e.: For the simple prefork solution we can either try to disable the modules mpm_worker and/or mpm_event and activate “mpm_prefork” OR remove/install related RPMs.

But there is also another way to get PHP8 running – which is based on a FastCGI configuration of Apache2 together with the installation of a service for php8, namely php8-fpm. Personally, I have not yet tried a fast-cgi / php8-fpm combination on Leap 15.4. But I intend to describe the setup soon in this blog. In the meantime, please, check the information at the following links. It is given for other operative systems, but an adaption is straightforward.

Note: php-fpm is a service which must be started on your system via systemd’s command “systemctl”.

Digital ocean on PHP-fpm and Apache2 for Ubuntu 18
Digital Ocean on PHP and BSD
Digital ocean on PHP-fpm and Apache2 for Ubuntu 20

VMware and KVM

KVM works on leap 15.4 wwithout problems. I could directly start an existing qemu-virtualized Debian installation.

VMware WS also works on Leap 15.4. But you must have a version > WS 16.2.3 available. I updated to WS 16.2.5 by installing the bundle “VMware-Workstation-Full-16.2.5-20904516.x86_64.bundle”. Afterward I could start both VMware-virtualized Windows 10 and Win 7 installations on a Leap 15.4 KDE desktop without any problems.

Conclusion

The Upgrade from Opensuse Leap 15.3 to Leap 15.4 (with a KDE desktop) works without major problems even on older laptops with old Nvidia mobile graphics cards. Its a bit irritating that some Leap repositories got a new location with Leap 15.4 – but this can be fixed after the Upgrade.

A big positive surprise was that KDE 5.24 worked with Wayland even on my old Nvidia GT 645M card. A current Blender version MUST, unfortunately, be installed via Flatpack. Python 3.10 and PHP 8.0 are supported. KVM and VMware WS 16.2.5 pose no problems on Leap 15.4.

Happy working with Leap 15.4!

Links

Wayland vs. Xorg
https://linuxiac.com/ xorg-x11-wayland-linux-display-servers-and-protocols-explained/

Apache2 and PHP8
https://bbs.archlinux.org/ viewtopic.php?id=178124

 

Ceterum censeo: The worst fascist, war criminal and killer living today is the Putler. He must be isolated at all levels, be denazified and sooner than later be imprisoned. A president who orders the systematic destruction of civilian infrastructure must be fought and defeated because he is a permanent danger to basic principles of humanity. He must be brought to justice in front of an international court. Long live a free and democratic Ukraine!

 

KVM/Qemu VMs with a multi-screen Spice console – VI – remote access with remote-viewer and TLS encryption

In my series on various methods to access a Spice console of a VM I have already covered two remote scenarios in an Intranet based on remote-viewer and SSH:

  • Scenario 1: remote-viewer is run on the KVM/Qemu server and accesses the Qemu-hypervisor over a Unix socket. The user at the remote client-system opens a “ssh -X” or “ssh -XC” session to the server, starts remote-viewer there and uses the graphical output data via the client’s X-server. Audio requires a reverse SSH tunnel for Pulseaudio ( “ssh -X -R 44713:localhost:4713” ).
  • Scenario 2: remote-viewer is started on the remote client-system. A Spice and VM-specific TCP-port (TCP socket) on the server is used for the transfer of video + audio data. Security can be achieved by establishing a SSH tunnel with port-forwarding and further user-related SSH-restrictions.

See
KVM/Qemu VMs with a multi-screen Spice console – V – remote access via remote-viewer, a network port and a SSH-tunnel
KVM/Qemu VMs with a multi-screen Spice console – IV – remote access via SSH, remote-viewer and a Unix socket
KVM/Qemu VMs with a multi-screen Spice console – III – local access with remote-viewer via a Unix socket
KVM/Qemu VMs with a multi-screen Spice console – II – local access with remote-viewer via a network port
KVM/Qemu VMs with a multi-screen Spice console – I – Overview over local and remote access methods

Security regarding an encrypted data transfer, user authentication and port or socket access was achieved via SSH in both scenarios, plus ACLs in case of the first scenario. A critical point in both scenarios was data compression. SSH compression (=gzip) had a palpable negative impact on the responsiveness of the VM’s desktop in the Spice windows. However, data compression offered via Spice options did not diminish the performance – at least it could not be felt.

In this article we have a look at yet another scenario for remote-viewer: Spice is this time combined with TLS encryption. However, in this post, we use TLS for data encryption, only, and not yet for client-authentication. Client authentication methods in combination with TLS and remote-viewer will be the topic of the next article.

We use the same systems as in the last articles: A KVM/Qemu server host “MySRV” with a Leap 15.2 OS on it, a test-VM “debianx” with a Kali-OS on it and a client-system “MyLAP” (a laptop with a Leap 15.2 OS). On the KVM/Qemu host our meanwhile familiar user “uvma” is used to start the VM “debianx” for us with the help of virt-manager. On the client-system “MyLAP”, instead, a user “myself” will start remote-viewer.

Schematic drawing

The following sketch shows what we want to achieve:

The
Qemu-hypervisor shall use a TLS server-key and a X509-server-certificate to encrypt all application data transferred in our Intranet between the server and the remote-viewer application on the client-system. This should include all data channels of the Spice protocol.

TLS CA, server certificates and RSA-keys

A sound TLS setup requires at least a CA, a CA-certificate, a server-certificate for the KVM/Qemu-server and a file with the private key of an asymmetric (RSA) key-pair. This brings us to the question: What tools can we use on a Leap-system to create such certificates for our private network?

On a Linux system there are, of course the OpenSSL libraries together with the so called “certtool“, a CLI-tool. You get the latter on Leap 15.2 by installing the “gnutls” RPM from the Leap15.2-Update repository. A documentation for the creation of CA, server and client TLS certificates and related key-pairs with certtool is given on the following web-pages:
https://libvirt.org/tlscerts.html
https://qemu-project.gitlab.io/qemu/system/tls.html.

Personally, I prefer a graphical tool to keep an overview about my own CAs and related server-certificates. As Opensuse never replaced their YaST CA-tool after they changed to Ruby as the programming platform for YaST we have to look elsewhere.

A very good tool which provides a lot of options is “XCA“. You find it in the package “xca” on a Leap 15.2 system. It is intuitive to use, offers a lot of options and its “help” documentation is very good – if you already know something about the differences and requirements of certificates. It offers suitable templates for CA-, server- and client-certificates. For a step-by-step description of how to create certificates see section 14 in the help functionality. Other tutorials for certificate creation with “xca” can be found in th following PDFs
http://help.mguard.com/ pdf /en / mguard8/ AppNotes/ AH EN X.509 CERT XCA 108396 en 00
http://evardsson.github.io/ s3c3/ Generating, signing and exporting keys and certificates with XCA

Another older tool, which I still use, is TinyCA. The following image shows a test example (I have no such net nor server as displayed).

Its templates are simpler than those of “xca”; the options are also a bit more limited, but sufficient for private purposes. Opensuse provides a RPM “tinyca2” in its standard repositories. I have written some blog posts about it; see: TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – I and two later posts.
Please, be aware of the fact that you need to apply additional patches to get SHA-256 and SHA-512 capabilities. See the named post about it. You should be able with my descriptions to create a server certificate for your KVM/Qemu-host. Also see TinyCA2 as a replacement for YaST’s CA-tools on Opensuse Leap servers with TLS/SSL – II for a description into which directory the CA-certificate files should be placed on a Leap 15.x OS.

For the rest of the present article I assume
the following:
You have created a CA, a CA-certificate, a X509-compatible server-certificate and a RSA based private key for the server. You do this on whatever system you use for the administration of your CA. You have also exported the certificate data and the key into files with the “pem“-format and copied them (scp) to a save place under the control of root on your KVM/Qemu server host. In the end you should have the following files there:

  • ca-cert.pem
  • server-cert.pem
  • server-key.pem

Note that these specific file-names are important for the later Qemu-configuration. You should rename your files accordingly or make copies with these names. Note that the server-key file contains a private key – this file must be protected against unauthorized access during all steps of the configuration process and after.

Note also that the server-certificate should be set up with the FQDN of our KVM/Qemu-server: This is “mysrv.anraconc.de” for our test situation.

You must also place a copy of the CA-cert file onto the client-system(s) from which the Spice user later connects to the KVM-server. The “CA-cert”-file must in addition be known there as coming from a trustworthy CA. See a separate section below for the required measures on an Opensuse Leap system.

If you already had a CA and had already issued certificates in the past – can we reuse them? The answer is: Yes, you could. Personally, however, I prefer to issue a special dedicated server-certificate and keys for Qemu. One of the reasons is that the Qemu process must be able to read the server-key-file and it is run for a special user “qemu” and not root. But I do not want “qemu” to be able to read other server-keys used by completely other processes as e.g. for a web- or mysql-server.

Configuration of Qemu on the KVM-host for TLS connections

You remember from previous articles of this series that remote-viewer talks directly to the Qemu-hypervisor; it does not involve any libvirt layer. It is therefore no surprise that we need to configure Qemu itself such that it uses TLS. But which is the right configuration file to take? And where do we place our certificates and keys?

On a Leap 15.2 system we normally use the libvirt machinery to create and start Qemu-based VMs and the related Qemu-processes. Then we need to tell libvirt how to start a Qemu-process with the required correct options. The config-file to take in this case is “/etc/libvirt/qemu.conf” (see the 2nd article of this series).

[If you, by the way, are interested in the qemu-options and in particular the TLS options which can be used if and when you start a qemu-process manually see the qemu documentation, e.g. here and here.]

The named “qemu.conf”-file on our Leap based KVM/Qemu-server has multiple sections regarding TLS. The first main section covers the directories used for certificate and key-files. There you also find the file-names mentioned above. Later on you find an option to change the directory for Spice related certificates. We use this option.

For the time being we set the following parameters and un-comment the related lines:

# The following tells Qemu to use TLS for the encr<yption of Spice cahnnels 
spice_tls = 1  

# We need to specify a directory where we place the certifactes and key to be used  
spice_tls_x509_cert_dir = "/etc/pki/libvirt-spice"

That is all we need for this article. (As mentioned in a previous post: On systems with apparmor active one should also activate “security_default_confined = 1”. But this no special TLS option).

Afterwards we have to copy our certificate- and key-files to “/etc/pki/libvirt-spice/“.

Note
again:
It is obligatory to use the filenames given above. A VM would not start otherwise and Qemu would complain non-existing or unusable files.

What file access rights are required?
The certificates should only include public keys, so here we could grant others the “r”-right. The situation is different with the file “server-key.pem“. It contains the server’s private key – and probably in unencrypted form if we did not protect it by password.

Therefore, we need to restrict the read rights for this file. And here we are confronted with a small glitch in the Opensuse configuration – the apparmor settings allow the privileged libvirt-user who is allowed to start virsh or virt-manager to read the files – but not “qemu”. A simple solution is

mysrv:~ # cd /etc/pki/libvirt-spice/
mysrv:/etc/pki/libvirt-spice # chmod 440 *
mysrv:/etc/pki/libvirt-spice # chown root.qemu * 
mysrv:/etc/pki/libvirt-spice # la
total 20
drwxr-xr-x 2 root root 4096 Apr 11 11:44 .
drwxr-xr-x 8 root root 4096 Feb 27 15:11 ..
-r--r----- 1 root qemu 2504 Feb 27 15:14 ca-cert.pem
-r--r----- 1 root qemu 2504 Apr 11 09:49 server-cert.pem
-r--r----- 1 root qemu 3243 Apr 11 09:49 server-key.pem
mysrv:/etc/pki/libvirt-spice # 

But from now on you should be careful during your experiments and check what members the group “qemu” has – on a Leap system it should only contain the user “qemu”, nobody else!

The question remains whether you need the CA-cert-file for any other purposes on the KVM server. If so, please follow the advice given in the section for using the ca-cert-file on the client-system and apply them in an analogous way on the server.

You should restart the libvirtd-daemon to activate the changed options for the start of Qemu-based VMs via virsh or virt-manager in the future.

Configuring Qemu to use TLS is NOT the same as configuring libvirt to use TLS!

Just a warning:
Readers who work totally libvirt-centered and use virt-viewer instead remote-viewer should at this point of reading become very clear about the fact that configuring Qemu for using TLS with Spice is something else than configuring libvirtd to use TLS for external connections. The Opensuse documentation at
doc.opensuse.org/ documentation/ leap/ virtualization/ html/ book-virt/ cha-libvirt-connect.html
refers to the latter. The settings to activate TLS for libvirtd and libvirt-tools use a different directory scheme and different file-names in comparison to what we did above. Also the required file access to certificates and private keys can be limited to root for pure libvitr-based tools – but not in our scenario.

Configuring the VM to use TLS with Spice

So far Qemu is prepared to support TLS on the KVM-server – if and when the use of TLS is requested. We, therefore, still have to define that TLS should be used for connections to the Spice console of our specific test-VM “debianx”.

Actually, we have to define a special network port for this purpose. In the XML-configuration file for the VM we change the Spice settings :

    
    <graphics type='spice' port='20001' tlsPort='20002' autoport='no' keymap='de' defaultMode='any' >
      <listen type='address' address='0.0.0.0'/>
      <image compression='auto_glz'/>
      <gl enable='no'/>
    </graphics>
    <sound model='ich6'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </sound>
    <video>
      <model type='virtio' heads='2' primary='yes'>
        <acceleration accel3d='yes'/>
      </model>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'
/>
    </video>

The first change in comparison to previous settings consists of a new attribute “tlsPort
(Off topic: I use the same audio and video settings as before.)

Note:

The “tlsPort” – just as the the standard “port” – is specific for the VM.
For another VM you must define another “tlsPort”.

The second change is the removal of the attribute “defaultMode”. This allows us later to switch between TLS-secure and “insecure” access methods as we like. Remember that we always can make a insecure” connection (regrding a lack of TLS) secure at any time by building a SSH tunnel.

Some reader may ask why we did not set the default mode to “secure” and deleted the “port”-attribute. Well, if we were in a position in which we had tested the TLS configuration already and wanted to use TLS only in the future (and not SSH, for example) then we could make these changes, yes. But I keep the option of using a SSH-tunnel open. TLS is anyway the preferred option if the associated port is specified by the Spice client (here remote-viewer).

The reader certainly has noticed that I activated Spice image data compression. We made a good experience with it the other day.

How to deal with the CA-certificate on the Leap 15.2 client-system? Where to place it?

OpenSSL will validate the whole CA-chain when confronted with a server-certificate. It needs the CA-certificate for it. In addition it should trust the related public key – as the CA-root-certificate is self-signed. This means that we have to make the certificate of our private CA known to the client-system(s) – here MyLAP – on which we want to start a Spice client requesting a TLS encrypted connection from the KVM/Qemu-server.

Opensuse Leap systems are a bit picky about were to place the CA-certificates. To say it clearly: “/etc/ssl/certs” is the wrong place!

Any certificates unknown to Leap 15.2 will not survive a reboot there. They won’t even survive a call of the “update-ca-certificate“-program, which would make the CA-certificate known to other programs as a usable and trustworthy one. So, placing the “ca-cert.pem”-file of our private CA into “/etc/ssl/certs” will lead to severe problems: It won’t be found or won’t be accepted during the start of remote-viewer on a client-system as MyLAP.

Note:

The right place for the certificate of our private CA on a Leap-system is “/etc/pki/trust/anchors/“.

You should copy it there. By the way: You should use the name given to your CA initially – not necessarily the special file name used for Qemu on the KVM/Qmu server. In my case it is something like “anraconc-CA”, thus “anraconc-CA.pem”.

So, we perfom the following copy-process

CaSRV:~ # scp /root/.TinyCA/anraconc-CA/cacert.pem root@MyLAP:/etc/pki/trust/anchors/anraconc-CA.pem
Password: 

On MyLAP we then enter

mylap:/etc/pki/trust/anchors # la 
-r--r--r-- 1 root root  2540 Apr 11 11:11 anraconc-CA.pem
mylap:/etc/pki/trust/anchors # update-ca-certificates
mylap:/etc/pki/trust/anchors # la /var/lib/ca-certificates/openssl | grep anrac
lrwxrwxrwx 1 root root    15 Apr 11 12:13 610c65bd.0 -> anraconc-CA.pem
-r--r--r-- 1 root root  2540 Apr 11 12:13 anraconc-CA.pem
lrwxrwxrwx 1 root root    15 Apr 11 12:13 bfb4c341.0 -> anraconb-CA.pem

“update-ca-certificates” makes the CA-certificate system-wide. The look into “/var/lib/ca-certificates/openssl” just was a check for this.
That is all we have to do regarding certificates on the client.

Test of the TLS encrypted remote connection to the Spice console

We first open our firewalls for connection from MyLAP to port 20002 on MySRV. On our KVM/Qemu-host we then start the libvirtd-daemon again to cover all
changes to Qemu and the VM. Afterward our privileged user “uvma” starts the VM “debianx” for us on the server. This should work without any problems – there should not be any errors regarding the TLS options and TLS files.

Then we have a brief look at https://libvirt.org/uri.html and https://www.spice-space.org/spice-user-manual.html to get an idea how we have to formulate our remote-viewer parameters for TLS:

myself@mylap:~> remote-viewer spice://mysrv.anraconc.de?tls-port=20002

(remote-viewer:29853): GSpice-WARNING **: 15:29:34.201: Warning no automount-inhibiting implementation available

with results that look very similar to what we have done in the last article. I omit the proof by screenshots as we would get no new information from them.

But did you notice a major difference besides the special way of specifying the TLS-port to use ?
We have to use the FQDN of the server!
Exactly in the form it was filled as the “common name” into the server-certificate! If we just used “mysrv” this would lead to an error message of OpenSSL – despite the fact that the short name can be resolved by a DNS server.
Note also that something like “remote-viewer spice://mysrv.anraconc.de:20002” will NOT work.

The required form of the command for remote-viewer with TLS is :

remote-viewer spice://FQDN_OF_KVM_HOST?tls-port=VM_SPECIFIC_PORT_NR

You should also test that the variant

myself@mylap:~> remote-viewer --spice-ca-file=/etc/pki/trust/anchors/anraconc-CA.pem  spice://mysrv.anraconc.de?tls-port=20002

works flawlessly.

Checking for encryption

A look at netstat on the server proves a connection to port 20002:

mysrv:~ # netstat -an | grep 20002
tcp        0      0 0.0.0.0:20002           0.0.0.0:*               LISTEN     
tcp        0      0 192.168.2.4:20002      192.168.2.22:36650      ESTABLISHED
tcp        0      0 192.168.2.4:20002      192.168.2.22:36646      ESTABLISHED
tcp        0      0 192.168.2.4:20002      192.168.2.22:36642      ESTABLISHED
tcp        0      0 192.168.2.4:20002      192.168.2.22:36648      ESTABLISHED
tcp        0      0 192.168.2.4:20002      192.168.2.22:36658      ESTABLISHED
tcp        0      0 192.168.2.4:20002      192.168.2.22:36656      ESTABLISHED
tcp        0      0 192.168.2.4:20002      192.168.2.22:36640      ESTABLISHED
tcp        0      0 192.168.2.4:20002      192.168.2.22:36644      ESTABLISHED
tcp        0      0 192.168.2.4:20002      192.168.2.22:36652      ESTABLISHED
tcp        0      0 192.168.2.4:20002      192.168.2.22:36654      ESTABLISHED
mysrv:~ # 

While this only shows that a connection to the right port is established. However, an additional look with wireshark shows you the TLS version (which it gets from protocol headers):

We see that TLS V1.3 is indeed used to encrypt the application data crossing port 20002.

Data transfer rates and responsiveness

The data transfer rates for the present scenario overall are very similar to the ones measured for the SSH-scenarios with Spice data compression. Maybe a tiny bit higher for TLS. But there are too many impact factors to really say this. The responsiveness of the window manager and single applications are excellent – as with the SSH scenario of the last article. I leave it to the reader to test it out on his own.

Does TLS encryption to the VM work locally, too?

An interesting question is whether we can have
encryption locally on the KVM/Qemu-server, too. The answer is: Yes, but you still have to provide the FQDN of the server; the network request will nevertheless be handled over the “lo”-device. This at least enables you to test your VM settings locally. But local encryption could also be interesting in some multi-user scenarios.

Using different options for the defaultMode and the Spice data channels

Allowed values for the “defaultMode” attribute in the Spice configuration of the VM are “secure”, “insecure” and “any”. With “any” you can switch between encrypted and unencrypted access at any time by closing the Spice windows and opening them again with different settings for the remote-viewer. You should check which port is taken by looking at the output of e.g. netstat. Using “secure” will enforce TLS-encryption; if no sufficient certificates were in place the VM would not even start then.

An important feature regarding TLS is that you may define which Spice data channel should/must be encrypted. You find more information about this at https://libvirt.org/formatdomain.html#graphical-framebuffers. I quote from the documentation there:

When SPICE has both a normal and TLS secured TCP port configured, it can be desirable to restrict what channels can be run on each port. This is achieved by adding one or more elements inside the main element and setting the mode attribute to either secure or insecure. Setting the mode attribute overrides the default value as set by the defaultMode attribute. (Note that specifying any as mode discards the entry as the channel would inherit the default mode anyways.) Valid channel names include main, display, inputs, cursor, playback, record (all since 0.8.6 ); smartcard ( since 0.8.8 ); and usbredir ( since 0.9.12 ).

The example given in the libvirt documentation is:

    
<graphics type='spice' port='-1' tlsPort='-1' autoport='yes'>
  <channel name='main' mode='secure'/>
  <channel name='record' mode='insecure'/>
  <image compression='auto_glz'/>
  <streaming mode='filter'/>
  <clipboard copypaste='no'/>
  <mouse mode='client'/>
  <filetransfer enable='no'/>
  <gl enable='yes' rendernode='/dev/dri/by-path/pci-0000:00:02.0-render'/>
</graphics>

Off topic: You see that there are more options for Spice – e.g. the streaming parameter, which can be used for video-streaming. In a quiet minute the interested reader should have a look into the Spice documentation at
https://www.spice-space.org/spice-user-manual.html
and
https://qemu.readthedocs.io/en/latest/system/invocation.html
to get more information.

What about other security elements?

It is nice that we now are able to use a TLS encrypted connection for remote-viewer. But a noticeable disadvantage in comparison to the SSH-tunnel scenario of my last article is that we must keep the Spice TLS-port open and accessible on the server. In addition: Basic security measures on a server should also include some form of user authentication – and the access to the Spice console of a VM should be restricted to selected users. With the TLS-elements discussed above alone we cannot achieve this. So, you have to wait for yet another blog article.

In the meantime you can and should at least set a password for the Spice console:

    
<graphics type='spice' port='20001' tlsPort='20002' autoport='no' keymap='de' defaultMode='any' password='my_verysecret_pwd' >
..... 

See the 2nd article of this series about it.

Conclusion

It is relatively easy to
configure a KVM/Qemu-server such that it encrypts Spice data with TLS. We tested this with a remote-viewer instance started on a client-system somewhere in our Intranet. A basic requirement is of course the creation of a private CA and certificates/keys. Tools like TinyCA or XCA help us with this.
As remote-viewer directly talks to the Qemu-emulator we had to configure libvirtd to enable dependent tools like “virsh” and “virt-manager” to start qemu-processes with the required parameters for TLS. This could be done via a few settings in the file “/etc/libvirt/qemu.conf”.
This type of qemu-configuration differs from activating TLS for a remote access to libvirt-based tools themselves. As a consequence the private server-key to be used by the Qemu process must be made readable for the “qemu”-user.
The TLS setup for remote-viewer and Spice neither allowed for user authentication on the server nor for user-specific restrictions so far. In the next article

KVM/Qemu VMs with a multi-screen Spice console – VII – remote-viewer, qemu and SASL authentication

we shall, therefore, have a look at methods for user authentication combined with TLS.

Links

Qmu, Spice und TLS
https://qemu-project.gitlab.io/qemu/system/tls.html

https://www.libvirt.org/tlscerts.html

https://ravada.readthedocs.io/en/latest/docs/spice_tls.html

Spice + defaultMode
https://libvirt.org/formatdomain.html#video-devices

OpenSSL to check for a valid TLS certificate on a network port
https://tenable.force.com/s/article/Using-OpenSSL-to-verify-certificate-information-on-a-port

KVM/Qemu VMs with a multi-screen Spice console – IV – remote access via SSH, remote-viewer and a Unix socket

I continue with my series on methods to access the graphical Spice console of virtual machines [VM] based on the KVM/Qemu-hypervisor combination on a Linux host.

KVM/Qemu VMs with a multi-screen Spice console – III – local access with remote-viewer via a Unix socket
KVM/Qemu VMs with a multi-screen Spice console – II – local access with remote-viewer via a network port
KVM/Qemu VMs with a multi-screen Spice console – I – Overview over local and remote access methods

In the last article we saw that “remote-viewer” can be used locally on the KVM-host to directly access the Qemu-emulator of a specific VM via a Unix socket instead of a network port. Its a simple and fairly effective method – though not well documented. We confined the right to access the socket for a VM to a specific group of users.

Actually, the socket based access method also provides the basis for a simple remote scenario in an Intranet – namely via ssh -X. This is the topic of this article.

Such a method requires relatively high data transfer rates across the network – but in a switched Gigabit LAN the rates are within reasonable limits …. And despite a lack of OpenGL HW acceleration Spice reacts very responsively to mouse operations and window movements. In the course of our experiments I will also introduce another virtual “video” device model which can be used together with our VM – namely a “virtio” device with multiple heads. As the QXL device it corresponds to a kind of virtual graphics card.

I assume that the reader is familiar with SSH and the setup of the SSH-service on a Linux system. Some knowledge about Pulseaudio is helpful, too.

Why do we care about remote Spice scenarios in an Intranet?

Why do I discuss remote scenarios for a “one seat” console of a VM in an Intranet at all? One answer is:

Any free-lance consultant or developer must think about a systematic way of how to organize data and work for customers in accordance with security requirements like the EU-GDP or the German DSGVO. Personally, I strongly recommend to confine the work and all data exchange processes for a selected customer to a specific VM on a well managed Linux server host. You then can encrypt the virtual disks and isolate the VM(s) pretty well by configuring both firewalls in the virtual network, on each VM as well as on the KVM-host and on routers in your LAN. Backup, recovery and machine extensions are easy to manage, too.
But you may need to access a VM’s desktop graphically from a client system (PC, laptop). This is were Spice comes into the game – at least in a Linux environment. Being able to work with a full fledged graphical desktop of a VM from different clients and locations in your LAN might be a basic requirement for preparing presentations, documents and maybe some development work in parallel on the VM.

I myself, for instance, often access the full desktop of server-based VMs from my Linux workstation or from a Linux laptop. Via SSH and the Spice console. We shall see below that the network data transfer rates for applications as Libreoffice Draw via SSH to the KVM host and using the Spice console can become smaller than in a situation where we open Libreoffice remotely by a direct “ssh -X” call to the VM itself. And the situation is even better in other scenarios we shall study in forthcoming articles.

In general it will be interesting to watch the objective data transfer rates plus the felt
responsiveness of Spice clients in remote scenarios throughout all our coming experiments.

Encryption requirements – the advantages of SSH

Even in the LAN/Intranet of a free-lancer or in a home-office with multiple users encryption for remote interactions with VMs may be required. We have two main options to achieve this for remote-viewer:

  • We use SSH on the remote system, connect to the KVM-host and start remote-viewer there.
  • We start remote-viewer on the remote system and encrypt the connection to the VM on the KVM host with TLS.

Both methods have their advantages and disadvantages. In the end usability on the remote system is an important criterion. A TLS setup will be discussed in a forthcoming post. Note that we also can use remote-viewers’ sister application “virt-viewer” in a SSH-based scenario – but this is a different story, too.

It is clear that using “ssh -X” is a simple approach which just uses the X11-protocol capabilities to realize a remote scenario. But it has some major advantages over other scenarios:

  • We get encryption almost for free. Most SSH implementations on Linux systems work out of the box.
  • We can enforce the use of secure Opensource encryption algorithms – both for the asymmetric KEX and authentication mechanisms and for the symmetric encryption parts of the data exchange. (See https://stribika.github.io/2015/01/04/secure-secure-shell.html)
  • We get user authentication based on a public key algorithm almost for free.
  • We can use a “ssh-agent” on the remote client to control the different authentication keys for different users allowed to access different VMs.
  • It is sufficient to open a SSH-port on the server. We do not need to open extra network ports for the Spice protocol.
  • We can get encrypted audio data transfer with some simple tricks in combination with Pulseaudio.

Therefore, it is really worthwhile to test a combination of “ssh -X” with starting remote-viewer on the KVM host. I shall, however, not discuss basics of SSH server and client configurations in this article. The preferred or enforced use of certain encryption algorithms for specific SSH connections is something a Linux user should be or become familiar with.

Regarding authentication I assume a standard configuration where private and public authentication keys are organized in the folders “~./ssh/” both for the involved user on the remote client system and the invoked user on the KVM/Qemu server host, respectively.

Schematic drawing

I have not yet depicted the SSH scenario with remote-viewer in any of my schematic drawings so far. The combination of remote-viewer with SSH is a variant of a local scenario as we open the “remote-viewer”-application on the KVM host [MySRV] and just transfer its graphical output via SSH to the X-Server of a remote Linux workstation [MyWS].

We do not care about the transfer of audio data during our first steps. We shall cover this problem in some minutes.

On the left side we see a Linux workstation from which a user logs into our KVM host as user “uvmb”. I assume that user “uvmb” has become a member of the special group “spicex” on the KVM host which we gave read/write access to the Spice UNIX socket created by Qemu (see my last post). On the right side we have our a KVM/Qemu server host. The user starts the remote-viewer application there (i.e. on the KVM
host), but gets its graphical output on his desktop on the remote workstation. On the KVM/Qemu host we, of course, use the fastest method for the remote-viewer application to exchange data with the Qemu-emulator process – namely via a Unix socket. See the definitions for the VM’s XML file (for libvirt applications) discussed in the last post:

    
    <graphics type='spice' autoport='no' keymap='de' defaultMode='insecure'>
      <listen type='socket' socket='/var/spicex/spice.socket'/>
      <image compression='off'/>
      <gl enable='no'/>
    </graphics>

This scenario may appear a bit strange for those among my readers who know that remote-viewer is a network client application: Remote-viewer is normally used on a remote client systems to connect to the Qemu process for a VM on a server host via TCP over a LAN. In our present scenario, however, we start remote-viewer on the server host itself and achieve network capabilities only by making use of SSH. But such a scenario sets comparison standards regarding data transfer rates. Any real client/server solution should provide advantages over such a simple approach. We come back to such comparisons in the forthcoming articles of this series.

An interesting question, for example, is whether the whole data exchange will resemble more a transfer of image data in the case of a full desktop presentation by remote-viewer or a transfer of X commands for constructing individual desktop contents. We should not forget that Spice and remote-viewer have their own handling of graphical data and a special client-server model for it.

A first disadvantage of our simple SSH-based scenario could result from the following fact:

Spice does not accept an activation for the compression of image data for a local socket-based configuration. As we start remote-viewer in our scenario on the KVM host we, therefore, cannot use the image-compression option for the Spice configuration. If a reduction of data transfer rates is required due to a limited LAN bandwidth our only chance is to use data compression for SSH. SSH uses gzip; due to extra CPU activities on both sides using compression may reduce the performance of application which exchange many data between the SSH client and server during user interactions.

In my test setup the KVM-host is controlled by an Opensuse Leap 15.2 OS, whereas the remote client system – a laptop (MyLAP) – runs Opensuse Leap 15.1. (Yes, I should have upgraded it already …).

Requirements for a reasonable performance of remote scenarios with SSH, remote-viewer and Spice

“ssh -X” is not the most efficient way of transferring graphical data. The performance experience depends a bit on the symmetric encryption algorithm and very much on the bandwidth of your network. To make a long story short:

For the QXL device temporary peaks of the data transfer rate can reach 60 MiB/s to 90 MiB/s for some window operations on a Spice console. Such rates may e.g. occur appear when you move complex and large windows quickly around with the mouse on the displayed VM’s desktop – with transparency effects of a XRender compositor being active. With the “virtio” graphics device we reach a rate of around and below 40 MBit/s.

Such rates may seem quite high – and they indeed are. But a quick test shows that you reach 25 – 45 MiB/sec already when quickly moving around a complex transparent pattern within a “Libreoffice Draw” sketch remotely over a network connection with SSH. The presentation of transparent windows within a KDE desktop with compositor dependent effects is far more complex. So Gigabit NICs are required.

If your network becomes a limiting factor you can use the “-C”-option of SSH to enable data compression. This may give you a factor between 8 and 10 for the reduction of transfer data rates. In a test
case with remote-viewer I could reduce the data transfer rate below 8 MiB/s from something of 80 MiB/s without compression. This is an impressive reduction of data.

But there is a caveat of compression, too. The compression has to happen very (!) quickly for fast user interactions with the displayed VM-desktop in the Spice windows. So, you may get a delayed response now for some fast actions on the displayed desktop due to the compression overhead. Now you need pretty fast CPU cores on the KVM/Qemu host and the remote client system! Depending on your system and your LAN I would experiment a bit with and without compression.

A first test

I use a laptop with the hostname “MyLAP” with an Opensuse Leap 15.1 installation for a quick test. The VM (with a KALI 2020.4 OS) is located on a server host “MySRV” with Opensuse Leap 15.2 (see the last articles of this series for its configuration).

On the laptop I start a KDE session as user “myself”. We have a SSH authentication key pair prepared. Our (private) key resides in “~/.ssh/id_rsa_vm”. We have exported the public key to the KVM host into the “~/.ssh/”-directory of the user “uvmb” there (probably “/home/uvmb/.ssh/”). User “uvmb” is a member of the group who got “rw”-access by ACL rules on the KVM-server to the specific UNIX socket used by our test VM “debianx” (see the previous articles).

On the KVM host a privileged user “uvma” has already started the VM “debianx” (with a local socket configuration) for us. Just to be on the safe side we open a desktop session for user “uvmb” on the KVM/Qemu” server and test remote-viewer there:

All Ok here.

Now, we move to the laptop. There we open a KDE session, too, as user “myself”. In a terminal we start the ssh-session:

myself@mylap:~/.ssh> ssh -X -i ~/.ssh/id_rsa_x uvmb@mysrv
Enter passphrase for key '/home/myself/.ssh/id_rsa_x': 
Last login: Thu Mar 25 09:54:53 2021 from 192.168.2.22
Have a lot of fun...
uvmb@mysrv:~> 
uvmb@mysrv:~> remote-viewer spice+unix:///var/spicex/spice.socket &
[1] 5041
uvmb@mysrv:~> 
(remote-viewer:5041): GStreamer-WARNING **: 12:37:49.271: External plugin loader failed. This most likely means that the plugin loader helper binary was not found or could not be run. You might need to set the GST_PLUGIN_SCANNER environment variable if your setup is unusual. This should normally not be required though.

(remote-viewer:5041): GSpice-WARNING **: 12:37:49.409: Warning no automount-inhibiting implementation available

We ignore the warnings – and get our two Spice windows (on the KDE desktop of the laptop).

So far so good.

Let us move a complexly structured window (Firefox or the KDE settings window with a significant size (800×800)) around on the VM’s desktop in the Spice window of the laptop, with the help of fast mouse movements. Whilst we do this we measure the data transfer rates over the relevant NIC on the KVM server:

If you enlarge the picture you see peak rates of 85 MiB/s for data sent to the SSH-client.
In my network this has, fortunately, no major effect on the interaction between laptop and the VM – no major delay or lagging behind. And due to a fast switch my wife can nevertheless stream videos over a gateway system from the Internet. 🙂

How can we explain such transfer rates? Well, the window within the Spice screen I moved around had a size of around 800×800 px. Assume a 32 Bit color depth and a refresh rate of the pixel information on the virtual screen of around 30 times a second. You can do the calculation by yourself. The data fit well to the observations. Thus, we probably transfer changed image data of the window area on the VM’s desktop.

Reducing data transfer rates by SSH integrated (gzip) compression

We end the Spice session now on the laptop (by closing the Spice windows) and log out of the SSH session. Then we restart a new SSH-session with

<pre>myself@mylap:~/.ssh> ssh -XC -i ~/.ssh/id_rsa_x uvmb@mysrv
Enter passphrase for key '/home/myself/.ssh/id_rsa_x': 
Last login: Thu Mar 25 09:54:53 2021 from 192.168.2.22
Have a lot of fun...
uvmb@mysrv:~> 
uvmb@mysrv:~> remote-viewer spice+unix:///var/spicex/spice.socket &
[1] 5041
uvmb@mysrv:~> 

Note the “C“-option for the ssh-command!
Now the measured transfer rates on the KVM-server are less than 9 MiB/s.

However, I notice some lagging of the moved windows reaction to quick mouse cursor changes on the remote client. Not, that it affects normal working – but palpable. I cross checked by working with complex figures within Libreoffice Draw – absolutely no problems with the performance there. So, the reduced responsiveness is mainly due to operations which trigger the VM’s window manager and the re-drawing of the windows as well as the desktop within the Spice induced X-window on the client-system. In our case fast mouse movements to change the position of some application windows on the displayed VM desktop quickly and erratically ….

I see the lagging also with the Gnome desktop of the Kali guest – especially, when moving transparent terminal windows. In my opinion the lagging is even more pronounced. So, KDE 5 is not so bad after all 🙂 . And then its time for optimizing via desktop settings. Remember that you can switch off a compositor totally for the KDE desktop.

I also found that the decline of responsiveness with SSH data compression also depended somewhat on the number of opened Spice “displays” or “screens” and their sizes. Responsiveness is better with just one Spice window open on the remote system. In our SSH-based scenario responsiveness depends

  • on the number of virtual Spice displays,
  • on the size of the moved window,
  • on the complexity and to a minor degree also on transparency effects.

I could also see these dependencies for a “ssh -XC” when I exchanged the QXL device with a so called “virtio”-video-device.

Using a “virtio” video device

So far we have worked with the QXL device for a virtual graphics card device in the VM’s configuration. Let us try an alternative – namely a so called “virtio”-video-device. “virtio”-devices for virtual NICs and virtual storage devices enhance performance due to special interaction concepts with the real hardware; see the links at the bottom of this post for more information on the ideas behind virtio-drivers. Can we get a performance improvement in our scenario by a “virtio” device for the virtual graphics card?

Our configuration for the VM then, for example, looks like

   <graphics 
type='spice' keymap='de' defaultMode='insecure'>
      <listen type='socket' socket='/var/spicex/spice.socket'/>
      <image compression='off'/>
      <gl enable='no'/>
    </graphics>
    ...
    ...
    <video>
      <model type='virtio' heads='2' primary='yes'>
        <acceleration accel3d='yes'/>
      </model>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
    ...

You see that we can set multiple heads for a virtio video device, too. A big advantage is that we do not need any special memory settings as for the QXL device.

When you try this setting, you will found out that it works quite well, too. And there is a remarkable difference regarding data transfer rates:

The maximum rates for the same kind of window movements are now well below 48 MiB/s. For the same kind of fast movements of complex windows across the desktop surface in the Spice window.

Now, if you in addition use SSH compression (ssh -XC) you get the rates down to 8.2 MiB/sbut with only a slightly better responsiveness of windows to the mouse movement on the remote Spice window than for a QXL setup.

In my opinion a virtio-display device is something worth to experiment with (even without 3D acceleration).

Libreoffice Draw as a real world test case

Let us briefly compare data rates for something more realistic in daily work.

In the tests described below I firstly open Libreoffice [LO] Draw by a direct “ssh -X” call to the VM itself. Then I open LO Draw within the remotely displayed desktop of the VM based on a “SSH -X” connection to the KVM server. This means a major difference regarding the SSH connection and the data transfer requests!

Within LO Draw I use a sketch like the following

and, later on, move the green or violet figures very fast around in the LO frame with the mouse. Transparency included.

So, for a first test, let us open the VM’s LO Draw on my laptop MyLAP via a direct “ssh -X” command (without data compression!) directed to the VM:

<pre>myself@mylap:~/.ssh> ssh -X -i ~/.ssh/id_rsa_x myself@debianx
Enter passphrase for key '/home/myself/.ssh/id_rsa_x': 
Linux debianx 5.10.0-kali3-amd64 ......
......
Last login: Fri Mar 26 17:38:16 2021 from 192.168.2.22
...
myself@debianx:~> 
myself@debianx:~$ libreoffice --draw 

Note that “debianx” is now used as a host name! (The host name was chosen to be the same as the name of the VM in virt-manager; but the meaning in a network context, where “debianx” must be resolved to an IP, is now different. Note that the VM communicates to the outside world via a virtual network of the KVM host and routes defined on the VM and the KVM host directing data from the VM in the end over some NIC of the KVM host).

When moving the drawing’s figures around I measure data transfer rates on the relevant Ethernet device of the KVM-server:

Taking sent and received data together we have total rates around 25 MiB/s.

Now, in a second test, let us do something very different: We open Libreoffice Draw on the VM’s KDE desktop displayed in a Spice window, which in turn got transferred via SSH to the X11-service on my laptop:

And, again, we move the figures around very fast. The measured rates then are significantly smaller – below 4.4 MiB/s.

This proves the following statement which in turn justifies the whole Spice approach:

It may be more efficient to work remotely with a VM application on the VM’s desktop via Spice and a “SSH -X” connection to the KVM-server than requesting the graphical output of the VM’s application directly via “SSH -X” from the VM itself!

And what about sound?

We now turn to a topic which also deserves more documentation – namely the handling of sound with a remote solution like ours. We need Pulseaudio for a transfer of sound data from a VM (on the KVM/Qemu server) to the remote client system. Well, the very same Pulseaudio [PA] which often enough has ruined some of my nerves as a Linux user in the past 12 years or so. In combination with remote-viewer we simply cannot avoid it.

To be able to understand its configuration in a network with Opensuse Leap systems we must deal with the server properties of PA. See e.g. the following links for some explanation:
Free desktop Org documentation on Pulseaudio in a network
Archlinux documentation on PulseAudio

A Pulseaudio installation can work as a daemon-based service for other client-applications than the ones started locally during the desktop session of a user. Such clients can be applications started on other computers. PA’s client/server structure has network capabilities! To use PA in a network context some requirements must be fulfilled:

  • The module “module-native-protocol-tcp ” must be loaded. On a standard Opensuse Leap system this is the case; see the settings in the files “/etc/pulse/default.pa” and for a specific user in “~/.config/pulse/default.pa“.
  • For a direct connection between two PCs, as we need it for our present purpose, we can use a special TCP-port. The standard port is “4713“. For some first tests we will open this port for a directed transfer from the server to the client on local firewalls of the systems as well as on firewalls in between. But later we will rather integrate the port handling into our SSH tunnel.
  • The PA service must be told to accept remote connections over TCP. We can use the “paprefs” application for it.
  • We may require some form of authentication to grant access. We move this point to SSH by opening a remote tunnel – so we can forget about this point.

To get some information about
what is playing where during the next steps it is useful to have the applications “pavucontrol” (pulseaudio volume control) and “paman” (pulseaudio manager) running. You find the relevant packets in the standard Update Repository of your Leap distribution. The packet “qemu-audio-pa” should be installed, too, if it is not yet present on your system.

Where is sound of the VM played if we do nothing?

The funny thing about sound in our remote scenario with SSH and a Unix socket on the KVM host is the following:

When we start remote-viewer on the KVM-server in our scenario without any special measures for audio, we will see the graphical output on the remote client, but hear the sound on the speaker system of the server (if it has any). Well, in my test scenario the “server” has such an equipment.

well, let us start some sounds via the Spice windows on the client “MyLAP”. In the above images you saw that I had opened a directory with KDE sound files. Whilst we play them (e.g. with the parole player) we can at the same time have a look at the pavucontrol window on the KDE desktop of user “uvmb” on the server “MySRV”:

If you enlarge the image you see a PA-client there with the name “Remote Viewer”. This is not too astonishing as we had started remote-viewer on the KVM server and not on the remote laptop. And as a default remote-viewer interacts with the active PA on the system where remote-viewer itself is running:

Well this might be okay if the client and the server are in the same room. But if you had moved with your laptop into another room you, of course, would like to hear the sound on your laptop’s speakers. To achieve this we have to redirect the audio data stream of an application of the VM to a remote PA service.

How do we transfer sound from a SSH-server to the PA-system on the client during a SSH session?

I assume now that port 4713 is open on all firewalls. Still we have to prepare the PA-service on the remote client system – here on our laptop “MyLAP”.
For this purpose we open “paprefs” on MyLAP (NOT in the VM displayed in the Spice windows there, but in a standard terminal window of MyLAP’s desktop):

myself@mylap:~> paprefs

we turn to the tab “network server” and activate the following options:

Your laptop (the SSH- and Spice-client) is then able to work as a sound-server within the LAN.

Do not worry too much about the deactivated authentication. You can control in your firewall settings which system gets access – and later on we shall close port 4713 completely again for remote access by restrictive firewall rules. (If you really need authentication you must copy the cookie under “~/.config/pulse/cookie” from your laptop onto the server and uvmb’s folder structure.)

But now: How, do we tell an application started on the KVM-server to direct its audio output to the PA server on the laptop? Well, this is controlled by an environment variable “PULSE_SERVER”; see the documentation mentioned above about this.

You
can easily test this by opening a “ssh -X” connection from your remote system to an SSH server and redirect the audio output of an application like smplayer to the PA on your remote system. In my case:

<pre>myself@mylap:~/.ssh> ssh -X -i ~/.ssh/id_rsa_x uvmb@mysrv
Enter passphrase for key '/home/myself/.ssh/id_rsa_x': 
Last login: Thu Mar 25 09:54:53 2021 from 192.168.2.22
Have a lot of fun...
uvmb@mysrv:~> 
uvmb@mysrv:~> env PULSE_SERVER=192.168.2.22 smplayer & 
[1] 5041
uvmb@mysrv:~> 

Any sound played with smplayer is now handled by the PA on the laptop. See the screenshot from the laptop:

Now, we can of course do the same with our remote-viewer:

<pre>myself@mylap:~/.ssh> ssh -X -i ~/.ssh/id_rsa_x uvmb@mysrv
Enter passphrase for key '/home/myself/.ssh/id_rsa_x': 
Last login: Thu Mar 25 09:54:53 2021 from 192.168.2.22
Have a lot of fun...
uvmb@mysrv:~> 
uvmb@mysrv:~> env PULSE_SERVER=192.168.2.22 remote-viewer spice+unix:///var/spicex/spice.socket &
[1] 5041
uvmb@mysrv:~> 

You should hear any sound played with an audio application within the VM on the remote system (in my case on the laptop MyLAP):

Isn’t it fun?

Remote SSH tunnel and port forwarding for the transfer of audio data

Ok, we have a sound transfer – but not encrypted. This can – dependent on your audio applications – be a security hole. In addition we lack control over the users who may access our PA-server on the remote system. To cover both problems we are going now to make use of the full power of SSH. We open a reverse SSH tunnel with port forwarding from some arbitrarily chosen port on the KVM/Qemu server to port 4713 on the laptop:

<pre>myself@mylap:~/.ssh> ssh -X -R 44713:localhost:4713 -i ~/.ssh/id_rsa_x uvmb@mysrv
Enter passphrase for key '/home/myself/.ssh/id_rsa_x': 
Last login: .... from 192.168.2.22
Have a lot of fun...
uvmb@mysrv:~> 
uvmb@mysrv:~> env PULSE_SERVER=tcp:localhost:44713 remote-viewer spice+unix:///var/spicex/spice.socket &
[1] 5041
uvmb@mysrv:~> 

You see the difference? We direct the audio output of remote-viewer on the KVM-host to port 44713 – and SSH does the rest for us via port-forwarding (plus encryption). (Control question: Which system does “localhost” in the SSH statement refer to? The laptop or the KVM/Qemu server?)

The result of this sound redirection looks, of course, the same on pavucontrol on our remote client system as before.

We now can close the port 4713 by some suitable firewall rule on our client system for any external access. Due to SSH port forwarding we only access the port locally there. You can even pin it on the “lo”-device with the SSH command. Read about it on the Internet.

The additional overhead of the audio data transfer is minimal in comparison to the video data transfer triggered by window manager operations:

We speak about some 600 KiB/s for some stereo sound.

To make things complete –
here are the data transfer rates for high resolution Live TV video streaming from the VM on the KVM-server over “SSH -X” to the remote client (without data compression):

You see: Its Easter time! Old Hollywood movies are running on German TV …

Conclusion

The method to access the Spice console of a VM with remote-viewer and via a Unix socket locally on the KVM host enabled a first secure remote scenario by simply redirecting the graphical data stream from the KVM-server to a remote X-window service with “SSH -X”.
The combination with a virtio-video device proved to deliver a relatively small peak data transfer rate around 45 MiB/s for complex window operations requiring a fast redraw of major parts of the desktop in the remote Spice windows. Without SSH data compression we got a very good responsiveness of complex windows to fast movements induced by the mouse cursor on the remotely displayed desktop of the VM. We saw that we could reduce the resulting data transfer rates below 9 MiB/s by using SSH data compression. However, this had some negative impact on the felt responsiveness of operations triggering the window manager of the VM’s graphical desktop.
However, working with graphical applications like Libreoffice Draw on the remotely displayed desktop of the VM via Spice and SSH required substantially smaller transfer rates than in a scenario where we requested a display of the application by a direct “ssh-X” connection to the VM itself.
I have shown in addition that we can easily transfer the sound created by audio applications within the VM via a remote SSH tunnel and port forwarding to the Pulseaudio server on the remote client system.

In the next article of this series we are preparing a TLS based remote solution for accessing the Spice console of a VM.

Links

SSH with compression
https://www.xmodulo.com/how-to-speed-up-x11-forwarding-in-ssh.html?format=pdf

SSH with Pulseaudio
https://askubuntu.com/questions/371687/how-to-carry-audio-over-ssh

KVM/Qemu VMs with a multi-screen Spice console – III – local access with remote-viewer via a Unix socket

In the last article of this series

KVM/Qemu VMs with a multi-screen Spice console – II – local access with remote-viewer via a network port
KVM/Qemu VMs with a multi-screen Spice console – I – Overview over local and remote access methods

I discussed “remote-viewer” – a tool to access the graphical Spice console of a virtual machine [VM] on a KVM/Qemu host. Although remote-viewer is thought to be used over network connections, you can also use it locally on the virtualization host itself, e.g. in a desktop virtualization scenario.

To get an overview we first had a brief look at some central libvirt and qemu configuration files which control the interaction of Spice clients with the libvirtd daemonand/or the Qemu-emulator. We then defined a network port (e.g. 20001) in the Spice related entry of the VM’s XML configuration file. This file is evaluated when you start a Qemu VM with virsh or virt-manager. Afterward we could access the Spice console of the VM by entering

spice://localhost:20001

on a terminal in a graphical desktop session on the KVM host. If the host had an IP like 192.168.2.22

spice://192.168.2.22:20001

would in principle work, too. But a successful outcome may, of course, depend on local firewall settings for your network devices.

We verified that remote-viewer supports a multi-screen presentation of any major graphical Linux desktop started on the VM. Present versions of KDE and Gnome on a Kali/Debian/Opensuse guest automatically adapt to changes of the user’s Spice client windows (on the host’s desktop). XFCE, however, requires a manual configuration of the virtual screens with tools of the guest OS.

I also demonstrated that a Spice console session corresponds to a fragile “one seat” situation: Other local or remote users can kick us out of our Spice session at any time. We could at least protect us against unauthorized session switches by defining a password for the Spice console. So far, so good.

But: Local access via a network port is certainly not the fastest method for local user interaction with a VM: Each transaction triggers operations of a TCP network stack. Can we get around this?

Yes, we can – by working with a Unix socket on the VM host. This is the subject of this article. While we prepare a Spice socket configuration for remote-viewer we also answer the question which sockets the libvirtd daemon offers for its client.

We use our test VM “debianx” again, which has a Kali OS installed together with multiple desktops to choose from (Gnome, KDE, XFCE). The KVM/Qemu host is a Opensuse Leap 15.2 system with a KDE desktop.

Documentation? Not really …

I did not find any hints in the Opensuse documentation on virtualization of how to use remote-viewer with a Unix socket. Neither the man pages, nor other user-friendly descriptions of remote-viewer gave me a clue. I got a socket based approach to work after an accidental view into two discussions on the Internet plus a bit of trial and error. These are links to the discussions I referred to:

https://www.linuxquestions.org/questions/linux-virtualization-and-cloud-90/remote-viewer-spice-qemu-and-unix-domain-socket-how-to-connect-4175571914/
https://bugzilla.redhat.com/show_bug.cgi?id=1335832

You may find a description of socket based configurations for Spice also in articles on Virgl3D based rendering – a local socket based configuration is essential there.

Spice access via a socket

The first article of this series contains a schematic drawing which shows various access methods to the Spice console of a VM. However, aside TCP ports I had not displayed any Unix sockets there. The following picture gives you an idea how such a local alternative could look like:

You should not take the direct connections to the Spice console too literally. Of course, the real interaction occurs between remote-viewer and the Qemu-emulator.

In the drawing I also indicated that libvirt-based tools (as virt-manager, virt-viewer), which do not directly interact with the qemu-emulator, use a specific socket which is automatically created at a standard location on Opensuse Leap 15.x systems.

Off topic: What sockets are used by virt-manager and virt-viewer?

Actually, libvirtd exposes multiple sockets to libvirt clients – each for a specific purpose; see
https://libvirt.org/manpages/libvirtd.html
and
https://libvirt.org/daemons.html
for details.

Virt-manager has its own graphical console window. Select a running VM and simply choose the menu-point “Open” to open a Spice client window on your host.

Note: In contrast to remote-viewer and also virt-viewer, virt-manager does not allow you to open multiple “screen”windows.

In a terminal window we ask “netstat” to inform us about relevant active sockets; just for interest we also look into related directories:

MySRV:~ # netstat | grep libv
unix  3      [ ]         STREAM     CONNECTED     554391   /run/libvirt/libvirt-sock
unix  3      [ ]         STREAM     CONNECTED     513499   /run/libvirt/libvirt-sock
unix  3      [ ]         STREAM     CONNECTED     554599   /run/libvirt/libvirt-sock
unix  3      [ ]         STREAM     CONNECTED     515826   /var/lib/libvirt/qemu/domain-1-debianx/monitor.sock
unix  3      [ ]         STREAM     CONNECTED     513581   /run/libvirt/libvirt-sock
MySRV:~ # 
MySRV:~ # la /run/libvirt/ | grep sock
srw-------  1 root root    0 Mar  9 17:48 libvirt-admin-sock
srw-rw-rw-  1 root root    0 Mar  9 17:48 libvirt-sock
srw-rw-rw-  1 root root    0 Mar  9 17:48 libvirt-sock-ro
srw-------  1 root root    0 Mar  9 17:48 virtlockd-sock
srw-------  1 root root    0 Mar  9 17:48 virtlogd-admin-sock
srw-------  1 root root    0 Mar  9 17:48 virtlogd-sock
MySRV:~ #
MySRV:~ # la /var/lib/libvirt/qemu/ 
total 44
drwxr-x--- 10 qemu qemu 4096 Mar  9 17:48 .
drwxr-xr-x 11 root root 4096 Oct 26 11:01 ..
drwxr-xr-x  3 qemu qemu 4096 Apr  2  2017 channel
drwxr-xr-x  2 qemu qemu 4096 Nov 16 17:56 checkpoint
drwxr-x---  2 qemu qemu 4096 Mar  9 17:48 domain-1-debianx
drwxr-xr-x  2 qemu qemu 4096 Apr  2  2017 dump
drwxr-xr-x  2 qemu qemu 4096 Apr  2  2017 nvram
drwxr-xr-x  3 qemu qemu 4096 Sep 10  2018 ram
drwxr-xr-x  2 qemu qemu 4096 Apr  2  2017 save
drwxr-xr-x  2 qemu qemu 4096 Apr  2  2017 snapshot
MySRV:~ #
MySRV:~ # la /var/lib/libvirt/qemu/domain-1-debianx/ 
total 20
drwxr-x---  2 qemu qemu 4096 Mar  9 17:48 .
ndrwxr-x--- 10 qemu qemu 4096 Mar  9 17:48 ..
-rw-------  1 qemu qemu   32 Mar  9 17:48 master-key.aes
srwxrwxr-x  1 root root    0 Mar  9 17:48 monitor.sock
MySRV:~ # 

By the way: A nice tool to list sockets is “ss“; try “ss -axeo | grep libv” or

ss -a –unix -p | grep virt

for instance.

Some sockets obviously have very restrictive rights settings. However, the rights situation seems to be totally relaxed for two of the sockets in “/run/libvirt”. As we shall see in a minute these sockets are the relevant ones for Spice clients using libvirt.

Readers of the last article may have guessed that we configure access rights to these sockets in the file “/etc/libvirt/libvirtd.conf”. Sorry, but on a standard Opensuse Leap system this is wrong. Instead the sockets are created by systemd during the start of the libvirtd.service. See the respective files libvirtd.service, libvirtd.socket, libvirtd-ro.socket in the folder “/usr/lib/systemd/system”:

MySRV:/usr/lib/systemd/system # cat libvirtd.service 
[Unit]
Description=Virtualization daemon
Requires=virtlogd.socket
Requires=virtlockd.socket
# Use Wants instead of Requires so that users
# can disable these three .socket units to revert
# to a traditional non-activation deployment setup
Wants=libvirtd.socket
Wants=libvirtd-ro.socket
Wants=libvirtd-admin.socket
Wants=systemd-machined.service
.....

and e.g.

MySRV:/usr/lib/systemd/system # cat libvirtd-ro.socket
[Unit]
Description=Libvirt local read-only socket
Before=libvirtd.service
BindsTo=libvirtd.socket
After=libvirtd.socket

[Socket]
# The directory must match the /etc/libvirt/libvirtd.conf unix_sock_dir setting
# when using systemd version < 227
ListenStream=/run/libvirt/libvirt-sock-ro
Service=libvirtd.service
SocketMode=0666

[Install]
WantedBy=sockets.target

A standard rights setting of “666” is used. You could change this in a special local file under “/etc/systemd/”. We shall return to respective settings in another article.

Virsh and virt-manager require a (rw) socket which allows for VM re-configuration, i.e. writing operations to the Qemu-emulator configuration data for a VM. This socket is “/run/libvirt/libvirt-sock“.

Regarding access to a Spice console, however, a so called “ro”-socket, namely “/run/libvirt/libvirt-sock-ro“, is sufficient. You can verify this by trying

virt-viewer -c qemu:///system?socket=/run/libvirt/libvirt-sock-ro

The “ro” refers to a denial of configuration writing and changes of Qemu-process parameters controlling the VM. It is NOT directly related to the Linux access rights of the socket itself. Actually, the socket is a “stream” socket; this already implies that the user needs write access to it. Which is given in an Opensuse Leap system. See the generous “rw-rw-rw-“-setting in the listings above!

This raises the question:
What restricts the access to these libvirt standard sockets at all on an Opensuse Leap system?

Answer:
Its a policy setting; see the Opensuse documentation in “Virtualization guide – Connecting and authorizing“. More on this topic in another article.

How would we specify an URI, which points to a Unix-socket, for remote-viewer?

To force remote-viewer to use a Unix socket we first have to find out how we specify an URI pointing to such a socket. Well, the first of the named articles above together with the man-pages for remote-viewer gives us an idea. The right form for a local access is:

remote-viewer -v spice+unix://Path-To-Socket

Note that a path down from the root ”
/” of the Linux directory tree will lead to three “///” !

You cannot use the libvirtd-sockets with remote-viewer!

Can we use the sockets provided by libvirtd with remote-viewer? The answer is: No. More precisely: I do not know how, if it should work against my expectations. We use the above recipe and try:

MySRV:~ # remote-viewer -v  spice+unix:///var/lib/libvirt/qemu/domain-1-debianx/monitor.sock
Guest (null) has a spice display
Opening connection to display at spice+unix:///var/lib/libvirt/qemu/domain-1-debianx/monitor.sock

With the result:

Something equally negative happens with

MySRV:~ # remote-viewer -v spice+unix:///run/libvirt/libvirt-sock
Guest (null) has a spice display
Opening connection to display at spice+unix:///run/libvirt/libvirt-sock

(remote-viewer:22055): GSpice-WARNING **: 19:29:01.691: incomplete link header (-104/16)

We are stuck. Well, it would have been too simple. And it would have been strange, too, because remote-viewer was made to directly access Qemu. So, the next logical question is:

How can we tell Qemu to provide a suitable Unix socket for the Spice console?

Required settings in the XML domain file for the VM => specify a socket for the Spice item

We can use the information provided in the Red Hat bug tracker mentioned above. We guess that we can change the Spice settings according to the following pattern in the VMs’ domain definition file “/etc/libvirt/qemu/debianx.xml”:

    
    <graphics type='spice' autoport='no' keymap='de' defaultMode='insecure'>
      <listen type='socket' socket='/tmp/spice.socket'/>
      <image compression='off'/>
      <gl enable='no'/>
    </graphics>

You see that I choose the “/tmp”-directory to create a socket. The directory must of course be writeable. For whom? And which access rights will our aspired socket get?

It is reasonable to assume that we will see the rights of the specific system user, which is used to run Qemu processes for VMs. We already saw in the last article that this is the user named “qemu” (single member of group “qemu”) on a standard Opensuse system.

OK, let us see whether we can start our “debianx” test VM with this new Spice item in its XML configuration.

No problem! To check whether the VM really is operational we start virt-manager’s integrated Spice console window and log into Kali’s KDE desktop:

No problem there either.
Note the settings for the Spice window – the last menu point must be checked to guarantee an automatic adaption of the VM’s desktop to the dimensions of the Spice console window.

If you now would use

virt-viewer -c qemu:///system?socket=/run/libvirt/libvirt-sock-ro

again, virt-manager’s Spice window would be closed (one seat!) and a virt-viewer window would open (NOT a remote-viewer window; see the top bar of the window below).


But all of this is no proof that a new socket has been created. virt-manager and virt-viewer use the sockets “/run/libvirt/libvirt-sock” and “/run/libvirt/libvirt-sock-ro” (to connect to libvirtd) – as we already know. But a look into the “/tmp”-folder

MySRV:~ # ls -lisa /tmp | grep spice
1452545    0 srwxrwxr-x   1 qemu  qemu        0 Mar 13 14:31 spice.socket
MySRV:~ # 

actually shows that we indeed have a new socket. We get an additional confirmation by netstat:

MySRV:~ # netstat -ax | grep spice
unix  2      [ ACC ]     STREAM     LISTENING     137989   /tmp/spice.socket
MySRV:~ # 

Remote-viewer with a local Unix socket

Let us use the prepared socket as user “uvma”. Unfortunately, a first trial with

remote-viewer spice+unix:///tmp/spice.socket

fails due to insufficient access rights. Obviously, the user “uvma” needs write rights on the specified “stream” socket.

The most simple solution for the moment is to add the user “uvma”, which we already put into a privileged group “libvirt” in the last article, to the group “qemu”, too. (This is probably not the best solution. We come back to security aspects later.) But for the time being we enter (as root)

usermod -a -G qemu uvma

As user “uvma” we afterward log out and in again to our desktop session on the host. In a terminal window we then enter (as user “uvma”)

remote-viewer spice+unix:///tmp/spice.socket

It works! A new Spice client window for remote-viewer is opened. I added one more “screen” and also started some applications to see, if we can really interact with the VM – which is indeed the case. Even sound works (if pulseaudio is used on the host):

Great!

Security considerations

Besides an improved performance, working with a Unix socket avoids opening a network port and related potential security issues. But, as we saw, we need some special rights for such a scenario. Which also has security implications ….

Regarding this point I do not think that putting a user into the “qemu”-group is a good idea. Well, you could argue that our user “uvma” is already privileged regarding VMs. Yes, true enough. But we may change this in the future and separate users which can use virt-manager from others which use remote-viewer for a specific VM: The user who gets the right to open the Spice console may be different from the special user which is allowed to start the VM.

Another problem is that a user being member of the qemu group has almost the same rights as the “qemu”-user itself. But, in contrast to the special user “qemu” on an Opensuse Leap system, a normal user as “uvma” has a login-shell:

MySRV:/etc/libvirt/qemu # cat /etc/passwd | grep qemu
qemu:x:484:483:qemu user::/sbin/nologin
MySRV:/etc/libvirt/qemu # cat /etc/passwd | grep uvma
uvma:x:1025:100:uvma:/home/uvma:/bin/bash

“uvma” needs a login-shell as
he/she shall work with remote-viewer in his/her desktop session on the host. So, if this user gets hacked (e.g. via a browser bug) this would have consequences for all VMs on the host.

We can at least confine a selected user’s impact to a specific VM. Let us take a user “uvmb”. We want to allow this user to access our test-VM “debianx” locally via a socket – but only this VM!

For this purpose we create a special group “spicex” and add both “qemu”, “uvma” and “uvmb” to this group.

usermod -a -G spicex uvmb
usermod -a -G spicex uvma
gpasswd -d uvma qemu

We also remove user “uvma” from the “qemu”-group.

Then we create a special directory “/var/spice/spicex“. You can, of course, choose a different path. We set the group of this folder to “spicex”. Then we set the “s”-flag on the group and use ACLs to enforce a default group for the user and the group with certain rights on an files created in this folder.

chown qemu.spicex /var/spice/spicex
chmod g+s /var/spice/spicex
setfacl -dm u:qemu:rwx,g:spicex:rwx,other::--- /var/spice/spicex

In addition we stop our VM and change its XML configuration to

    <graphics type='spice' autoport='no' keymap='de' defaultMode='insecure'>
      <listen type='socket' socket='/var/spice/spicex/spice.socket'/>
      <image compression='off'/>
      <gl enable='no'/>
    </graphics>

Afterward we restart the libvirtd-daemon. That’s it. Te next time, you start your VM by virt-manager as “uvma” you get something like

MySRV:/var/spice/spicex # la
total 12
drwxrws---+ 2 qemu spicex 4096 Mar 17 19:26 .
drwxr-xr-x  9 root root   4096 Mar 15 16:32 ..
srwxrwx---+ 1 qemu spicex    0 Mar 17 19:26 spice.socket

Now, you change to user “uvmb” by logging out and starting a new X-/KDE-session on the host or by just entering “su – uvmb” in a terminal. We login as “uvmb” and try

uvmb@MySRV:~> remote-viewer -v  spice+unix:///var/spicex/spice.socket

This should work; if you stayed in the KDE session of user “uvma” you probably get some error messages regarding audio and a denied pulseaudio access. But the Spice graphics should be OK. Similar precaution measures should be taken for other VMs. ACLs give you enough flexibility to control VM-specific access. Now, you could remove “uvma” from group spicex – and get some kind of tool access segregation. It would not make much sense however as long as uvma still is privileged by being a member of the libvirt group; uvma still can open the Spice console at any time via libvirtd and its special sockets. Regard “uvma” as a VM administrator.

Summary:
The configuration of a VM with a Unix socket has the advantage that we can control the Spice session access, and thereby a potential session switch to another user, a bit better. We restrict the access to libvirtd to selected members of an administrative group and the access to the socket to a selected user of the VM. Though it does not hurt to have a password in place in addition …

Off topic hint 1: Adjustment of Spice screen positions relative to each other on the guest system

When you open a second Spice windows with remote-viewer it is not guaranteed that the guest’s desktop system initially places these virtual Spice screens seamlessly side-a-side. But both KDE, Gnome and XFCE provide graphical tools to adjust the geometrical relation of multiple screens. With the help of these tools you can specify how relative corner positions of the virtual screens are handled. You only have to do this once, afterwards you can move your Spice windows around on the host’s desktop as you like :

Relative positioning of two virtual Spice screens with the monitor tool of the guest’s KDE desktop

Independent positions of the Spice windows on the KDE desktop of the KVM/Qemu host

Even resizing of the Spice windows won’t disturb the relative position definition of the virtual screen corners in the guest.

Off topic hint 2: Workaround for faulty Clipboard interaction between the KDE sessions on the host and in the Qemu guest VM

I noticed a strange dis-coupling between the functionality of the clipboard of KDE main session on the host and the clipboard of guest VM’s KDE session. Due to the spice-vdagent they should work seamlessly together. It looked OK in the beginning for the exchange of data between the host and the VM. However, when I tried to copy between two terminal windows on the host I got error message in the terminal from which I started the guest VM:

Spice-CRITICAL **: 14:46:03.424: clipboard_request: assertion 's->clipboard_by_guest[selection] == FALSE' failed

And no data were copied! This disappeared as soon as I activated the “system” tray in the control bar of the guest’s KDE desktop, activated the clipboard entry there and adjusted the clipboard settings there to those of the KDE session on the host.

Conclusion

Remote-viewer works very well with a local Unix socket instead of a TCP socket as the interface to the Qemu-emulator process of the VM. A socket based local access scenario to a Spice console can easily be configured via respective settings in the XML-definition file of a VM. However, to improve security you should avoid adding a standard user who wants to use remote-viewer to the “qemu” group. Involving ACL rights will help you to confine users to access the Spice console of specific VMs via placing a socket into a specific directory and controlling access to it and its contents.

Note by the way that using Unix sockets locally on the host also allows for a new remote-access scenario via SSH. Such a scenario could even be more efficient than a TLS encrypted standard connection over a network port in a LAN. Much to discover! Stay tuned. In the next article

KVM/Qemu VMs with a multi-screen Spice console – IV – remote access via SSH, remote-viewer and a Unix socket

I will show you how to use remote-viewer via SSH.

Links

The ss-command to list up sockets
https://www.networkworld.com/article/3327557/using-the-linux-ss-command-to-examine-network-and-socket-connections.html

lbvirt and authentication on Opensuse
https://documentation.suse.com/sles/15-SP1/html/SLES-all/cha-libvirt-connect.html

KVM/Qemu VMs with a multi-screen Spice console – II – local access with remote-viewer via a network port

In my first article in this series on local and remote connections to the Spice console of a KVM/Qemu virtual machine [VM] I have given you an overview over some major options. See the central drawing in

KVM/qemu with the graphical multi-screen Spice console – I – Overview over local and remote access methods

In this post we explore a part of the drawing’s left side – namely a local connection with the remote-viewer client over a network-port and the “lo”-device. Local means that we access the Spice console with a Spice client in a desktop session on the KVM/Qemu host.

You can find some basic information on “remote-viewer” here.

Note: “remote-viewer” supports VNC, too, but we ignore this ability in this series.

A local scenario with remote-viewer on a KVM/Qemu host corresponds to desktop virtualization – though done with a remote tool. Such an approach can become a bit improper, because setting up ports for potential remote network connections always has security implications. This is one of the reasons why I actually want to discuss two different local access methods which can be realized with remote-viewer:

  • Method 1: Access via a network port (TCP socket). This standard method is well documented on the Internet both regarding the VM’s setup (e.g. with virt-manager) and the usage of remote-viewer (see the man pages). The network based scenario is also depicted in my drawing.
  • Method 2: Access via a local Unix socket. This method is not documented so well – neither regarding the VM’s setup (e.g. with virt-manager) and not at all by the man pages for remote-viewer.

You may complain now that I never indicated anything in the above drawing about a pure Unix socket! Well, at the time of writing the first article I did not even know that remote-viewer worked over a pure Unix socket and how one can configure the VM for a Unix socket. I will discuss the more common “Method 1” in this present article first. “Method 2” will be the subject of the next post – and then I will provide an update of the drawing. Talking about sockets: When you think a bit about it – Unix sockets must already be an ingredient of the local interaction of libvirt-tools with qemu, too, ….

Below I will discuss a set up for “Method 1” which is totally insecure. But it can be realized in a very simple way and is directly supported by virt-manager for the VM setup. Thus, it will give us a first working example without major efforts for creating TLS certificates. But, you are/were warned:

Disclaimer:
The test-configurations I discuss in this and the next articles of this series may lead to major security risks. Such configurations should NOT be used in productive multi-user and/or network environments without carefully crafted protection methods (outside the qemu-configuration) – as local firewall protection, system policies, etc. I take no responsibility whatever for an improper usage of the ideas presented in this article
series.

Assumptions for test scenarios

  • The KVM/Qemu host in this article series is an Opensuse Leap 15.2 host. Most of the prescriptions discussed may work with some minor modifications also on other Linux distributions. But you must look up documentations and manuals …
  • I assume that you already have set up a KVM/Qemu based test-VM with virsh or virt-manager. Let us call the VM “debianx“. Actually, it is a Kali system in my case. (Most of the discussed measures will work on guests with a Debian OS, too.)
  • On our Opensuse KVM host we find a XML-definition file “debianx.xml” for a libvirt domain (i.e. a VM) below the directory “/etc/libvirt/qemu/“, i.e. “/etc/libvirt/qemu/debianx.xml”. It has a typical XML structure and can be edited directly if required.
  • The KVM host itself has a FQDN of “MySRV.mydomain.de“. (MySRV is partiall writtenin big letters to remind you that you have to replace it by your own domain.
  • The user on the KVM host, who invokes remote-viewer to access the VM, has a name “uvma“. We will later add him to a group “libvirt” which gets access rights to libvirt tools. We shall also work with a different user “uvmb” who is a member of the group “users”, only. Both users work on a graphical desktop on the KVM/Qemu host (!) – let us say a KDE desktop. These users open one or more Spice client windows on the host’s desktop to display graphical desktops of the KVM/Qemu guest VMs – as if the windows were screens of the VM.

We must carefully distinguish between the (KDE) desktop used by “uvma” on the KVM host and the desktop of the guest VM:

The Spice client windows on the KVM host’s (or later on independent remote systems) desktop present full graphical desktops (Gnome, XFCE, KDE …) of the VM and allow for interactive working with the VM. The desktop used on the host can, of course, be of a different type than the one used on the guest.

I will use this first practical article also

  • to have a brief look at two basic configuration files for libvirtd and qemu settings,
  • to discuss some basic setup options for a Qemu VM,
  • to check the multi-screen ability of remote-viewer
  • and to prove the “one-seat” situation for the Spice console.

I restrict my hints regarding the guest configuration to Kali/Debian or Opensuse Leap guest systems on the VM. I provide images for a Kali guest system, only. I do not have time for more …

Make backups

Before you start any experiments you should make a backup of the directories “/etc/libvirt” and “/etc/pki” of your host – and in doubt also of the disk-files (or real partitions) of your existing VMs. You should also experiment with a non-productive test VM, only.

Basic security considerations

(In-) Security is always a bit relative. Let us consider briefly, what we intend to do with respect to “Method 1”:

With the first method we define a network port for unencrypted connections without authentication.

In principle the port can be used by anyone having access to your network or anyone present on your PC. Such a configuration is therefore only reasonable for desktop virtualization

  • if you really are alone on your PC
  • AND if you have a local firewall preventing access to the port from any other system AND if there is a local policy restricting access to the Qemu-hypervisor or Spice-clients.

nOtherwise it opens a much too big attack surface. Remember: Anyone being able to use the network port can kick you off your Spice console session seat, remotely, locally and also when you are already logged into the guest OS. And:

All data transfer over any kind of network device (lo, ethernet, virtual devices on the host, …) occurs unencrypted. Other users on your machine (legal users, e.g. active via ssh, or attackers) may with some privilege escalation be able to read it.

Access to the Spice console itself can, however, be restricted to users who know a password. At the end of this article we will add such a simple password to our configuration to get at least some basic protection against kicking you out of a Spice console session.

Preparational step 1: Settings in “/etc/libvirt/qemu.conf” and the integration of Spice with Qemu

As mentioned in the last article, Spice is fully integrated with the Qemu-emulator. So, it will not surprise you that we can modify some general properties of connections to a VM’s Spice console by parameter settings in a configuration file for Qemu. The relevant file in the libvirt-dominated virtualization environment of Opensuse Leap 15.2 is

/etc/libvirt/qemu.conf“.

Readers of my last article may ask now: Why do we need to configure the Qemu-driver of libvirt at all, when we access the Spice console with remote-viewer directly via Qemu ? I.e., without passing a libvirt-layer? As depicted in the drawing?

Answer: Probably you and me start KVM/Qemu based VMs through “virsh” or “virt-manager“, i.e. libvirt components. Then libvirt drivers which are responsible to start the VMs according to its setting profile must know what we expect from the Qemu emulator. If you worked directly with the qemu-emulator (by calling “/usr/bin/qemu-x86_64”) you would have to specify a lot of options to control the outcome! Some sections below you will find an example. Libvirt-programs only automate this process.

“qemu.conf” allows for general default settings of a variety of qemu-parameters. Some of them can, however, be overwritten by VM-specific settings; see the next section. When you scroll through the file you come to a major section which contains Spice parameters. For an easy beginning of our experiments we set some selected parameters to the following values:

 
#spice_listen = "0.0.0.0" # just leave it as it is 
# .... 
spice_tls = 0  # This corresponds to a deactivation of TLS and a INSECURE configuration!
spice_tls_x509_cert_dir = "/etc/pki/libvirt-spice"
# .... 
# just leave the next settings as it is - it creates a socket at  "/var/lib/libvirt/qemu/domain-1-debianx/monitor.sock"
#spice_auto_unix_socket = 1  
spice_sasl = 0

Our first setting deactivates TLS. This is reasonable as long a we have not created valid TLS server certificates and encryption keys. But we can already define a default directory into which we later place such a certificate and key files. We also deactivate any SASL authentication support for the time being. (Actually, even if you left it at the default value of “1” it would not help you much – as on Opensuse systems a required file “/etc/sasl2/qemu.conf” is missing, yet. As standard SASL encryption methods are insecure today, SASL activation makes sense in combination with TLS only.

General security precautions in “/etc/libvirt/qemu.conf”
Talking about security: On an Opensuse system with activated “apparmor” you could/should set the following parameters in “/etc/libvirt/qemu.conf”:

 
security_driver = "apparmor"
security_default_confined = 1

to confine VMs.

Note: If “apparmor” is deactivated for some reason you will after these settings not be able to use virt-manager or virsh.
You can check the status of apparmor via “rcapparmor status” or systemctl status apparmor”.
(Off topic: Those interested in process separation should also have a look at cgroup-settings for the VMs. I would not change the basic settings, if you do not know exactly what you are doing. But folks trying to experiment with “virgl3D” may need to add “/dev/dri/renderD128” to the device list for ACLs.)

Preparational step A: A brief look a “/etc/libvirt/libvirtd.conf” – allow a selected standard user to use virt-manger or virsh

As we are within the folder “/etc/libvirt”, we take the chance to very briefly look at another configuration file, which will become more interesting in later articles:

/etc/libvirt/libvirtd.conf

Among other things this file contains a variety of parameters which control the access to libvirt tools via Unix sockets or TCP-sockets – with and without TLS and/or some form of authentication. This is of no direct importance for what we presently are doing with remote-viewer – as we access Spice console directly via qemu, i.e. without a libvirt-layer. However, for convenience reasons you should nevertheless be able to use virt-manager or virsh. If you do not want to work as root all the time you, i.e. he normal user “uvma”, need(s) special access rights to access Unix sockets which are automatically opened by libvirtd. How can this be achieved on an Opensuse Leap system?

You can configure a special user-group (e.g. a group named “libvirt”) to get access to virt-manager. You can do this in a section named “UNIX socket access controls”. The instructions in Opensuse’s documentation on virtualization (see: Connections and authorization and section 9.1.1.1 therein) will help you with this. Afterwards you must of course add your selected and trusted user (here: “uvma”) to the defined group.

Note: The libvirtd-process is nevertheless run by the user “root” and not with the rights of the standard user (here “uvma”). The group just allows for a kind of sudo execution. Note also that the central sockets by which libvirt-clients connect to the libvirtd-daemon are created by systemd.

By the way – who is the user for qemu-processes on an Opensuse Leap system?
On an Opensuse there is a special user “qemu” which is used to run the Qemu-emulator processes for VMs. We also find a related group “qemu”. User and group have special rights regarding aes-keys for potential credential encryption related to a VM. The user and its group also define the access right to special Unix sockets generated directly by the Qemu emulator and not by libvirtd. We shall request such a Unix socket from Qemu in the next article.

On other operative systems you may find a different pre-configured group for libvirt access rights. In addition the standard qemu-user may have a different name. For Debian and derivatives you find related information at the following links:
whats-the-purpose-of-kvm-libvirt-and-libvirt-qemu-groups-in-linux,
install-configure-kvm-debian-10-buster,
libvirt_qemu_kvm_debian .

Preparational step B: Restart libvirtd or reload its configuration after changes to qemu.conf, livirtd.conf or changes to XML-definition files for VMs

Changes of the file “/etc/libvirt/qemu.conf” or “/etc/libvirt/libvird.conf” require that the libvirtd daemon is restarted or forced to reload its configuration. The same is true for any changes of
XML-definition files for VMs located in “/etc/lbvirt/qemu/”. (We will change such files later on). According to the man page sending a SIGHUP signal to the daemon will enforce a reload of the configuration. You can indirectly achieve this by the commands

rclibvirtd reload [on Opensuse systems)
or
systemctl reload libvirtd [any system with systemd]

But: Any libvirt or qemu changes will NOT affect already running VMs. You have to stop them, then restart libvirtd, reload the daemon’s configuration and restart the VMs again.

Preparational step C: Configure the VM to use a Spice-console – and some other devices

Ok, let us prepare our VM for “Method 1”. As we are in a libvirt environment we could use virt-manager to perform the required Spice configuration (see the image in the first article) . But we can also directly edit the XML configuration file “/etc/libvirt/qemu/debianx.xml” – assuming that you already have a working configuration for your VM. You need to be root to edit the files directly. See the restrictive access rights of the domain definition files

-rw------- 1 root root   4758 Mar  8 13:33 debianx.xml

By the way: A detailed description of possible parameter settings is provided at https://libvirt.org/formatdomain.html. Search for Spice and qxl …..

Regarding “Method 1” I use the following settings. The listing below only gives you an excerpt of the XML domain file, but it contains the particularly relevant settings for “graphics” (can be looked upon as a display device) and “video” (an be interpreted as a kind of virtual graphics card):

Excerpts from a libvirt domain definition XML file

   
   <interface type='network'>
      <mac address='52:54:00:93:38:4c'/>
      <source network='os'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
   ...
   <graphics type='spice' port='20001' autoport='no' listen='0.0.0.0' keymap='de' >    
      <listen type='address' address='0.0.0.0'/>
      <image compression='off'/>
    </graphics>
   ... 
    <sound model='ich6'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </sound>
    ...
    <video>
      <model type='qxl' ram='262144' vram='65536' vram64='2097152' vgamem='65536' heads='4' primary='yes'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
...

Parameters which affect general qemu-related properties (as e.g. the “listen”-settings) will overwrite the settings in “qemu.conf”. The choice of the PCI slot numbers may be different for your guest.

You see that I defined a network (!) port for the VM by which we can access the Spice console data stream directly. I have changed this port from the default “5900” to “20001”.

You should be aware of the fact that this sets a real network port on the KVM host – i.e. a network stack is invoked when accessing the Spice console. As indicated above we can avoid the superfluous network operations by directly working with a Unix socket (Method 2), but this is the topic of the next forthcoming article.

Regarding network port definitions for a Spice console three rules apply:

  • Each of the VMs defined requires its own individual port !
  • Firewalls between the client and the VM have to be opened for this port. This includes local firewalls on the VM, on the KVM host (with rules that may apply to virtual bridges, on the client system and on any network
    components in between.
  • A TLS port has later to be configured in addition if you deactivated the “autoport” functionality – as we have done in the example above. I shall describe how to set the TLS port in a forthcoming article.)

The individual port definitions already imply the provision of a URI with port specification when starting remote-viewer (see below).

Let me briefly comment on the QXL-settings:

The QXL configuration shown above allows for 4 so called “heads” (or connectors) of the virtual graphics device. These heads support up to 4 virtual screens, if requested by the Spice-client. Note that the situation is different from real hardware consoles:
The (Spice) client (here remote-viewer) defines the number of screens attached to the VM’s console by a number of Spice client windows opened on the user’s desktop on the KVM host. The dimensions of these Spice client windows determine the dimensional capabilities of the virtual “screens”.

How the virtual screen resolution is handled afterwards may depend on the user’s own desktop resolution (on the KVM host or a remote system) AND the display settings of the VM’s guest system’s own tools for screen management. Today these are typically tools integrated into the guest’s graphical desktop (KDE, Gnome, XFCE) itself. Present Gnome and KDE5 desktops on the VM’s guest Linux system automatically adapt to the virtual display dimensions – i.e. the Spice window dimensions. But a XFCE desktop on the guest may behave differently; see below.

A short note also on the network settings for our test VM:
A virtual machine will normally be associated with a certain type of virtual network. At least if you want to use it for the provision of services or other network or Internet dependent tasks. You can configure virtual networks with virt-manager (menu “edit” >> “connection details”); but you must be root to do this:

In my case I prefer a separate virtual network for which we need routing on the KVM host. This allows us to configure restrictive firewall rules – e.g, with netfilter on the host. It even allows for the setup of virtual VLANs – a topic which I have extensively covered in other article series in this blog. And when required we just can stop routing on the host.

Guest requirements
Note that the QXL-configuration must also be supported on the VM guest itself: You need a qxl-video-driver there – and it is useful to also have the so called spice-vdagent active (see the my referenced series about a qxl-setup in the last article). On the guest system this requires

  • the installation of the “spice-vdagent” package and the activation of the “spice-vdagent.service” (both on Debian/Kali and Opensuse guest systems) ,
  • the installation of the packet “xserver-xorg-video-qxl” on a Debian/Kali-guest or “xf86-video-qxl” on an Opensuse guest

Present Debian, Kali or Opensuse operative system on the KVM/Qemu guest VM should afterward automatically recognize the QXL-video-device and load the correct driver (via systemd/udev).
Regarding the (virtual) network device on the VM itself you must use the guest system’s tools for the configuration of NICs and of routes.

Preparational step D: Starting the VM – and “Where do I find logs for my VM”?

I assume that you as user “uvma” are logged in to a graphical desktop session on your KVM host “MySRV”. If you are not
yet a member of the libvirt-privileged group, you may need to use sudo for the next step. On a terminal window you then enter “virt-manager &”, select our VM “debianx” and boot it.

If you look at the process list of your KVM host you may find something like:

qemu     17662  5.5  6.8 15477660 4486180 ?    Sl   18:11   2:29 /usr/bin/qemu-system-x86_64 -machine accel=kvm -name guest=debianx,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-1-debianx/master-key.aes -machine pc-i440fx-2.9,accel=kvm,usb=off,vmport=off,dump-guest-core=off -cpu Skylake-Client -m 8192 -overcommit mem-lock=off -smp 3,sockets=3,cores=1,threads=1 -uuid 789498d2-e025-4f8e-b255-5a3ac0f9c965 -no-user-config -nodefaults -chardev socket,id=charmonitor,fd=33,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-hpet -no-shutdown -global PIIX4_PM.disable_s3=1 -global PIIX4_PM.disable_s4=1 -boot strict=on -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x5.0x7 -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x5 -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x5.0x1 -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x5.0x2 -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 -blockdev {"driver":"file","filename":"/virt/debs/debianx.qcow2","node-name":"libvirt-2-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"} -blockdev {"node-name":"libvirt-2-format","read-only":false,"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":"libvirt-2-storage","backing":null} -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x7,drive=libvirt-2-format,id=virtio-disk0,bootindex=1,write-cache=on -device ide-cd,bus=ide.0,unit=0,id=ide0-0-0 -netdev tap,fd=35,id=hostnet0,vhost=on,vhostfd=36 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:93:38:4c,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -chardev socket,id=charchannel0,fd=37,server,nowait -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=org.qemu.guest_agent.0 -chardev spicevmc,id=charchannel1,name=vdagent -device virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel1,id=channel1,name=com.redhat.spice.0 -device usb-tablet,id=input0,bus=usb.0,port=1 -spice port=20001,addr=0.0.0.0,disable-ticketing,plaintext-channel=default,image-compression=off,seamless-migration=on -k de -device qxl-vga,id=video0,ram_size=268435456,vram_size=67108864,vram64_size_mb=2048,vgamem_mb=64,max_outputs=4,bus=pci.0,addr=0x2 -device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -chardev spicevmc,id=charredir0,name=usbredir -device usb-redir,chardev=charredir0,id=redir0,bus=usb.0,port=2 -chardev spicevmc,id=charredir1,name=usbredir -device usb-redir,chardev=charredir1,id=redir1,bus=usb.0,port=3 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x8 -object rng-random,id=objrng0,filename=/dev/urandom -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pci.0,addr=0x9 -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny -msg timestamp=on

 
You see that the user “qemu” started the qemu-process by calling “/usr/bin/qemu-system-x86_64” and adding a bunch of parameters. You may identify some parameters which stem from the settings in libvirt’s XML definition file for our special the VM (or “domain”).

Afterwards, have a look at connections with
netstat on the host; you should see that something (qemu) listens on the defined Spice port of the VM:

MySRV:/etc/libvirt/qemu # netstat -a -n | grep 20001
tcp        0      0 0.0.0.0:20001           0.0.0.0:*               LISTEN
...

Regarding logs of the VM for error analysis: You will find them in the directory ” /var/log/libvirt/qemu” (on an Opensuse Leap system).

Method 1: Local access to the Spice console with remote-viewer

Now, we are prepared to test a local access to the Spice console with remote-viewer. (As we work via a network port you may still need to open the Spice port on a local firewall – it depends of how you configured your firewall.) The format of the URI we have to specify for remote-viewer is

spice://FQDN_OR_IP:PORT_NR

with

  • FQDN_OR_IP: You have to present a host address which can be resolved by DNS or a directly an IP-address.
  • PORT_NR: The port for the Spice service – here “20001”.

For our setup this translates to

spice://localhost:20001

and thus the command

remote-viewer spice://localhost:20001

As user “uvma” we enter this command in another terminal window of our graphical desktop on the KVM host :

uvma@MySrv:~> remote-viewer spice://localhost:20001

(remote-viewer:22866): GSpice-WARNING **: 12:43:58.150: Warning no automount-inhibiting implementation available

Just ignore the warning. Then you should get a window with a graphical display of some login-screen on the VM. Details depend of course on the configuration of your VM’s operative system. In my case, I get the “gdm3”-login-screen of my virtualized Kali system:

The desktop-manager may be a different one on your system. After a login to a Gnome desktop I use remote-viewer‘s menu to open a 2nd screen:

and get two resizeable screen-windows :

As expected! When we change the dimensions the desktop of the VM adapts to the new virtual screen sizes. Just try it out.

Will this work with a KDE desktop on the Kali guest, too? Yes, it does. KDE5 and Gnome3 can very well coexist on a Kali, Debian or Opensuse Leap15.2 (guest) system! For a Kali system you find information how to install multiple graphical desktop environments e.g. at the following links:
install-kali-linux,
kde-environment-configuring-in-kali,
kali switching-desktop-environments.

The next image shows the transparency effect of a moving terminal window on a KDE desktop of the same Kali VM – again with 2 Spice screens requested by remote-viewer:

Such effects, which can also be configured on Gnome, require an active compositor on the guest’s desktop. At least when working locally on a KVM host I never got any problems with the performance of QXL/Spice and remote-viewer with an active compositor on the guest’s Gnome, KDE, and XFCE-desktops (without OpenGL acceleration). This is a bit different on a remote system and using remote-viewer over a LAN connection; see the next articles.

KDE and Gnome desktops on the VM automatically adapt to the sizes of the virtual screens. XFCE does not … XFCE is the present default desktop on Kali; so I installed after a distribution upgrade. Here some remote-viewer hints for XFCE fans on a VM with Kali/Debian and XFCE:

  • Set the number of screens in remote-viewer to 1. After installing XFCE with ” sudo apt update && sudo apt install -y kali-desktop-xfce” and a reboot we can choose “XFCE-Session” on a button of the gdm3-screen (after having entered the username). It will the boot into a XFCE session.
  • Then with the setting tool you can configure fixed resolutions for the screen displays (see below).
  • Or: Just deactivate a virtual display, resize the respective window on your host’s desktop and reactivate the virtual display again in your XFCE guest. XFCE then automatically recognizes the new screen size and adapts.
  • When logging out choose an option to save the desktop.

Unfortunately, XFCE has no seamless coexistence with KDE or Gome on Kali, yet. The following sequence of steps may fail:
1) Log out of a XFCE desktop-session, 2) choose a KDE or Gnome session afterwards /(this works without rebooting via the gdm menu), 3) log out of KDE/Gnome again and 4) try to restart a XFCE desktop.
On my Kali guest (on an Opensuse KVM host) I always have to reboot the guest to get a working XFCE session again, even if I did not change the screen dimensions during the KDE/Gnome session .. 🙁

Netstat reveals multiple connections corresponding to Spice channels

Using remote-viewer with a netowrk port is a really simple exercise. Most of the text above was spend on looking at the general virtualization environment. But, actually, the situation behind the scenes is not so simple. When we use netstat again, we get the following:

  
MySRV:/etc/libvirt/qemu # netstat -a -n | grep 20001
tcp        0      0 0.0.0.0:20001           0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:20001         127.0.0.1:46738         ESTABLISHED
tcp        0      0 127.0.0.1:20001         127.0.0.1:46750         ESTABLISHED
tcp        0      0 127.0.0.1:46734         127.0.0.1:20001         ESTABLISHED
tcp        0      0 127.0.0.1:46750         127.0.0.1:20001         ESTABLISHED
tcp        0      0 127.0.0.1:20001         127.0.0.1:46742         ESTABLISHED
tcp        0      0 127.0.0.1:46738         127.0.0.1:20001         ESTABLISHED
tcp        0      0 127.0.0.1:46740         127.0.0.1:20001         ESTABLISHED
tcp        0      0 127.0.0.1:46748         127.0.0.1:20001       
  ESTABLISHED
tcp        0      0 127.0.0.1:20001         127.0.0.1:46740         ESTABLISHED
tcp        0      0 127.0.0.1:20001         127.0.0.1:46734         ESTABLISHED
tcp        0      0 127.0.0.1:20001         127.0.0.1:46728         ESTABLISHED
tcp        0      0 127.0.0.1:20001         127.0.0.1:46744         ESTABLISHED
tcp        0      0 127.0.0.1:46728         127.0.0.1:20001         ESTABLISHED
tcp        0      0 127.0.0.1:46742         127.0.0.1:20001         ESTABLISHED
tcp        0      0 127.0.0.1:20001         127.0.0.1:46748         ESTABLISHED
tcp        0      0 127.0.0.1:46744         127.0.0.1:20001         ESTABLISHED

We find many, namely eight (8), active established connections. What do these connections correspond to? Well, they correspond to individual data exchange channels; I quote from
https://libvirt.org/formatdomain.html#video-devices:

“When SPICE has both a normal and TLS secured TCP port configured, it can be desirable to restrict what channels can be run on each port. This is achieved by adding one or more elements inside the main element and setting the mode attribute to either secure or insecure. Setting the mode attribute overrides the default value as set by the defaultMode attribute. (Note that specifying any as mode discards the entry as the channel would inherit the default mode anyways.) Valid channel names include main, display, inputs, cursor, playback, record (all since 0.8.6 ); smartcard ( since 0.8.8 ); and usbredir ( since 0.9.12 ).”

See also: spice_for_newbies.pdf

Theoretically, one should be able to use remote-viewer itself to activate or deactivate channels by setting up a “target file” for the connection; see the man-pages for more details. But on my machines it does not work neither locally not remotely. 🙁 I did not look into the details of this problem, yet ….

Testing the “one seat situation” at a Spice console

Now its time to test what I claimed in the last article: The Spice console can be accessed only by one user at a time. Let us assume, that user “uvma” is a member of the libvirt-group. Let us in addition create another user “uvmb” which is member of the group “users” on the host, only. I assume that “uvma” has opened a graphical desktop session on the KVM host (MySRV). E.g. a KDE session.

Step 1: As user “uvma” start virt-manager and boot your VM “debianx”. On a terminal window (A) use remote-viewer to open the Spice console of the VM with 2 screens. Log into a graphical desktop of the VM.

Terminal A:

uvma@MySRV:~> remote-viewer -v  spice://localhost:20001
Guest (null) has a spice display
Opening connection to display at spice://localhost:20001

(remote-viewer:20735): GSpice-WARNING **: 18:21:31.344: Warning no automount-inhibiting implementation available

Step 2: On your host-desktop open another terminal window (N) and login via “su – uvmb” as the other user. As “uvmb” now enter “remote-viewer spice://localhost:20001“.

uvma@MySRV:~> su - uvmb
Passwort: 
uvmb@MySRV:~> remote-viewer -v  spice://localhost:20001

This will at once close the open two Spice windows and after a blink of a second open up one or two new Spice windows again. The effect is clearly visible.

On terminal A we get:

Guest debianx display has disconnected, shutting down
uvma@MySRV:~> 

On terminal B we get a lot of warnings – but still the spice windows open in exactly the same status as we left them.

n

uvmb@MySRV:~> remote-viewer -v  spice://localhost:20001

(remote-viewer:20903): dbind-WARNING **: 18:25:40.853: Couldn't register with accessibility bus: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
Guest (null) has a spice display
Opening connection to display at spice://localhost:20001

(remote-viewer:20903): GSpice-WARNING **: 18:25:40.936: PulseAudio context failed Verbindung verweigert

(remote-viewer:20903): GSpice-WARNING **: 18:25:40.936: pa_context_connect() failed: Verbindung verweigert
Cannot connect to server socket err = Datei oder Verzeichnis nicht gefunden
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
AL lib: (EE) ALCplaybackAlsa_open: Could not open playback device 'default': Keine Berechtigung

(remote-viewer:20903): GLib-GObject-WARNING **: 18:25:40.962: g_object_get_is_valid_property: object class 'GstAutoAudioSink' has no property named 'volume'
AL lib: (EE) ALCplaybackAlsa_open: Could not open playback device 'default': Keine Berechtigung

(remote-viewer:20903): GLib-GObject-WARNING **: 18:25:40.964: g_object_get_is_valid_property: object class 'GstAutoAudioSrc' has no property named 'volume'
AL lib: (EE) ALCplaybackAlsa_open: Could not open playback device 'default': Keine Berechtigung
AL lib: (EE) ALCcaptureAlsa_open: Could not open capture device 'default': Keine Berechtigung

(remote-viewer:20903): GSpice-WARNING **: 18:25:41.015: record: ignoring volume change on audiosrc

(remote-viewer:20903): GSpice-WARNING **: 18:25:41.018: record: ignoring mute change on audiosrc

(remote-viewer:20903): GSpice-WARNING **: 18:25:41.021: Warning no automount-inhibiting implementation available

(remote-viewer:20903): GSpice-WARNING **: 18:25:41.052: playback: ignoring volume change on audiosink

(remote-viewer:20903): GSpice-WARNING **: 18:25:41.052: playback: ignoring mute change on audiosink

 
The warnings are mainly due to the fact that user “uvmb” has no rights to access the Pulseaudio context of the desktop of user “uvma”. (I take care of Pulseaudio in one of the next articles …) At the first switch between the users you may only get one Spice window as “uvmb”. Choose two screens then. Afterwards you can switch multiple times between the users uvma and uvmb. Two windows get closed for the user with present Spice console session, two windows are opened for the requesting user, and so on.

Conclusion: “uvmb” and “uvma” can steal each other the Spice console with remote-viewer as and when they like.

By the way: A Spice console can be left regularly by a user by just closing the Spice client window(s). Note that this will not change the status of your desktop session on the host! This is left open – with all consequences.

Restricting access by setting a password

Let us prevent being thrown of the “seat” in front of our Spice console. As root change the <graphics> definition in VM’s definition file to

...
 <graphics type='spice' port='20001' autoport='no' listen='0.0.0.0' keymap='de' passwd='spicemeandonlyme' defaultMode='insecure'>
      <listen type='address' address='0.0.0.0'/>
      <image compression='off'/>
      <gl enable='no'/>
    </graphics>
   ... 

If you haven’t noticed: The relevant difference is the “passwd” attribute. You could have added this setting via virt-manager, too. Try it out.

Shut down and restart your VM. Any user that now wants to access the Spice console using “remote-viewer spice://
localhost:20001” will be asked for a password. You yourself, too, if you close the console and try to reopen it.

Regarding security: The password transfer will to my understanding be AES encrypted. See Daniel P. Berrangé’s blog https://www.berrange.com/posts/2016/04/01/improving-qemu-security-part-3-securely-passing-in-credentials/. But as long as the rest of the data exchange with the VM is not encrypted, this precaution measure won’t help too much against ambitioned attackers.

Conclusion

Using remote-viewer locally on a KVM host in combination with a network port to access a VM’s graphical Spice console is easy and convenient. It requires a minimum of settings. In addition it offers up to four virtual screens which you can open via a menu.
However, using a network port implies security risks. You should think about proper counter-measures first if you want to lean on “remote-viewer”. Once configured in the way described above there is no libvirt-layer or anything else which may hinder ambitious attackers to analyze the unencrypted data flow between the Spice client and the VM through the host’s network port.

In the next article

KVM/Qemu VMs with a multi-screen Spice console – III – local access with remote-viewer via a Unix socket

I want to show you how one can configure the VM such that remote-viewer can access the Spice console via a local Unix port. A network port is not opened in this approach. Security is none the less hampered a bit as we have to give a standard user some rights which normally only the “qemu” group has. But we shall take care of this aspect by using ACLs.

Links

Virtualization on Opensuse
https://doc.opensuse.org/ documentation/ leap/ virtualization/ single-html/ book.virt/index.html

Libvirtd daemon
https://www.systutorials.com/docs/linux/man/8-libvirtd/

Libvirt connection URIs
https://libvirt.org/uri.html

Find the Spice URI to use
https://access.redhat.com/ documentation/ en-us/ red_hat_enterprise_linux/7/ html/ virtualization_deployment_and_ administration_guide/ sect-Domain_Commands- Displaying_a_URI_ for_connection_to_a_graphical_display

TLS disabled
https://unix.stackexchange.com/ questions/ 148794/ how-to-create-kvm-guest-with-spice-graphics-but-tls-disabled-using-virt-install

General Kali installation
https://www.cyberpratibha.com/blog/how-to-update-and-upgrade-kali-linux-to-latest-version/

KDE, XFCE on Kali
https://technicalnavigator.in/kde-vs-xfce-which-one-is-better/