Vino. The Remote Desktop Project. Take 2.


The primary goal of Vino was originally to provide a mechanism by which system administrators could remotely connect to a desktop machine and resolve basic problems for users. However, the umbrella term "Remote Desktop" encompasses much more functionality and use cases.

This is an attempt to step back from the original goals of and look at the bigger picture.


Here's a number of scenarios that could fall under the "remote desktop umbrella". The cast of characters in these scenarios are a set of personas defined for the Fedora Desktop:

Abby, Horatio and Bob are all employees of Kimber, Inc. (Although, Bob won't be for much longer unless he gets the finger out and actually does some work...)

Some scenarios:


The scenarios above can be broken up into four distinct use cases:

  1. Remote administration
  2. Terminal services
  3. Mobile sessions
  4. Collaboration

Lets try and derive a task list for each of those use cases:

1. Remote administration

The following are commonly perceived to be tasks, but personally I'm dubious that a person who needs assitance will really click a button and sit there waiting for someone to respond:

2. Terminal services

(Same tasks as with a traditional thick client - i.e. log in, do stuff, log out? Maybe its Horatio's "setting it up" tasks we want to think about here?)

3. Mobile Sessions

4. Collaboration

Existing Problems With Vino

I see two major issues that the original Vino design did not address

Weak Authentication

VNC uses a simple and weak DES based challenge-response authentication scheme. See here for more details. With Vino as it stands, I would feel safer not setting any password at all and approving each connection manually as it comes in.

Ideally we should properly authenticate any user which wishes to connect using PAM just like SSH or whatever.

Service Discovery

VNC, in much the same way as X, opens a listening TCP port (between 5900-5999) for each running display. Usually, users aren't aware of this because there is only a single display running on the machine they are connecting to and vncviewer connects to 5900 by default. However, on a multi-user machine, the problem quickly becomes apparent when one needs to know which of the open VNC ports to connect to.

Previously, I suggested that we may be able to use DNS-SD and mDNS to ease this problem. However, even this solution has its problems: you would only be able to see running VNC sessions on the current subnet, you would still have to explicitly choose between sessions and we would be making information on who is logged in and their usernames available to anyone on the network.

Implementation Details


VNC is commonly used for terminal services by adding a inetd entry which launches a VNC server every time there is a connection attempt on a certain port. The VNC server then uses XDMCP to query the display manager on the local host and get it to display a login screen on the newly started VNC server. The user can then login as normal. See this article for an example of this setup.

An extension of this idea would be for the display manager itself to listen on the VNC port and provide a VNC server for each connection. The display manager could then keep that server running if the user disconnects and allow re-connection. Further, the display manager could allow users to connect to sessions belonging to other users.

Display Management

With VNC support enabled, the display manager should listen for VNC connections on port 5900. When it receives a new connection on that port, it spawns a new VNC server in a similar fashion to inetd. With inetd the VNC server is spawned with the VNC socket available on file descriptors 0 (stdin), 1 (stdout) and 2 (stderr). However, when spawned from the display manager, file descriptor 0 is the VNC socket, file descriptor 1 is a connected UNIX socket with which the display manager and VNC server may communicate and, finally, file descriptor 2 is a pipe over which the VNC sevrer can make its error messages available to the display manager.

Once the VNC server has been spawned, the display manager should show the login screen on the VNC display. The user may log in as usual and a new session is started on the VNC display. However, if the user disconnects from the VNC server the display manager should not shutdown the VNC server, but instead leave it running and keep track of the fact that the user has a logged in session on that display.

If the user connects to the display manager via VNC and logs in (say, on display A), the display manager can detect that the user already has a session running on another VNC display (say, B) and re-connect that user to display B. In order to do that, the display manager asks the display A to stop updating the VNC client, asks display A for the current state of the VNC client and then asks display B to start updating the VNC client, given its current state.

This is achieved using a simple line based protocol over the UNIX socket between the display manager and the VNC server:

The "(VNC socket)" part indicates that the VNC socket, through which the client was connected to display A, is passed to display B over the UNIX socket through ancillary data with the "NEW CLIENT" message. See the recv(2) and cmsg(3) manpages for more details on how this is done. Also, see this example code.

VNC Modifications

Obviously, the VNC server needs to support the management protocol detailed above and be able to handle VNC clients which have already been initialized. When the VNC server is asked to stop handling a client, it must leave the protocol stream in a known state - i.e. it must complete any messages it was in the process of sending and flush any state from the stream.

The ZRLE encoding provides one difficulty here. With this encoding, the pixel data is compressed into a zlib stream. In order for display B to be able to continue using the ZRLE encoding, display A should send a dummy framebuffer update which completes the zlib stream. See the Z_FINISH flag to deflate() in this example.

One requirement of the VNC server is that it should support VNC's TLS extension so that the protocol stream is encrypted. Note that, initially, the TLS extension will use anonymous diffie-hellman key exchange which does not provide protection against man in the middle attacks and doesn't provide comparable security to using SSH tunnels. However, in time, support for server certificate authentication will be implemented which will be much more secure.

The TLS extension presents a problem similar to the issue with the state implied by the ZRLE encoding. In order for display B to be able to encrypt the VNC stream, display B needs to re-negotiate the TLS connection parameters with the client. This can be achieved by display A completely shutting down the TLS stream and display B immediately re-starting it. This is demonstrated in these server and client example programs.

Unfortunately, because of the ZRLE and TLS issues, the VNC client also needs minor modifications to be able to handle the stopping and re-starting of the zlib and TLS streams.

Non-VNC Displays

In order to be able to support connecting to non-VNC displays, the existing VNC server in the Vino package will be modified to support the VNC server management protocol detailed above.

With this implemented, all "remote desktop" connections will go through the display manager, be properly authenticated and then routed to the appropriate VNC server.

More details on this later.


We need to figure out how we will present the various options available to the user once authenticated. The options are:

More details on this later too.

Status So Far

At this point, we have things at a point where GDM can spawn VNC servers, keep them around and route a user to an existing VNC session. All the initially required VNC parts (manager protocol, TLS support, ZRLE issue) have been implemented as a patch against version 4.0 RealVNC's UNIX server and viewer. However, up until now, we've been concentrating on just prototyping the system and all the work we've done so far needs sanity checking.





Mark McLoughlin. June 18, 2004.