Chrome, Firefox, Plugins oh my!

Remember browser plugins? Not ‘apps’ or ‘add-ons’ from stores, but plugins. Those installers you used to download in the 90s in order to run special content on the web, such as a game, chat program, or watch some videos. Those were written using NPAPI (the Netscape Plugin API) and ActiveX controls (Internet Explorer’s equivalent). These are APIs that enable web authors to interact in real-time with their users and use any media a computer could deliver. The price though, was to write and maintain your plugin for each and every platform your users had.

Later, with the advent of Flash and Java applet plugins, most of that special content was implemented using only those two. Not incidentally, Flash and Java enable writing the code once and running it on all their supported platforms, unburdening the developer from maintaining multiple code bases.

Then along came HTML5, with the premise of enabling web-pages to become web-apps. Supplying web developers with media, storage, threading, and network APIs. APIs that up until 2009 were only available through the use of plugins. HTML5 made sense too. Web pages looked more and more like applications and less and less like text pages. And why should a plugin become an inseparable part of a system. By definition it plugs-in, it should also be able to plug-out.

Jumping to the present, it looks like it’s an end of an era. The Chromium team announced last year that they’re deprecating NPAPI plugins from Chrome at the beginning of 2014 and completely removing support by the end of that year. Also, Mozilla is marking NPAPI plugins as unwelcome citizens in their ecosystem by making them all ‘Click-To-Play’ by default. And last but not least, ActiveX control support was removed in the ‘New Windows 8 browsing experience’ (the ‘Metro’ application) edition of Internet Explorer available on Windows 8.

If you’re a web developer and this all sounds very irrelevant to you, consider yourself lucky! Unfortunately, this was quite relevant for CloudShare. Here’s why…

Remote Access

Remote Access is a name (and verb) given to protocols such as RDP and VNC that allow a user to use a machine remotely.

The CloudShare web application allows its users to remote access their machines through the browser. With Windows being our most popular OS, RDP is naturally our most popular remote access protocol.

To use RDP through a browser in 2008, CloudShare’s only option was to use NPAPI plugins and ActiveX controls. These plugins allowed Windows clients (browsers) to RDP to a remote machine using a web page element. A marvel at the time. These plugins served us well. At least up until now.

HTML5 Remote Access

Enter the Guacamole project.

Using Canvas and WebSockets HTML5 technologies, the Guacamole project proved any browser can become a client in a remote access protocol. It works something like this:

A machine, acting as a remote-access gateway (a proxy to remote-access other machines) is run with a Guacamole web server and daemon. The user logs into the Guacamole web application, using a browser and chooses his desired machine to connect to. The gateway then acts as a translator between the selected protocol (RDP/SSH/VNC) used by the remote machine and the Guacamole protocol used by the browser.

The actual client is pure HTML, CSS and Javascript, and is served to the browser using the same Guacamole web application.

Multiplatform and Protocol Abstraction

Let’s illustrate our problem. Our remote access page allows a user to connect to a machine using VNC, RDP, or SSH. RDP uses NPAPI plugins or ActiveX controls, and VNC and SSH use Java applets. Each has its own code base and a different interface. To make things more complex, our NPAPI plugin uses Window’s native ActiveX control DLL to connect to a machine using RDP. Different Windows versions provide different DLLs with different behaviors, and non-Windows platforms cannot be supported. This adds the platform dimension to our testing matrix as well.

Using Guacamole not only allows us to maintain one code base to run on any platform a browser runs on, but it also allows us to use any protocol (supported by the Guacamole project) and deliver it on top of a single WebSockets protocol. In other words, not only do we get platform agnostic code, but we also get the same code to connect to different protocols.

Using Guacamole, our remote-access client becomes much simpler. Changing a protocol is simply a change in configuration and capabilities, not interface or code. As it’s written in Javascript and HTML, it’s cross-platform. With a bit of effort, also cross-browser.

A New Hope (A New Client)

So now we have the task of building a new Remote Access client. The most important gap we needed to fill was security, specifically – authentication and authorization. Guacamole’s gateway application comes with a few out of the box authentication methods that you can install:

Hard coded configuration

An XML file containing your users’ credentials and remote machines. This could work for on-premise use with a small number of users. But it surely isn’t scalable nor maintainable for a Cloud Computing service.

MySQL and LDAP

Managing your users and remote connections using a database schema or Directory Access listings. The problem with those lies with the fact that CloudShare already has users and machines with complex and intricate permissions logic. Mirroring that information and logic is an effort that we would like to avoid.

Security Concerns

Being behind our firewall, we should not forget that Guacamole is a remote-access gateway and as such can access any machine that has SSH, VNC or RDP connections available, even itself. Even without administrative access. This needs to be addressed in our authentication method.

So what do we do?

Three words: ‘One Time Passwords’. Authentication happens in four stages:

A Client requests Cloudshare to connect to a remote machine via Guacamole. Cloudshare authenticates the client’s request (the user and connection), and saves a temporary cryptographic hash (“password”); or rejects it. The Client requests connection from Guacamole using the given password. Guacamole queries Cloudshare and authenticates (or rejects) the request.

This solution removes the need to mirror application logic, and needs minimum maintenance leading to better scalability.

Fortunately Guacamole allows you to write your own authentication method via dynamic class loading, that allowed us to implement the server side of the above solution.

Also, Guacamole’s Javascript client modules are decoupled from Gateway and authentication code. The client modules are the engine that translates the Guacamole protocol instructions to Canvas element images and DOM events, and DOM events back to the Guacamole protocol. This allowed us to embed the client in our Remote Access page and change its authentication method.

A Brighter Web

Hopefully this problem-solution blog was enlightening for you. Guacamole is one of the more inspiring examples of what can be accomplished with HTML5 technologies. Today 90% of all our users use Guacamole to access their machines via VNC and SSH and we’re working hard on bringing RDP into that statistic soon.