novnc: VNC screen sharing in the web browser

published Nov 29, 2010 02:20   by admin ( last modified Nov 09, 2012 11:51 )

Sometimes, when you want to do screen sharing, it can be hard to get the client in place on the other person's computer. They may have trouble installing it, may not have the rights to install it, or feel it is just too much trouble.

Fear not, because nowadays one can use a regular web browser as a VNC client. All the person at the other end needs to have on their computer is a modern web browser, such as Google's Chrome.

 

 

Screen detail: A Chrome browser running noVNC. In the upper half one can see the web browser that noVNC is running in, further down shows part of the VNC session that is running inside the browser (Gnome on Ubuntu 10.4)

The new generation of web browsers support the canvas element of HTML 5. The canvas element allows the browser to display a bitmap in a rectangle, and this bitmap can be continously manipulated pixel-by-pixel through javascript. Again, having a modern browser with a super fast javascript engine makes it realistic to use the canvas element for sharing a remote computer in real time.

 

I have found three implementations of VNC through the web browser:

ThinVNC works on Windows only on the server side as far as I can tell, and I run Linux, so that one is out. Guacamole needs a java servlet container (e.g. Apache + Tomcat), and I do not want to install that, so the choice fell on noVNC, and so far it works like a charm!

I have not been able to make it run on Firefox (v 3.6.12), but it does run on Chrome (v 8.0.552), both tested on Ubuntu Linux. A customer failed to connect with a Chrome 7 series, running on OSX, so my guess is Chrome 8 or better is a good bet. noVNC also works with Chromium (an open source version of Chrome) 9.0.565 on CentOS 5, but not with Firefox 3.6.4 on CentOS 5 in my tests.

All three programs, or at least novnc and Guacamole that I have paid attention to, requires three programs to run:

  • The VNC server of your choice,
  • A server that translates (proxies) the VNC server communication to a web browser friendly language (called WebSockets),
  • A javascript running in the web browser that takes care of painting the remote screen, and handles mouse and keyboard events in cases one is not merely viewing but also controlling the remote machine.

 

What you need on the server side.

I liked the way noVNC gets you up and running really quickly. First and foremost you need a VNC server. I have tested noVNC with Gnome's desktop sharing (on Ubuntu 10.4). After downloading and unpacking noVNC, you can start it right away in the terminal, with the command indicated in the readme file. This will start a Websockets proxy server. The one used in noVNC is written in Python and hence needs no Java (in contrast to Guacamole). You need to indicate what port your VNC server is running on, so the Websockets server knows where the VNC server is that it is proxying. VNC servers typically run on port 5900, or 5901, or 5902 or thereabouts. For desktop sharing it is often 5900.

The command line also starts a web server that the remote client should connect to. You can vary the ports that the Websockets proxy and web server run on, to avoid conflicts with other server processes on your machine.

After having started noVNC, simply point the browser to the URL that the command returned in the terminal. This will load a web page and the javascripts needed to connect.

The web server is just a simple server to serve the html page and javascripts to the browser. If you already have a web server somewhere you can serve the files from there instead.

Encrypted connections

When using plain old VNC, it is a good idea to tunnel the session through ssh. With noVNC you can have the connection encrypted directly in the browser. The noVNC readme explains how: There is no need to connect to a different encrypted port; the proxy automatically recognises that the connection is encrypted. The proxy can be started with a --ssl-only flag to only accept encrypted connections, and encryption must then always be switched on in the web browser page, either under the settings menu (that looks like a button) or by supplying "encrypt=1" as an extra CGI parameter when loading the page. I have tested with Google Chrome (v 8.0.552), on Ubuntu Linux 10.10 and it worked fine. Ok, I didn't intercept the traffic between the browser and server to really verify it was encrypted, but I take in good faith that it was.

Installing the proxy server as a service

Once I had played around with noVNC for a while, I started to look to have it installed with a bit more permanence. Now the HTML and the javascript for the web browser can be served from any old web server, and the VNC server is built into Gnome, but what about the WebSockets proxy, that translates the VNC to something the browser can understand? noVNC ships with no less than 3 alternative WebSockets proxies, one written in Python, one written in (server side) Javascript and one written in C. The Javascript version does not support encryption. The Python based proxy server can be run in the foreground with the -f flag, and as a daemon otherwise. But it would be nice to have it run always, and automatically started when the server reboots. I decided to put it under the control of supervisord, a framework for running processes and keeping them alive, that I am familiar with from developing with Plone and buildout. Supervisord does not manage other daemonized processes. Instead it wants to run processes that think they are running in the foreground, but are in fact connected to supervisord. Supervisord in this way is tightly coupled with the processes it runs. It can restart and otherwise manage its child processes, without the need for pid files or other such things. It i also trivial to run multiple copies of a program.

On Ubuntu 10.4, you can install supervisord easily; it is one of the packages in the usual repositories. After it has been installed, it has an entry in the /etc/init.d directory , and in /etc/supervisor/ directory you can add directions for it to run wsproxy.py as a foreground process. On install supervisord is configured to start when the server boots. Here is what I use. This is an entry in the /etc/supervisorsuper/supervisord.conf file on a Ubuntu 10.4 server:

 

[program:wsproxy]
command=/usr/local/bin/wsproxy/wsproxy.py -f 6900 --cert=self.pem --ssl-only localhost:5900
process_name=%(program_name)s
numprocs=1
directory=/usr/local/bin/wsproxy
stopsignal=TERM
user=a_user_name

It runs wsproxy.py on server startup, and will restart wsproxy if it ever would go down. wsproxy is configured above to proxy a VNC server running on port 5900 and serves it out as a websocket service on port 6900 for noVNC. wsproxy is configured above to requre SSL encryption.

Update:

There seems to be a bit of trouble with the websocket protocol that noVNC uses, but according to Wikipedia, Google Chrome should still support it in all versions. The crux is here.:

http://hacks.mozilla.org/2010/12/websockets-disabled-in-firefox-4/

Check:

http://en.wikipedia.org/wiki/WebSockets#Browsers_supporting_WebSocket

for what browsers to use. However, the developer of NoVNC, Joel Martin, points out in a comment to this blog post that NoVNC has a built in Flash based Websockets proxy, so one is with NoVNC actually not dependant on Websockets support in the web browser.

So, right now it seems like Firefox will not support Websockets out-of-the-box, until they have fixed the issue. It seems though that you can turn it on again in about:config. Opera is turning websockets off by default from what I can see. However I guess the browser versions tested below as working (Chrome v 8.0.552, and Chromium 9.0.565) will continue to work since they are already out, and it seems all Chrome versions support it.