Using Your Computer Desktop Remotely with VNC

8 minute read

I have a linux box at home which I like because it can act as a file server, a web server, and many other things. Having a desktop unix machine means I can also remotely logon from the outside world via SSH, which is cool. I have normal cheap DSL at home, and my IP addres changes every once in a while. I use DynDNS, a free service, to associate an unchanging name to my ever-changing IP address. A program on my computer notices if my IP address changes, and notifies dyndns to update my name to the new IP address. This means that as long as I use my dyndns name, I can always reach my computer from the outside world.

Editor’s note: for the rest of this description, I’ll use “Windows computer” for the computer you’re sitting at, and “Linux computer” for your unix server you’re trying to connect to.

SSH is only a text window, which is great for most things, but sometimes I want access to graphical programs running on my Linux computer. Originally, I tried to accomplish this with a free X-server on my laptop: Cygwin/X. It really is free, and it really works, and you can really run X-windows programs from your ssh shell and have them show up on your Windows computer. There are some quirks. For one thing, the last part of the install using Cygwin’s “setup.exe” (a distinctive name if I ever heard one) hangs for me on my Windows computer at the end of the install, if I’m using setup.exe version 2.510.2.2, which at the time I’m writing this is the “stable” version. They offer a lot of ways to try and make things work in their troubleshooting, and I tried them all with no success. What did work, however, was to use one of their “unstable” newer versions which worked beautifully (I used version 2.523). Since Cygwin has ported basically almost all standard unix programs to work on a Windows computer, you can also install a lot of other free software if you want. Part of the default install is bash, a much better command prompt than Windows’ standard command prompt cmd.exe. I also installed tcsh because I’m used to it, and the open version of ssh, which is up-to-date, powerful, and free. In addition I installed of course the X-Windows support.

The best way to connect to a Linux computer to start running X programs on your local Windows computer is to first ssh, forwarding the X connections through your secure ssh “tunnel”. To do this, you first start the Cygwin X-server on your Windows computer. It is a “server” because it serves your computer’s resources (display, keyboard, mouse) to programs that want to show up on your computer. Then, with an open cygwin shell (one usually starts up when you start up the Cygwin X-server) ssh to your Linux computer, and be sure to use the “-X” option to make sure you are tunnelling X connections through ssh. Like so:

ssh -X linuxbox.mynetwork.com

Where linuxbox.mynetwork.com is your Linux computer. Then, any X program you start in that ssh session, like for instance xeyes, will show up on your Windows computer, and be running on your Linux computer. This works fairly well for two computers on the same local network.

If you’re much farther away from your Linux computer, for instance somewhere on the internet, this can quickly become way too slow. Also, you have to start everything from scratch every time you reconnnect, because all of your programs will die when you disconnect.

Enter VNC. VNC is more like viewing your desktop on your main Linux computer from afar and being able to control it from afar. The main difference is that the desktop still exists on your Linux/Unix computer and all the programs are still running even if your remote connection disconnects. So you can start up some graphical program, have it do something that will take a long time, disconnect from your Linux computer, and reconnect later to see what happened while you were gone. It also means you don’t have to restart all of your programs everytime you reconnect. It’s really what you usually want.

VNC is also usually much faster than X if you’re far away from your desktop computer. I’ve been connecting to my computer in California from Minnesota, and it’s almost real-time. Almost. X would be much much slower.

To start a vnc session between your Linux and Windows computers, first you need to ssh to your Linux box. You need access to a particular port in a range that starts with 5900, on your Linux box. To do this, we will “tunnel” the ports securely using ssh. VNC uses different display numbers to identify different sessions. We’ll use display 2, because usually that’s free (display 0 is usually the screen you see when you’re logged in on the console of your Linux/Unix machine.) The port you need to access for VNC is number 5900+display, or in our case for display 2, 5902. So we securely forward that port to our Linux machine by using ssh as follows:

ssh -L 5902:linuxbox.mynetwork.com:5902 linuxbox.mynetwork.com

This opens up an ssh session to linuxbox.mynetwork.com, and connects local (Windows) port 5902 (the first number after the “-L”) to port 5902 on linuxbox. This works as long as you can ssh to your Linux computer. You don’t have to do anything else, like open ports in a firewall surrounding your Linux box. ssh does everything. You can also do this with Windows graphical ssh programs. You need to specify an “Outgoing” port forwarding, and 5902 on the linux box, and 5902 on your computer.

