Bug 861053

Summary: virt-manager can't connect to VNC console if VNC port is blocked by firewall and SSH is used for main libvirtd connection
Product: [Fedora] Fedora Reporter: Vladislav Bogdanov <bubble>
Component: virt-managerAssignee: Cole Robinson <crobinso>
Status: CLOSED WONTFIX QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 17CC: berrange, crobinso, hbrock, jforbes, virt-maint
Target Milestone: ---Keywords: Reopened
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2012-10-24 19:05:19 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Vladislav Bogdanov 2012-09-27 12:21:47 UTC
Description of problem:
virt-manager can't connect to VNC console of VM running under libvirt-0.10.2/qemu-1.2.0 when using ssh for main libvirt connection, VNC listen address is set to 0.0.0.0 (qemu.conf has uncommented vnc_listen = "0.0.0.0" line) and VNC ports are blocked by firewall (connections to both libvirtd and VNC are allowed only from the same network, and virt-manager is on different network).

Version-Release number of selected component (if applicable):
virt-manager-0.9.4-1.fc17.noarch
libvirt-client-0.10.2-3.fc17.i686 (recompiled from koji for f17)

Actual results:
2012-09-26 16:21:28,981 (connection:579): Connection managed save support: True
2012-09-26 16:21:33,554 (connection:161): Using libvirt API for netdev enumeration
2012-09-26 16:21:33,555 (connection:201): Using libvirt API for mediadev enumeration
/usr/share/virt-manager/virtManager/console.py:701: Warning: g_object_set_qdata: assertion `G_IS_OBJECT (object)' failed
  pages.add(self.fs_drawer)
2012-09-26 16:21:48,013 (details:557): Showing VM details: <vmmDomain object at 0x923a964 (virtManager+domain+vmmDomain at 0x917f360)>
2012-09-26 16:21:48,207 (engine:324): window counter incremented to 2
2012-09-26 16:21:48,258 (console:1116): Starting connect process for proto=vnc trans=ssh connhost=vd01-b.local connuser=root connport=None gaddr=0.0.0.0 gport=5900 gsocket=None
2012-09-26 16:21:48,306 (console:412): VNC connection to vd01-b.local:5900
2012-09-26 16:21:48,892 (console:1001): Viewer disconnected


Expected results:
2012-09-26 16:42:40,390 (connection:579): Connection managed save support: True
2012-09-26 16:42:45,725 (connection:161): Using libvirt API for netdev enumeration
2012-09-26 16:42:45,726 (connection:201): Using libvirt API for mediadev enumeration
/usr/share/virt-manager/virtManager/console.py:701: Warning: g_object_set_qdata: assertion `G_IS_OBJECT (object)' failed
  pages.add(self.fs_drawer)
2012-09-26 16:42:48,177 (details:557): Showing VM details: <vmmDomain object at 0xa8b8b1c (virtManager+domain+vmmDomain at 0xa94e970)>
2012-09-26 16:42:48,331 (engine:324): window counter incremented to 2
2012-09-26 16:42:48,388 (console:1116): Starting connect process for proto=vnc trans=ssh connhost=vd01-b.local connuser=root connport=None gaddr=0.0.0.0 gport=5900 gsocket=None
2012-09-26 16:42:48,439 (console:156): Creating SSH tunnel: ssh -l root vd01-b.local sh -c 'nc -q 2>&1 | grep "requires an argument" >/dev/null;if [ $? -eq 0 ] ; then   CMD="nc -q 0 0.0.0.0 5900";else   CMD="nc 0.0.0.0 5900";fi;eval "$CMD";'
2012-09-26 16:42:48,442 (console:179): Tunnel PID=13981 OUTFD=17 ERRFD=19
2012-09-26 16:42:50,526 (console:1029): Viewer connected


Additional info:
<graphics> section of live VM definition is:
      <graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0' keymap='en-us'>
        <listen type='address' address='0.0.0.0'/>
      </graphics>

On another host (libvirt-0.9.12/qemu-1.1.1-rc3) it is:
      <graphics type='vnc' port='5909' autoport='yes' keymap='en-us'/>

