How to secure VNC with SSH

The big problem with VNC is lack of security for remote access. One way to fix this problem is to tunnel the client to server connection through SSH. As usual with secure communication there are right ways and wrong ways to do the job.

Let us start with the server side. Assume that the machine that runs Xvnc sits on the Internet (e.g., there is no firewall protecting it from the jungle out there) and we need to run the Xvnc server on the machine. First, we need to restrict the range of addresses Xvnc will accept connections from. This is easily accomplished by giving -localhost as an argument to vncserver. Started this way, the server will only listen on address 127.0.0.1 and will be invisible to the outside world, which is exactly what we want. Here's the line I start my Xvnc with:

$ vncserver :7 -geometry 1280x854 -localhost

The -geometry argument is for a nice fullscreen display on a 15-inch PowerBook.

But what good is a VNC server that nobody can connect to, you may ask? That's where SSH comes in to complete the picture. With the server side safely running, making a secure VNC client connection is a two-stage process.

First, we need to establish a secured link to the server. A simple ssh connection is not enough, however, since our goal is to talk to TCP port 127.0.0.1:5907 (in our example above) from the client side. The solution is to forward connections from the client machine to the server side via the tunnel. Here's what works on my laptop:

$ ssh -x -e none -L 5902:127.0.0.1:5907 vnc.server.host

Once the ssh session is established, a connection to port 5902 on the client machine will be pushed by ssh through a secure link and will appear as a connection to port 5907 on the server machine. Why 5902? This has to do with the way VNC uses port numbers. It can only use the range 5901-5909 as displays 1 to 9. It may be possible to teach it to talk out of this range, but that will require rebuilding the client application, something I do not want to do.

Now we are ready for the real fun. Start your favorite VNC client and connect to localhost:2 (that's what 5902 has become, VNC port 2). After being asked for a VNC password (their own little security joke, imho) you should see the X display in a window. If you quit from the VNC client (and exit the ssh connection as well) and connect later (again starting with the ssh connection), you'll see the X display exactly where you have left it before.

Security considerations

It is still possible to connect to the VNC server from the server machine, but presumably the password you have supplied vncserver with is good enough to ward off pesky users.