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 has a problem checking her email. She telephones the internal helpdesk where she finds herself talking to Horatio. Horatio would like to be able to remotely see what problem Abby is having and, hopefully, fix it without having to waste time walking around the office looking for Abby's desk before fixing the problem.
Bob has gone home for the evening and left some program running which is consuming a lot of resources. Horatio sees this problem a lot and is sick of it. He'd like to be able to sort the problem out quickly (and without moving) by closing the program or logging Bob out. However, he doesn't want to just kill Bob's session or reboot his client since he knows Bob is quite likely to have some half written documents open or something.
Horatio has noticed from his proxy server logs that somebody is looking at an awful lot of porn. Horatio suspects Bob but needs to prove it by catching him in the act. Horatio wants to snoop on Bob every now and again over the course of the day.
Kimber is just about to hire another 200 Bobs and Horatio has been tasked with figuring out a way to provide the computing resources neccessary at much lower cost per employee than previously. Horatio dreams of a system which
scales cheaply - after an initial investment he'd like to be able to setup newly hired Bobs very cheaply
doesn't waste a lot of hardware - Horatio knows that Bobs are just supposed to come into work, handle customer queries, use a browser for looking up customer details etc. and that's it. It really pains Horatio to see one of those goons sitting there in front of a machine with a 1.6Ghz processor, heaps of RAM and disk space, sound card, speakers, CD/DVD-ROM, USB ports etc. etc.
is easy to manage - 200 new desktop machines to individually manage does not appeal one little bit to Horatio
is easy to monitor and control - in Horatio's mind, Bobs are like delinquent children. Anything which makes it easier for Horatio to keep an eye on and prevent them from screwing things up is good.
doesn't require starting from scratch - the last thing Horatio wants to have to do is switch *everyone* in Kimber over to the new system or waste the existing hardware he already has.
Abby has to give a presentation to senior management at 4pm in the board room downstairs. She hates having to spend ages getting stuff setup before she gives the presentation - especially with a presentation like this where she's nervous enough without having to worry about the computer going wrong on her. Wouldn't it be great if she could have everything setup before she went into the room and could launch straight into the presentation.
Abby has a conference call at 6pm with her colleagues in Mongolia. She always finds herself shouting down the phone at them so she prefers to take the call in a private room. She'd prefer not to have to interrupt her work by logging out and then logging back in in the room, though.
One of Horatio's colleagues in the office on the other side of town is trying to diagnose a problem with their mail server. Horatio is doing his best helping the guy out over the phone but he's having difficult understanding exactly what the guy is seeing. Horatio would love to remotely sit on the guys shoulder and talk him through it.
The scenarios above can be broken up into four distinct use cases:
Lets try and derive a task list for each of those use cases:
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:
(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?)
I see two major issues that the original Vino design did not address
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.
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.
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.
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.
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.
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:
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.
When you logout from a session GDM re-displays the login screen on the X server. For every client, apart from the one which actually started the session, you need to disconnect the client and start and new Xvnc for it.
Need root to be able to select any session, the user to choose between re-connecting, starting a new session and connecting to another user's session. Need to figure out the UI for this too.
Out-of-the-box terminal setup - i.e. start up the X server, start the fullscreen vncviewer and point the vncviewer at the terminal server.
Sanity check patches with George
Server certificate support
Client should warn when using an insecure connection
Sanity check patches and get upstream
Implement the management protocol
See vino/docs/TODO to more
Mark McLoughlin. June 18, 2004.