Tunnel VNC over SSH through the internet

One of the things I find most fulfilling about learning technology is the ability to pass along what I’ve learned.  I can also help loved ones migrate from Windows and other proprietary software, to free/libre software like GNU/Linux, and learn how to use their improved system.  This can take the form of looking over their shoulder and showing them how to do things, or temporarily unseating them while I work on things too advanced for their current skill level.  But what if I’m far away?  My father lives on the other side of the continent, but he is very much a computer novice.  When he gets stuck, or needs some administration done, it’s much easier to show him or do it for him than it is to put him through trying to describe what he’s seeing and then attempting to understand my instructions over the phone.

VNC is an excellent solution to this problem.  In combination with a phone call or VOIP call, it’s the next best thing to being there.   It allows me to see his screen, take control of his mouse and keyboard, and show him – “See this?  <wiggling mouse>  Click here.”  It also allows me to zip through administrative tasks myself, and once I’m connected, he doesn’t even have to be home.  I can do what needs to be done and then shut down his computer for him.

But VNC is not a complete solution.  It is, unfortunately, inherently insecure.  A cracker (notice I did not misuse the word “hacker” as the mass media so often does – because an ethical hacker would never do this) could use VNC password cracking software to get your password(s) and then wreak havoc on your computers, or steal personal data from them.  So we need something more secure than VNC so we can use strong encryption, greatly reducing the likelihood of getting victimized by the bad guys/gals.

Enter SSH, or Secure SHell.  We can create an SSH connection between the two computers and then tunnel the VNC data through that connection.  In this way we have a fully encrypted connection with all the advantages of VNC.

For those of you who missed “Ports 101”, this is a good time to explain the concept of computer ports.  Think of your computer as a country somewhere in the world.  Computer ports are like a country’s ports of entry.  Some are on land, and for the sake of the example we’ll call these TCP ports.  Others are seaports, and we’ll call those UDP.  Together they represent locations where information and goods can be exchanged with the rest of the world.  You have 65,536 land ports (TCP) and 65,536 seaports (UDP), numbered from 0 to 65535.  Some of these ports are officially reserved for special government uses, and others are accessible to the public.  In order to keep out people who wish to do you harm, these ports must be guarded, and only let authorized traffic through.  This is your firewall’s job.  Your team of border guards is your firewall.  You can tell them to stop all incoming traffic, for example, which is technically safest but then you’re also cut off from outside goods and services.  Or you can tell them to allow only certain kinds of inbound and outbound traffic at certain designated ports, and only open those ports when you know you’ll be sending or receiving something beneficial.

Now, this tutorial will assume a few things for the sake of brevity and clarity.  First, I will assume you are connecting from one GNU/Linux system to another GNU/Linux system.

Second, I will write as though you want the SSH service on its official (usual) port: 22, and VNC on its official port: 5900.  For security’s sake, you’re well advised to change these.  Precisely because they’re “official” ports, crackers know to look for these services on these particular ports – so it’s a good idea to use different port numbers to make the services harder for them to find.  Crackers frequently use programs that scan only the relatively small number of official ports so see if they’re open.  Scanning all of your tens of thousands of ports takes significantly longer, and some won’t invest the time and effort on it – they’ll look for someone else with easier pickings.  So ideally, you’ll choose port numbers that aren’t officially assigned to anything, such as ports 49152 to 65535.  (See here for a list of official port assignments.)  Warning:  This will only provide a modicum of protection from more persistent crackers, so don’t think you’re safe just because you picked port 50000; if you leave it open all the time and don’t combine this with other security measures, you’re inviting trouble.

Third, for reasons stated above, I’ll assume you’ve already devised a way to temporarily open ports 22 and 5900 on the server (target system).  As I mentioned, you can set them up to be open all the time, but this represents an unnecessary security risk.  They’ll be two holes in the person’s firewall just begging for some cracker to find and exploit.  It’s far better to open them only when necessary, and connect right away.  Once you’re connected, those holes are filled by your own connection, so others can’t use (or abuse) them.  Opening the ports the first time will require a little walkthrough for the person at the other end, and directions will depend on their setup – whether they are using a router, and if not, which distribution of GNU/Linux they are using.  (For details, consult the router’s user manual or the documentation for their distribution.)  After that, again depending on their setup, you may be able to use an automated script for this task – but that’s another tutorial for another day.

Fourth, I’ll assume you want to use password authentication.  This may seem obvious at first blush but there’s actually a better way to do it – SSH keys.  With SSH keys you don’t need passwords, and there is an extra level of security introduced because it’s even harder for a cracker to impersonate you and get unauthorized access.  But again, this is a bit of a process unto itself and is best saved for another tutorial.

Lastly, I’ll assume the server has the SSH server and at least one VNC server installed.  This isn’t much of a stretch, since many GNU/Linux distributions come with these installed by default.  Here I use ‘sshd’ (from the ‘openssh-server’ package) and ‘krfb’ (which has its own package ‘krfb’).  Your client computer also needs an SSH client and VNC client, which often come installed by default as well; here I use ‘krdc’ (package ‘krdc’) and ‘ssh’ (package ‘openssh-client’).  If any of these are missing, use your GNU/Linux distribution’s package manager to install them.

The first thing to do after the ports are open, is to have the person open a terminal (on Debian GNU/Linux KDE version this is Kmenu -> System -> Konsole – Terminal Program).  Now they will need to switch user to root.  Then they’ll start the ssh server on the specified port – in this case, port 22.  (If they’re using Ubuntu or one of its derivatives, ‘su’ doesn’t work – they’ll need to skip the first part and just put “sudo ” before the third line below.):