Once you get this ssh session open, all you need to do is type

vncserver :2

and you should have started up a new session on display 2. If this is the first time you run vncserver, it will ask you for a password. Use something reasonably secure, like maybe your account password.

To connect to this vnc session, you need a VNC Viewer on the Windows computer. A good free one is TightVNC. Remember, for what I’m describing, you only need the viewer. Usually it’s one self-contained program.

Now, since we’ve tunnelled our port 5902 to the Linux box’s port 5902, to any programs on our Windows computer, our local port 5902 is what we want to access. So when the viewer starts and asks for the computer to connect to, we’ll connect to:

localhost:2

Which is shorthand for saying, “Connect to port 5902 of this very computer”. ssh will then take everything it sees on port 5902 of this Windows computer and make it show up on port 5902 of the Linux box. Like magic. Hopefully, it will ask you for your password, and Voila! A window will open that shows your desktop of your Linux computer.

That’s the main functionality. Now for the finer points. You probably don’t want full 24-bit or 32-bit color being forwarded across the internet, because that’s just slow. So use the following vncserver command instead:

vncserver -depth 16 :2

That will use 16-bit color instead, which if fine for most uses. You can even go really primitive and use a 256-color palette for even faster performance:

vncserver -depth 8 :2

But this kind of sucks.

Another thing: Most likely the VNC session will use a custom Desktop, i.e. a plain vanilla X-session with twm, an old but reliable window manager. If you want to see a normal session, with something like KDE or Gnome, you’ll have to doctor some files. Personally I like KDE, so what I did was to doctor my xstartup file inside the directory ~/.vnc to be like so:

#!/bin/sh
  
xrdb $HOME/.Xresources
xsetroot -solid grey
xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
# twm &
startkde

As you can see, I commented out the line with twm and added startkde. Now when I start a new VNC session, I get a new kde session.

KDE is also cool, because it allows you to take an existing console logon and make it available for remote viewing using VNC. To do this, to the the KDE Control Center, Internet and Network, Desktop Sharing. Check “Allow uninvited connections” and “Allow uninvited connections to control the desktop”. Uncheck “Announce service on the network” and “Confirm uninvited connections before accepting”. You may also want to check the box for “Always disable background image” in the Session tab to speed things up. Also, you might want to choose your port in the Network tab instead of having it assigned automatically, so you always know which port to connect to from the outside world using your ssh tunnel.

The final tweak is probably beyond the scope of this document (or would be even longer than I’m willing to write.) Just be aware that there are a lot of compression options for VNC, especially if you’re using a TightVNC server on your linux box and TightVNC viewer on your remote computer. TightVNC can use JPEG compression for things, which speeds up everything a lot, but can make your desktop look like you’re viewing it through a smudgy window. Both normal compression and JPEG compression can be adjusted by a number from 1 to 9, so you can fine tune how much compression you use to balance speed with prettiness.

Some more tidbits: TightVNC and other programs make available VNC servers for Windows computers too, so you can see and control Windows computers’ desktops remotely. I’ve never tried this and don’t know the security/usability implications. I’m sure there’s also some implementations for MacOSX, because that’s basically Unix underneath too.

ADDENDUM: Apparently, if you have an alias for your network address, (in a ‘hosts’ file perhaps) there will be problems with ssh tunnelling. You may receive an error on your Linux console saying “open failed: administratively prohibited” if you use an alias for your computer in your hosts file.

For instance, when I’m in my house, my Linux computer has a different, local ip address because it’s inside my firewall. I have this called ‘mylinuxbox’ in my hosts file, so I can have a name for what would otherwise just be a local ip address (i.e. 192.168.x.x). If you try to say “ssh -L 5902:mylinuxbox:5902 mylinuxbox” you will get the cryptic “administratively prohibited” error on your Linux console. The correct way to do it is to use the full non-aliased form inside the -L argument:

ssh -L 5902:192.168.x.x:5902 mylinuxbox

where you would replace “192.168.x.x” with whatever your local ip address is.

Updated: