virt-manager with SSH and 2FA with TOTP?

Hi! (I hope, this is the right list for my question. I already posted it to the debian-user ML, but someone pointed me to this list. Alas, there is no virt-manager ML anymore) In our network we have several Debian systems working as VM host running QEMU+KVM based virtual machines. I usually use virt-manager on my workstation as GUI to connect to the VM host, manage the VMs and also to connect to the VM console if needed. To connect to the VM host I use SSH with public key authentication. On the commandline with virsh this looks like this (example): andreas@ws1:~> virsh -c qemu+ssh://root@maxwell/system Welcome to virsh, the virtualization interactive terminal. Type: 'help' for help with commands 'quit' to quit virsh # So far, so good. Recently I decided to increase our internal network security standards and activated 2FA with time-based one-time passwords on several hosts. (The idea is to eventually have 2FA for SSH for all users on all hosts in our network) This works very well and even quite comfortable with authenticator-apps on my smartphone or KeePassXC on my workstation generating the TOTP. Example: andreas@ws1:~> ssh root@mach Enter OTP: Linux mach 6.1.0-32-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.129-1 (2025-03-06) x86_64 root@mach:~# So for a successful SSH connection I now have to enter a valid TOTP (generated by the authenticator app) and then it connects. Connecting to the host with virsh on the commandline also works in a similar way: andreas@ws1:~> virsh -c qemu+ssh://root@mach/system Enter OTP: Welcome to virsh, the virtualization interactive terminal. Type: 'help' for help with commands 'quit' to quit virsh # All fine. Works as designed... When I use virt-manager to connect to the VM host, the GUI opens a dialog asking for the OTP and then connects, showing the list of all configured VMs etc. I can also open the configuration of a given VM, manage and change it. All fine, too... But when I try to use virt-manager to connect to the console of a specific VM, it doesn't work as expected. virt-manager opens a new window for the console, but also endlessly keeps opening password entry dialogs. As soon as I enter the current OTP and klick "ok", another dialog is opened, again asking for another OTP. And so on... (These are one-time passwords, valid for 30 seconds, which cannot be re-used) I can connect to the VM console with a SPICE viewer like remmina using SSH port forwarding like this: andreas@ws1:~> ssh -L 5906:localhost:5906 root@mach Enter OTP: root@mach:~# (where 5906 is the SPICE port for the VM in question) And then use remmina to connect to port 5906 on localhost. This gives me the SPICE console of the VM. Of course, this is not as comfortable as using virt-manager. But with virt-manager I haven't found a way to successfully connect to the VM console with 2FA in place. So, finally, my question: Did anyone on this list manage to use virt-manager to connect to a VM console using SSH with 2FA? Thanks! - andreas -- Andreas Haumer *x Software + Systeme | mailto:andreas@xss.co.at Karmarschgasse 51/2/20 | https://www.xss.co.at/ A-1100 Vienna, Austria | Tel: +43-1-6060114

On Fri, Apr 11, 2025 at 09:14:23PM +0200, Andreas Haumer via Users wrote:
Hi!
(I hope, this is the right list for my question. I already posted it to the debian-user ML, but someone pointed me to this list. Alas, there is no virt-manager ML anymore)
Hi, virt-manager uses github discussions instead of ML.
In our network we have several Debian systems working as VM host running QEMU+KVM based virtual machines.
I usually use virt-manager on my workstation as GUI to connect to the VM host, manage the VMs and also to connect to the VM console if needed.
To connect to the VM host I use SSH with public key authentication.
On the commandline with virsh this looks like this (example):
andreas@ws1:~> virsh -c qemu+ssh://root@maxwell/system Welcome to virsh, the virtualization interactive terminal.
Type: 'help' for help with commands 'quit' to quit
virsh #
So far, so good.
Recently I decided to increase our internal network security standards and activated 2FA with time-based one-time passwords on several hosts. (The idea is to eventually have 2FA for SSH for all users on all hosts in our network)
This works very well and even quite comfortable with authenticator-apps on my smartphone or KeePassXC on my workstation generating the TOTP.
Example:
andreas@ws1:~> ssh root@mach Enter OTP: Linux mach 6.1.0-32-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.129-1 (2025-03-06) x86_64 root@mach:~#
So for a successful SSH connection I now have to enter a valid TOTP (generated by the authenticator app) and then it connects.
Connecting to the host with virsh on the commandline also works in a similar way:
andreas@ws1:~> virsh -c qemu+ssh://root@mach/system Enter OTP: Welcome to virsh, the virtualization interactive terminal.
Type: 'help' for help with commands 'quit' to quit
virsh #
All fine. Works as designed...
When I use virt-manager to connect to the VM host, the GUI opens a dialog asking for the OTP and then connects, showing the list of all configured VMs etc. I can also open the configuration of a given VM, manage and change it.
All fine, too...
But when I try to use virt-manager to connect to the console of a specific VM, it doesn't work as expected. virt-manager opens a new window for the console, but also endlessly keeps opening password entry dialogs. As soon as I enter the current OTP and klick "ok", another dialog is opened, again asking for another OTP. And so on... (These are one-time passwords, valid for 30 seconds, which cannot be re-used)
I can connect to the VM console with a SPICE viewer like remmina using SSH port forwarding like this:
andreas@ws1:~> ssh -L 5906:localhost:5906 root@mach Enter OTP: root@mach:~#
(where 5906 is the SPICE port for the VM in question)
And then use remmina to connect to port 5906 on localhost. This gives me the SPICE console of the VM.
Of course, this is not as comfortable as using virt-manager. But with virt-manager I haven't found a way to successfully connect to the VM console with 2FA in place.
So, finally, my question: Did anyone on this list manage to use virt-manager to connect to a VM console using SSH with 2FA?
Currently this is expected behavior as virt-manager opens new tunnel for each spice connection. Not sure if it is possible to change or how difficult it would be to use only single ssh tunnel. I have no experience with ssh+2fa but if ssh keys can be still used in addition to password+totp users can copy their keys to the remote hosts and avoid entering the password at all. If your goal is to use only password+totp and not allowing ssh keys virt-manager will ask for the password several times. Pavel
Thanks!
- andreas
-- Andreas Haumer *x Software + Systeme | mailto:andreas@xss.co.at Karmarschgasse 51/2/20 | https://www.xss.co.at/ A-1100 Vienna, Austria | Tel: +43-1-6060114