dad@jupiter ~ dad$ su
root@jupiter ~ dad# /usr/sbin/sshd -p 22
root@jupiter ~ dad#

Lastly, you’ll need their external IP address in order to find their computer on the internet.  The easiest way to do this is to have them point their web browser to http://www.whatismyip.org and read the number to you.

Now it’s time to do some things on the client.  You’ll need to open a terminal.  The following command starts the ssh client, creates the tunnel, specifies several settings, and launches the VNC server on Dad’s system, all in one fell swoop.  (This is all on one line.)

g33kgrrl@saturn ~ g33kgrrl$ ssh -p 22 -L 5900:localhost:5900 dad@ 'krfb -display :0'
g33kgrrl@saturn ~ g33kgrrl$

Let me break this down so you can modify it to your needs.  ‘ssh’ starts the ssh client.   ‘-p’ tells it to connect on the server SSH port you specify, in the format ‘-p serverSSHport‘ – here, it’s 22.  ‘-L’ means forward the following client port to the following computer and the following server port.  The next bit gives those specifics in the format ‘clientVNCport:localhost:serverVNCport‘.  In this case, it’s just going straight from client VNC port 5900 to server VNC port 5900.  Next is the username of the person I’m helping and the IP address of his computer, which I obtained above, in the format ‘username@IP-address‘.  Next, enclosed in apostrophes, is the command I’d normally need to type to start the VNC server from the terminal, which in krfb’s case is ‘krfb’, along with any specifications it needs; usually you’ll at least want to specify which display to use with ‘display :0’ (that’s a ‘zero’ not a letter ‘O’).

After you run the above command, it will ask you for the password the person is using on their computer.  Presumably, if they already don’t mind you having control of their system they won’t mind you having their password either.  (There’s a more elegant way, involving creating a separate account for you on their system, but I’m trying to keep things simple here.)

After entering the password, the VNC server should start on the server machine.  If you’re using krfb as the VNC server, the person at the server end should now notice the kfrb window popping up on their computer.

krfb - initial screen

krfb - initial screen

IMHO (In My Humble Opinion), the easiest way here is to have them click the ‘Configure” button at the bottom.  It will give them a window like this:

krfb - configure screen

krfb - configure screen

Have them put an X in ‘Allow uninvited connections’

Make sure ‘Announce  service on the network’ is unchecked

Make sure ‘Confirm uninvited connections before accepting’ is unchecked

Make sure ‘Allow uninvited connections to control the desktop’ is checked

In the ‘Password’ box, have them enter their login password

krfb - configure connections

krfb - configure connections

They can click ‘Apply’ and ‘OK’ – krfb is now all set up so that the next time you connect to them, they won’t have to configure it at all.  Lest you worry about the security of this setup, I should mention that krfb will exit when they shut their system down, so someone has to manually launch it in order to start it up again.  And we’re only opening the ports when we’re about to connect to them, so as long as their firewall is both enabled and properly configured (you will double-check it to be absolutely sure, won’t you?), it isn’t something to lose sleep over.

Meanwhile, back at the client, you can launch your VNC client.  As mentioned previously, I’m using krdc.  Its location in the menu will vary (in Debian it’s Kmenu -> Internet -> Krdc – Remote Desktop Connection), or you can just type ‘krdc’ at a terminal.  It will give you a window that looks like this:

krdc - initial screen

krdc - initial screen

In the box, you’ll need to give it the protocol (vnc), the server’s IP address, and the server port, in the format vnc://serverIP:serverVNCport :

krdc - configure connection

krdc - configure connection

Click ‘Connect’.

It should briefly flash a window saying it’s ‘authenticating.’  Next it will say that ‘Access to the system requires a password.’  Enter the person’s login password.

Now krdc should open a large window in which you can see the server’s desktop.  I always like to click ‘Scale’ at the top left so their whole screen fits neatly in the krdc window.

Congratulations!  You are now the master of your own destiny — or at the very least, of this person’s desktop.  Well, sometimes ya gotta start small.


4 thoughts on “Tunnel VNC over SSH through the internet

  1. Pingback: Adventures in GNU/Linux remote installation – or not « g33kgrrl's garage

  2. Hi!

    A couple of comments that we may have already talked about at the Ontario Linux Fest:

    – Instead of asking for the external IP every time, it is quite convenient to register with a dynamic DynDns or a similar service, that way you can always use the same name. e.g. dad.homeip.net

    – For people that use cable/DSL modems with firewalls or routers, they’ll need to forward the ports. While this task is easy for tech users like us, it is sometimes a pain for non tech users. There is a way to keep their computer safe with all the ports closed and still achieve the same results:

    Reverse SSH tunneling:
    (Here I assume that your server is running on port 51022 and his server is running on 52022 and that you created a “dad” account for him on your computer)
    From their side they can do the following (I actually configure putty for them so they don’t even have to type this):

    > ssh -p 51022 -R 52022:localhost:52022 dad@g33kgrrl.homeip.net

    You can then ssh to his box and do whatever you want.

    ssh -p52022 dad@localhost -R 5900:localhost:5900

    – Finally: To actually tunnel VNC over ssh you don’t have to open the VNC port on the firewall. Once you tunnel with 5900:localhost:5900, you can just start the VNC server on their side (I use x11vnc) and connect using vnc://localhost:5900

    I hope you can make to the presentation next Monday.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s