In order to present a virtual machine’s console in XenCenter, XenServer creates a VNC stream for each VM that is running on the server.  The VNC session is bound to the localhost address of the server (127.0.0.1) and is therefore not directly accessible from external VNC clients.  In this post I’ll discuss a quick and dirty way to connect directly to the VM’s console using a remote VNC client and an SSH tunnel.  Since there is not a version of XenCenter that runs on Linux, this method allows you to connect to XenServer VM consoles from a Linux machine.

This post will assume that the user doesn’t have access to XenCenter, but does have root access to the XenServers in a resource pool.  To create the SSH tunnel it will expect that you’re using OpenSSH.  If not, you’ll need to look at your SSH utility’s documentation to determine how to create SSH sessions and tunnels.  Some VNC clients have the ability to establish SSH tunnels on their own.  I’ve found these implementations to be hit or miss, so for this post we’ll separate SSH and VNC utilities. Also, note that this post will exclusively use the XenServer CLI. If you want to access the VNC console via the XAPI, documentation is found at here.

First, you’ll need to find the domain ID of the VM you’re interested in and the XenServer host that it’s running on.  To do this you’ll need to SSH to one of the hosts in the resource pool and execute the following xe command:

[root@jeckle ~]# xe vm-list params=dom-id,resident-on name-label=<name of VM>
resident-on ( RO)    : 06970b38-8b11-4228-bfc5-198405530e10
         dom-id ( RO): 2

Next, you’ll need to identify which server is running the VM from the uuid above:

[root@jeckle ~]# xe host-list uuid=06970b38-8b11-4228-bfc5-198405530e10
uuid ( RO)                : 06970b38-8b11-4228-bfc5-198405530e10
          name-label ( RW): jeckle
    name-description ( RW): Default install of XenServer

If you need to determine the IP address of the host that’s running the VM you can issue the following command:

[root@jeckle ~]# xe pif-list management=true params=IP host-uuid=06970b38-8b11-4228-bfc5-198405530e10
IP ( RO)    : 192.168.10.52

If necessary, establish an SSH session to the host that is running the VM you want to connect to.

Next, we’ll need to identify the port that XenServer is using to present the VM console’s VNC stream.  The process varies for Windows and Linux VMs, so follow the process for the OS that the VM you’re connecting to is running.

For Windows, using the domain ID you identified from the vm-list command earlier (domain ID 2, hence qemu.2), issue the following command:

[root@jeckle ~]# netstat -lp | grep qemu.2
tcp        0      0 jeckle.skunkworks.home:5902 *:*               LISTEN      8044/qemu.2

This tells you that you want to connect to the Windows VM on port 5902.

For Linux, run the following command:

[root@jeckle ~]# netstat -lp | grep vncterm
tcp        0      0 jeckle.skunkworks.home:5900 *:*              LISTEN      7097/vncterm
tcp        0      0 jeckle.skunkworks.home:5903 *:*              LISTEN      19654/vncterm

You’ll note that is is not decisive as there are multiple listings.  In the case listed here, we actually know that it’s port 5903 because dom0 always uses 5900.  On a machine with many Linux VMs we need to determine which port to use another way.  Using the domain ID you identified from the vm-list command earlier, issue the following command (in the following example I’m using domain ID 30):

[root@jeckle ~]# grep 'domain/30' /proc/*/cmdline
Binary file /proc/19654/cmdline matches
Binary file /proc/19665/cmdline matches
Binary file /proc/self/cmdline matches

Comparing the 2 previous outputs you’ll see that the only process ID in common is 19654, and therefore you can identify that port 5903 is the one the Linux VM is using.  If there are a lot of Linux VMs running on a single host it would probably be better to find the process ID first and then grep the netstat output for the process ID, like this:

[root@jeckle ~]# netstat -lp | grep 19654
tcp        0      0 jeckle.skunkworks.home:5903 *:*               LISTEN      19654/vncterm

Now that we know the port we want to connect to, we need to create an SSH tunnel to the XenServer and then connect the VNC client through the tunnel.  An SSH tunnel basically says, any connection that is made to a selected port on the local machine will be forwarded through the SSH tunnel to an identified port that is accessible from the remote host you SSH to.  To create the tunnel issue the following command in a local shell:

ssh -L <local port>:localhost:<VM console port> <username>@<xenserver host>
  • local port: any unused port on the client host that you want to proxy through (should be greater than 1024)
  • VM console port: the port on the XenServer host that the VM console is listening on
  • username: the user account on the XenServer host that the VM is running on
  • xenserver host: the host your VM is running on

Here’s an example:

ssh -L 5903:localhost:5903 root@192.168.10.52

This command says to send any traffic that is sent to local port 5903 on the client, through ssh to the host 192.168.10.52 and then redirect it to localhost:5903.

Once this is established, you can connect a VNC client to localhost:5903 and you’ll be connected to the VM’s console.