On both systems all "*listen" parameters of libvirtd.conf and qemu.conf are the same, so probably something is changed in libvirt (if I didn't miss something obvious in configuration).

Though that format change probably should not affect how virt-manager connects to consoles if SSH is used for main libvirtd connection - naturally, if one uses SSH to connect to libvirt, then there is high probability that both libvirtd and VNC (5900+) ports are blocked by firewall.

Following patch fixes the problem for me.
--- console.py.orig     2012-09-27 15:06:44.118445064 +0300
+++ console.py  2012-09-26 16:42:13.595321247 +0300
@@ -73,9 +73,9 @@ class ConnectionInfo(object):
             self._connhost, self._connport = self._connhost.split(":", 1)
 
     def need_tunnel(self):
-        if self.gaddr != "127.0.0.1":
-            return False
-
+#        if self.gaddr != "127.0.0.1":
+#            return False
+#
         return self.transport in ["ssh", "ext"]
 
     def get_conn_host(self):

Comment 1 Cole Robinson 2012-10-14 00:46:08 UTC
This behavior is intentional. It's assumed that if listen=0.0.0.0 then VNC is externally accessible, otherwise why is it configured like that?

The libvirt default is 127.0.0.1, so unless there's a libvirt bug here, listen=0.0.0.0 needs to be explicitly enabled. And if the user requests that then we should honor it, and it's up to them to configure things correctly.

I hope that's a sufficient description. Closing as NOTABUG, Vladislav please reopen if you think I've missed something.

Comment 2 Vladislav Bogdanov 2012-10-15 07:03:27 UTC
(In reply to comment #1)
> This behavior is intentional. It's assumed that if listen=0.0.0.0 then VNC
> is externally accessible, otherwise why is it configured like that?

Having daemon listening on address does not generally mean that it is accessible directly from everywhere.

And, if user (having configured listen=0.0.0.0) connects via ssh tunnel to libvirtd itselt, there is very strong probability that neither libvirtd nor VNC ports are accessible directly from that user's location.

So, fact that connection is tunnelled should have priority over fact that daemon is listening on some non-loopback addresses.

In my case I need limited connectivity, several cluster nodes should have direct access to each other's ports, while the rest of network should use ssh tunnels for that.

I do not see how to configure that with libvirt-only configuration. Even if there is way to do that, I would prefer to have firewall in the middle to prevent exploitation of yet-unknown bugs.

> 
> The libvirt default is 127.0.0.1, so unless there's a libvirt bug here,
> listen=0.0.0.0 needs to be explicitly enabled. And if the user requests that
> then we should honor it, and it's up to them to configure things correctly.
> 
> I hope that's a sufficient description. Closing as NOTABUG, Vladislav please
> reopen if you think I've missed something.

Intention you talk about leads to limitation for some use-cases. libvirtd itself is only the small building block, and solely its configuration cannot guarantee that everything is clean on the way to reach it.

Comment 3 Cole Robinson 2012-10-24 19:05:19 UTC
I get what you're saying. But virt-manager really tries to be a dumb tool. In this case we are reacting to how your VM is configured, which is listening on 0.0.0.0.

If we default to using SSH always, other people will complain (I guarantee). If we add some fallback logic to use SSH if the VNC connection fails, it's more maintenance burden for us, for behavior that not all users will even want.

As a user you have several options:

- If one of the nodes that can access the libvirt host has SSH access, tunnel through that to connect libvirt host.
- ssh -X to the libvirt host and run virt-manager from there
- Configure your graphics devices to use 127.0.0.1 and use ssh tunnelling on all hosts that will access the machine.

But I don't think we should add code to virt-manager to support a narrow use case where we are basically guessing at the admin's intention. Nor do I think it's worth adding explicit UI to handle this scenario.

One way this could work, and I'd support in virt-manager, would be if qemu allowed specifying 2 graphics devices. You could have one VNC connection listen on 0.0.0.0 and the other listen on 127.0.0.1, then virt-manager would have a way to choose the graphical device. I'd support that, but I don't know if qemu will ever provide that ability.

Maybe virt-viewer would take a patch to allow forcing a connection method via a command line switch, then you could connect as a one off like 'virt-viewer --connect <libvirturi> <domainname> --force-ssh'

Closing as WONTFIX.