Java VNC over SSH

My dad has two computers in different parts of the state. He recently got this computer-controlled weather station (sorry, no link at this point) that records all sorts of information about the outdoor and indoor temperature. The station’s software has a “Remote Publishing” feature and e-mail reports, but he wanted the ability to actually see what it’s showing in near-realtime.

He came across the service of GoToMyPC, and thought it was the coolest thing since sliced bread. And I’ll grant that it is pretty slick – you install the server software on your machine(s), and the software will keep in touch with GoToMyPC’s central servers, letting them know of your on/offline status. From any java-enabled web browser, you can then go to the GoToMyPC website, and you can connect to any of your online PCs. It even works through NAT on both ends! (I’m guessing it’s doing something through the central servers in that case, but I’m not sure).

The downside? It’s $19.99/month. Yeow. I’m thinking, That’s just, like, VNC… with a Java client… secured… shouldn’t that be basically free? (FYI, they use a Citrix client, not VNC)

His birthday is in a week, so what better excuse to tinker around with getting the same effect, using free/open source software?

So, we can split this up into a few things that need to be in place:

  1. VNC Server
  2. SSH Tunneling to the VNC Server
  3. Java client

VNC Server
There are a whole bunch of software packages available now for VNC. The servers I’m setting up are Windows machines, so I decided to go with UltraVNC. Why UltraVNC? Mainly because I’m familiar with it. I used it for helpdesk stuff at the University of Michigan, and it’s used at my current place of employment as well. It has a few well-integrated features, like file transfer and chat. And the system tray icon , while somewhat creepy, is very simple to describe to people who are unfamiliar with the program and need to do something like change a password.

  1. Download UltraVNC (http://www.ultravnc.com) on the machine that you want to be remotely accessible. Getting the Setup package will probably make things simpler than the plain ZIP archive.
  2. Install UltraVNC. Leave most options at their defaults. At the “Select Components” screen, you can probably deselect “DSM Encryption Plugin” and “UltraVNC Repeater.” We’ll be using SSH for our encryption. Check “Register UltraVNC Server as a system service” and “Start or restart the UltraVNC service” on the Additional Tasks screen.
  3. When installation is nearly complete, you should receive a prompt that there is no default password set. At this point, the installer will show you the “Default Local System Properties” screen.
  4. Change the default settings to be like the following:

    We’ve made it so that only loopback connections are allowed (so that only SSH-tunneled connections are allowed, basically). The other options are mostly up to your preference. Also, be sure to set a password. You might notice that my password is very short: in fact, it is just vnc. Why the heck am I telling you my password? Because in order to use it, you’d have to have access to my machine (loopback only, remember?). If you’ve got access to my machine (physical or via SSH), you can probably view my registry, and the VNC password is stored there. It’s “encrypted,” but every VNC server uses the same type of encryption and the same encryption key. So I might as well just tell you. This is just to further emphasize my point that we’re not going to rely on VNC to handle any encryption. Besides, you might find it useful to have the same password as me in one of the steps below.

  5. Hit OK. This will start the service.

SSH Tunneling
We now have a VNC server that has absolutely no security, other than the fact that it can only be accessed from the machine it’s running on. Now we need to find a way to let people in over the Internet in a secure way. Enter SSH.

For some background on SSH Tunneling, check out http://www.afp548.com/articles/security/ssh-tunnels.html. There are some great illustrations there. Basically, an SSH Tunnel allows you to create a secure “tunnel” through an otherwise secure network – in our case, the Internet (which is pretty much the least secure of all networks).

In order to set up this tunnel, we need to set up an SSH server. There is a port of OpenSSH for Windows using Cygwin – unfortunately, in my experience it has proven somewhat flaky. I reccently discovered freeSSHd, a closed-source SSH server for Windows. It lets you have a different set of users than your Windows ones, it has a graphical control panel, and, as you could hopefully tell by its name, it is available free of charge.

  1. Download freeSSHd (http://www.freesshd.com).
  2. Install it. Say “Yes” to both of the post-install questions (Create a service and create the keys).
  3. You will now have a freeSSHd icon in your system tray. Click it once to bring up the adminstration tool.
  4. Click on “Users,” and add a new user. Give it a name (I used “sshtunnel”), and select “Password stored as SHA1 hash” as your Authorization. Then you can enter a password. Uncheck all of the “User can use” options, and hit Apply.
  5. Enable the “Tunnel” option in the Users list for the user you just created. Your screen should look like this:

    There’s an apparent bug in the program where if you set the “Tunnel” option outside of the Users list, it doesn’t get saved properly. That’s why we didn’t set it above, but instead set it here.

  6. Click on Apply and Save.

Now we’ve got an SSH server running. However, if you’re running your computer behind a router or other NAT device, there’s a little bit of extra work we need to do. We need to forward on incoming SSH connections to our server computer. How this is done varies from router to router… Often it can be found under the “Port Forwarding” option, though. You may also want to investigate options for reserving IPs for specific computers. This is sort of beyond the scope of this tutorial. Basically, you need to reserve an IP for your server computer, then make sure to forward incoming TCP connections on port 22 to port 22 of your server computer. If you’ve got multiple computers behind the router that you want to access remotely, you need to set your SSH servers to listen on different ports, forward on the appropriate ports, and set your ssh client to connect on the alternate port (more info on that below).

Java Client
3SP put out an open-source Java VNC Client (under their SSHTools project) that automatically tunnels through ssh, taking care of a lot of the intermediate steps that were once annoying/difficult to comprehend. We’re going to put this applet on a webpage to simplify access to our remote server. Note – I leave it up to you to secure your webpage. I would recommend using some sort of authentication at the webpage level to make sure that the fact you’re running a VNC server isn’t advertised openly on the web.

  1. Get the latest SSHVnc-Applet from the SSHTools website (http://sourceforge.net/projects/sshtools/). Grab the .zip version if you’re running on a Windows machine.
  2. Unzip the files somewhere on your hard drive. There’s a sample html file that shows how to use the applet in a webpage. I didn’t find the sample adequate to my needs, so I modified it to make the following changes:
    • Automatically connect to a host.
    • Resize the size of the applet to fill the webbrowser window.
    • Get rid of text and graphics above and below the applet.

Here’s the html file I used (save this as “yourhost-sshvnc-applet.html”):

<html>
<head>
<title>SSHVnc Applet</title>
</head>
<body style="margin: 0; padding: 0">

<applet width="99%" height="99%"
archive="SSHVncApplet-signed.jar,SSHVncApplet-jdkbug-workaround-signed.jar,SSHVncApplet-jdk1.3.1-dependencies-signed.jar"
code="com.sshtools.sshvnc.SshVNCApplet" codebase="." style="border-style:
none; border-width: 0; padding: 0; margin: 0">
<param name="sshapps.connection.host" value="192.168.1.1" />
<param name="sshapps.connection.userName" value="sshtunnel" />
<param name="sshapps.connection.authenticationMethod" value="password" />
<param name="sshapps.connection.connectImmediately" value="true" />
<param name="sshvnc.connection.vncHostDisplay" value="localhost:5900" />
<param name="sshvnc.connection.useCopyRect" value="true" />
<param name="sshvnc.connection.compressLevel" value="9" />
<param name="sshvnc.connection.cursorUpdates" value="1" />
<param name="sshvnc.connection.eightBitColors" value="true" />
<param name="sshvnc.connection.encryptedVncPassword" value="91bc75c18d3d85a7" />
</applet>

</body>
</html>

Things to modify in this file – replace “192.168.1.1″ with your IP address or hostname (to find out your IP address, you can just go to http://www.whatismyip.com. Note that this is not your internal IP address, if you’re behind a router). Replace “sshtunnel” with your ssh username. And the encryptedVncPassword (91bc75c18d3d85a7) is the encrypted value of the password “vnc”. So if you used that as your VNC password, you can use this html file to avoid entering an extra password. If you decided to take the high road and use a unique password, you can find it out by going to your registry, browsing to HKEY_LOCAL_MACHINE\SOFTWARE\ORL\WinVNC3\Default, and checking out the Password value. Copy down the hex values shown in the Data field minus the spaces, and you’ve got your “encrypted” VNC password. Alternatively, you can just clear that line from the file, and be prompted for your VNC password.

There are other options available, too. Check out the instructions.htm file that comes with SSHVnc-applet.

To test it out, double-click on the html file you created, and you should get a Java VNC window. Say “yes” to any security questions, and enter your SSH user’s password. You should see your computer screen shortly. If you don’t, try restarting your computer, and making sure all the services are running.

If everything worked, you’re able to put this html file on the web, along with all the appropriate .jar files, and you’ve got a fully-functioning remote VNC file!

As usual, I hope this has been helpful to you. If you have any questions, comments, or whatever, make like a tree and leave ‘em.