Hi Pavel! Thank you for your reply! Am 14.04.25 um 11:07 schrieb Pavel Hrdina:
On Fri, Apr 11, 2025 at 09:14:23PM +0200, Andreas Haumer via Users wrote:
Hi!
(I hope, this is the right list for my question. I already posted it to the debian-user ML, but someone pointed me to this list. Alas, there is no virt-manager ML anymore)
Hi,
virt-manager uses github discussions instead of ML.
oh, well.. :-( I'll check if I can move this topic to the virt-manager project on github. But I hate web user interfaces for text-based communication... ;-)) [...]
But when I try to use virt-manager to connect to the console of a specific VM, it doesn't work as expected. virt-manager opens a new window for the console, but also endlessly keeps opening password entry dialogs. As soon as I enter the current OTP and klick "ok", another dialog is opened, again asking for another OTP. And so on... (These are one-time passwords, valid for 30 seconds, which cannot be re-used)
[...]
Currently this is expected behavior as virt-manager opens new tunnel for each spice connection. Not sure if it is possible to change or how difficult it would be to use only single ssh tunnel.
A *single* tunnel for each VM would be ok. But does it have to open *several* SSH tunnels for a single VM console connection?
I have no experience with ssh+2fa but if ssh keys can be still used in addition to password+totp users can copy their keys to the remote hosts and avoid entering the password at all.
If your goal is to use only password+totp and not allowing ssh keys virt-manager will ask for the password several times.
The goal is to have SSH keys + TOTP for increased security. Rationale: SSH keys are stored in the users home directory and are static. If an attacker gains access to the users account in some way, he or she will get access to the SSH keys as well and thus have doors wide opened to all servers where SSH public key authentication alone is used. As we rely heavily on SSH for remote access to all servers in our network we consider this a security problem and thus we want to establish 2FA for all SSH connections in our network. We have this setup implemented purely with SSHD and PAM configuration settings. No fancy tricks or fairy dust needed. We have it running for several weeks now and it works very well. At least at the command line level between Linux systems, which is our major use case for this. Problems with virt-manager/libvirt connections to VM hosts now are some kind of collateral damage of this increased security, it seems, as these connections rely on SSH tunneling, too. But one has to differentiate: We would be fine if virt-manager asks for the TOTP on the first connection to the VM host. It would also be ok, if virt-manager again asks for a TOTP once(!) if user opens the virtual console of a single VM on the host. But currently if a user opens the virtual console of a single VM in virt-manager, it asks for the TOTP repeatedly in a very short time. And this is the real problem. It looks as if virt-manager opens several SSH connections for a single SPICE connection (I don't know the internal details of the connection between virt-manager and the VM host, though, so this might be a totally wrong guess) This is very bad as in our setup TOTP keys can not be reused. One would have to wait 30 seconds for the next TOTP. And repeat this for several times in a row. This is not acceptable from a users POV. We could fall back to SPICE viewers like Remmina for VM console access. But it would be more comfortable if VM console access integrated with virt-manager could be used as well. KR - andreas -- Andreas Haumer *x Software + Systeme | mailto:andreas@xss.co.at Karmarschgasse 51/2/20 | https://www.xss.co.at/ A-1100 Vienna, Austria | Tel: +43-1-6060114

On Mon, Apr 14, 2025 at 12:17:44PM +0200, Andreas Haumer via Users wrote:
Hi Pavel!
Thank you for your reply!
Am 14.04.25 um 11:07 schrieb Pavel Hrdina:
On Fri, Apr 11, 2025 at 09:14:23PM +0200, Andreas Haumer via Users wrote:
Hi!
(I hope, this is the right list for my question. I already posted it to the debian-user ML, but someone pointed me to this list. Alas, there is no virt-manager ML anymore)
Hi,
virt-manager uses github discussions instead of ML.
oh, well.. :-(
I'll check if I can move this topic to the virt-manager project on github. But I hate web user interfaces for text-based communication... ;-))
[...]
But when I try to use virt-manager to connect to the console of a specific VM, it doesn't work as expected. virt-manager opens a new window for the console, but also endlessly keeps opening password entry dialogs. As soon as I enter the current OTP and klick "ok", another dialog is opened, again asking for another OTP. And so on... (These are one-time passwords, valid for 30 seconds, which cannot be re-used)
[...]
Currently this is expected behavior as virt-manager opens new tunnel for each spice connection. Not sure if it is possible to change or how difficult it would be to use only single ssh tunnel.
A *single* tunnel for each VM would be ok. But does it have to open *several* SSH tunnels for a single VM console connection?
I have no experience with ssh+2fa but if ssh keys can be still used in addition to password+totp users can copy their keys to the remote hosts and avoid entering the password at all.
If your goal is to use only password+totp and not allowing ssh keys virt-manager will ask for the password several times.
The goal is to have SSH keys + TOTP for increased security.
Rationale: SSH keys are stored in the users home directory and are static. If an attacker gains access to the users account in some way, he or she will get access to the SSH keys as well and thus have doors wide opened to all servers where SSH public key authentication alone is used. As we rely heavily on SSH for remote access to all servers in our network we consider this a security problem and thus we want to establish 2FA for all SSH connections in our network.
We have this setup implemented purely with SSHD and PAM configuration settings. No fancy tricks or fairy dust needed. We have it running for several weeks now and it works very well. At least at the command line level between Linux systems, which is our major use case for this.
Problems with virt-manager/libvirt connections to VM hosts now are some kind of collateral damage of this increased security, it seems, as these connections rely on SSH tunneling, too.
But one has to differentiate: We would be fine if virt-manager asks for the TOTP on the first connection to the VM host. It would also be ok, if virt-manager again asks for a TOTP once(!) if user opens the virtual console of a single VM on the host.
But currently if a user opens the virtual console of a single VM in virt-manager, it asks for the TOTP repeatedly in a very short time. And this is the real problem. It looks as if virt-manager opens several SSH connections for a single SPICE connection (I don't know the internal details of the connection between virt-manager and the VM host, though, so this might be a totally wrong guess)
Yes, SPICE is designed to use a separate TCP socket for different classess of data (frambuffer, mouse, keyboard, audio, etc).
This is very bad as in our setup TOTP keys can not be reused. One would have to wait 30 seconds for the next TOTP. And repeat this for several times in a row. This is not acceptable from a users POV.
We could fall back to SPICE viewers like Remmina for VM console access. But it would be more comfortable if VM console access integrated with virt-manager could be used as well.
virt-manager currently has a trivial SSH tunnel impl that establishes a new SSH connection for each connection, running netcat on the remote side to forward the TCP data over the primary SSH channel. It would be conceptually possible to change virt-manager to make use of SSH's port tunnelling feature instead of using 'netcat'. The code is mostly in virtManager/details/sshtunnels.py if someone wants to have a crack at it. The challenge would be you need some global caching to open SSH only once and then have to keep track of when to tear down the tunnel since you can't directy see how many of the tunnelled ports are currently in use. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On 14/04/2025 11:27, Daniel P. Berrangé via Users wrote:
virt-manager currently has a trivial SSH tunnel impl that establishes a new SSH connection for each connection, running netcat on the remote side to forward the TCP data over the primary SSH channel.
It would be conceptually possible to change virt-manager to make use of SSH's port tunnelling feature instead of using 'netcat'. The code is mostly in virtManager/details/sshtunnels.py if someone wants to have a crack at it.
The challenge would be you need some global caching to open SSH only once and then have to keep track of when to tear down the tunnel since you can't directy see how many of the tunnelled ports are currently in use.
As it's just running the ssh command, could it just set some combination of the Control{Master,Path,Persist} options so that there is automatic connection sharing? Incidentally you could probably achieve the same thing without any code changes by doing something like this in .ssh/config: Host <vm-host> ControlMaster auto ControlPath ~/.ssh/control.%C ControlPersist no That should share connections to the host until the last one is closed I think. Tom -- Tom Hughes (tom@compton.nu) http://compton.nu/

Hi! Am 14.04.25 um 12:41 schrieb Tom Hughes: [...]
As it's just running the ssh command, could it just set some combination of the Control{Master,Path,Persist} options so that there is automatic connection sharing?
Incidentally you could probably achieve the same thing without any code changes by doing something like this in .ssh/config:
Host <vm-host> ControlMaster auto ControlPath ~/.ssh/control.%C ControlPersist no
That should share connections to the host until the last one is closed I think.
I can confirm that this actually solves my initial problem: With these few lines in $HOME/.ssh/config one has to authenticate only once in virt-manager on the initial connection setup and then can use the virtual console right away. The first SSH connection to the host is authenticated as usual (in my case with SSH key + TOTP). Subsequent connections from the same client to the same host do not perform a new authentication, they now use the existing network connection. There seems to be a side effect, though: if the initial connection is done using virt-manager, a subsequent SSH shell session to the host is lost, if the virt-manager connection is closed. This is interesting, as if the initial connection is done using ssh on the commandline (to get a shell on the remote host), a subsequent virt-manager connection is not lost if the user exits the initial SSH commandline session: The SSH shell session hangs and waits until the virt-manager connection is closed. I have to further analyze security and other implications of this setup. Subsequent SSH sessions do not go through the PAM auth and session stack, for instance. Shell sessions show up in the output of "who", though. But for the case of virt-manager, this indeed is a good workaround. Perhaps virt-manager should use this feature only for its own SSH connections and not rely on the users ssh config setup? Perhaps it could use the ssh commandline options "-M" and "-S" on the initial connection and "-S" on subsequent connections to the same VM host? Anyway, SSH is a very powerful tool! It still amazes me after all these (almost 30) years I use it! I didn't know this SSH feature. Thank you for sharing this idea! - andreas -- Andreas Haumer *x Software + Systeme | mailto:andreas@xss.co.at Karmarschgasse 51/2/20 | https://www.xss.co.at/ A-1100 Vienna, Austria | Tel: +43-1-6060114

Hi! Am 14.04.25 um 12:27 schrieb Daniel P. Berrangé:
On Mon, Apr 14, 2025 at 12:17:44PM +0200, Andreas Haumer via Users wrote: [...]
But currently if a user opens the virtual console of a single VM in virt-manager, it asks for the TOTP repeatedly in a very short time. And this is the real problem. It looks as if virt-manager opens several SSH connections for a single SPICE connection (I don't know the internal details of the connection between virt-manager and the VM host, though, so this might be a totally wrong guess)
Yes, SPICE is designed to use a separate TCP socket for different classess of data (frambuffer, mouse, keyboard, audio, etc).
This is very bad as in our setup TOTP keys can not be reused. One would have to wait 30 seconds for the next TOTP. And repeat this for several times in a row. This is not acceptable from a users POV.
We could fall back to SPICE viewers like Remmina for VM console access. But it would be more comfortable if VM console access integrated with virt-manager could be used as well.
virt-manager currently has a trivial SSH tunnel impl that establishes a new SSH connection for each connection, running netcat on the remote side to forward the TCP data over the primary SSH channel.
It would be conceptually possible to change virt-manager to make use of SSH's port tunnelling feature instead of using 'netcat'. The code is mostly in virtManager/details/sshtunnels.py if someone wants to have a crack at it.
The challenge would be you need some global caching to open SSH only once and then have to keep track of when to tear down the tunnel since you can't directy see how many of the tunnelled ports are currently in use.
I now managed to implement a proof of concept of the SSH connection sharing idea suggested by Tom Hughes and Erik Huelsmann in the sshtunnels.py module of virt-manager. I currently consider this a hack and by no means a final solution, but in principle it seems to work: when opening the virtual console inside virt-manager, the user is now asked for the TOTP password only once (for the first SSH tunnel). Subsequent tunnels for the SPICE protocol now re-use the connection of this first tunnel and do not need to authenticate again. This should also improve the speed of connection setup as only a single authentication is needed. See https://github.com/virt-manager/virt-manager/discussions/899 for a discussion of all this. KR - andreas -- Andreas Haumer *x Software + Systeme | mailto:andreas@xss.co.at Karmarschgasse 51/2/20 | https://www.xss.co.at/ A-1100 Vienna, Austria | Tel: +43-1-6060114

Hi Andreas, On Mon, Apr 14, 2025 at 12:18 PM Andreas Haumer via Users < users@lists.libvirt.org> wrote:
Currently this is expected behavior as virt-manager opens new tunnel for each spice connection. Not sure if it is possible to change or how difficult it would be to use only single ssh tunnel.
A *single* tunnel for each VM would be ok. But does it have to open *several* SSH tunnels for a single VM console connection?
Have you tried using SSH's ControlMaster setting to prevent new connections from being set up, instead reusing the master (first) connection?
I have no experience with ssh+2fa but if ssh keys can be still used in addition to password+totp users can copy their keys to the remote hosts and avoid entering the password at all.
If your goal is to use only password+totp and not allowing ssh keys virt-manager will ask for the password several times.
The goal is to have SSH keys + TOTP for increased security.
Rationale: SSH keys are stored in the users home directory and are static. If an attacker gains access to the users account in some way, he or she will get access to the SSH keys as well and thus have doors wide opened to all servers where SSH public key authentication alone is used. As we rely heavily on SSH for remote access to all servers in our network we consider this a security problem and thus we want to establish 2FA for all SSH connections in our network.
We have this setup implemented purely with SSHD and PAM configuration settings. No fancy tricks or fairy dust needed. We have it running for several weeks now and it works very well. At least at the command line level between Linux systems, which is our major use case for this.
Have you looked at SSH certiicates? They will allow you to restrict validity of the certificate to short periods; it's possible to require a certificate instead of just a key. The other option is to use smartcards to store an ssh certificate. I do this with a yubikey: the smartcard unlocks at configured points in time. In case of a yubikey, touching it is enough. From there, everything works as it would with a regular ssh-agent resident key. By the way: the key in the home directory should have a password set. Adding it to ssh-agent using ssh-add removes the necessity to enter the password every time. The key an attacker can get their hands on will be password protected though. Just some ideas to further improve your security while maintaining healthy sanity :-) -- Bye, Erik. http://efficito.com -- Hosted accounting and ERP. Robust and Flexible. No vendor lock-in.

Hi Erik! Am 14.04.25 um 12:59 schrieb Erik Huelsmann:
Hi Andreas,
On Mon, Apr 14, 2025 at 12:18 PM Andreas Haumer via Users < users@lists.libvirt.org> wrote:
[...]
A *single* tunnel for each VM would be ok. But does it have to open *several* SSH tunnels for a single VM console connection?
Have you tried using SSH's ControlMaster setting to prevent new connections from being set up, instead reusing the master (first) connection?
This was also suggested by Tom Hughes and I can confirm that it indeed solves the problems with the virtual console in virt-manager! See my message to this ML a few minutes ago. Thank you both for this hint! I didn't know this SSH feature. [...]
Have you looked at SSH certiicates? They will allow you to restrict validity of the certificate to short periods; it's possible to require a certificate instead of just a key.
The other option is to use smartcards to store an ssh certificate. I do this with a yubikey: the smartcard unlocks at configured points in time. In case of a yubikey, touching it is enough. From there, everything works as it would with a regular ssh-agent resident key.
By the way: the key in the home directory should have a password set. Adding it to ssh-agent using ssh-add removes the necessity to enter the password every time. The key an attacker can get their hands on will be password protected though.
Just some ideas to further improve your security while maintaining healthy sanity :-)
Thanks for your valuable ideas! Some of them I already used in the past (password protected SSH keys), some of them I haven't yet but will explore in the future (SSH certificates). KR - andreas -- Andreas Haumer *x Software + Systeme | mailto:andreas@xss.co.at Karmarschgasse 51/2/20 | https://www.xss.co.at/ A-1100 Vienna, Austria | Tel: +43-1-6060114
participants (5)
-
Andreas Haumer
-
Daniel P. Berrangé
-
Erik Huelsmann
-
Pavel Hrdina
-
Tom Hughes