Using VNC to access remote desktop on Raspberry Pi or other computer behind a NAT firewall

By: (plus.google.com) +David Herron; Date: Wed Jun 28 2017 17:00:00 GMT-0700 (PDT)

Tags: Raspberry Pi » VNC » Remote Desktop

Connecting to a remote computer is very powerful, because you can access remote files, remote applications, and so forth. Those of us building home automation or other Internet of Things devices sometimes install those devices at a remote location behind a NAT firewall, and then need to access the computer's desktop environment. For example, I have a Beaglebone Black at a remote site over 3000 miles away, and needed to run Firefox on the BBB to access some things. It's not feasible to go to the device in person, therefore the question is how to access the remote desktop.

VNC is the primary choice for this purpose. It has a lower bandwidth requirement than running X11 over the Internet, plus you avoid the complexity of installing an X11 server on Windows or Mac. Simply install a VNC client, instead. The key hurdle is getting past the NAT router.

Set up a VNC server

On the BeagleBone Black or Raspberry Pi or an Ubuntu desktop run this to install tightvncserver ( (www.tightvnc.com) http://www.tightvnc.com/). The website has binaries for other systems like Windows.

$ sudo apt-get install tightvncserver

Depending on your system you may need to do this instead:

sudo apt-get install xorg lxde-core lxde-icon-theme tightvncserver

This command ensures an X11 server is installed along with the lightweight LXDE desktop environment.

Next we set up a tightvncserver configuration as so:

$ tightvncserver :1

The string :1 is a display number, and can be any number you like. It will ask you for a password for remote clients.

When you're done, the VNC server session can be killed this way:

$ tightvncserver -kill :1

From there starting the server just requires:

$ tightvncserver :1

Set up a VNC client

For the next step we need a VNC Client. There's a large variety available, even for mobile devices. Put "VNC Client" into the application store for your computer. A key for this particular task is ensuring the VNC client can run over an SSH tunnel, or even includes SSH tunneling capability.

I used ChickenOfTheVNC which is a good free VNC client for Mac OS X. Go to: (chicken.sourceforge.net) http://chicken.sourceforge.net/ ... which lands you at: https://sourceforge.net/projects/chicken/

The TightVNC team have a client program Remote Ripple (which seems to not support SSH tunneling) at (itunes.apple.com) https://itunes.apple.com/ru/app/remote-ripple/id1071186450?l=en&mt=8 and https://play.google.com/store/apps/details?id=com.glavsoft.rrviewerpro&referrer=utm_source%3Dtightvnccom%26utm_medium%3Dlink%26utm_content%3Dmaindl-link%26utm_campaign%3Drrviewer

Testing the VNC server locally

The first thing is to test a local connection. Run the tightvncserver on your target computer as above, then run the VNC client on your client computer.

Connection setup with ChickenVNC connecting to `tightvncserver :2`

The connection setup details will vary a bit from client to client. In ChickenVNC it asks for the hostname (or IP address) of the target computer. In others it will as for a URL like vnc://IP-ADDRESS:portNumber. In this case I started tightvncserver on display number 2, which corresponds to port number 5902, as shown in the ChickenVNC window.

ChickenVNC asking for the password

It then asks for the password.

ChickenVNC showing the Raspberry Pi

And then voila, a desktop for your remote computer shows up. This should work relatively well since it's all on the local network.

Congratulations, if you got this far you have successfully set up VNC server and client. It's time to take this to the next level and enable a remote VNC connection.

SSH'ing into a remote computer behind a NAT router

The next step is a little complex if only because the various NAT routers do this in infuriatingly different ways.

A NAT router is what keeps your home network relatively safe. "NAT" stands for Network Address Translation. It's the feature that assigns a local network address for devices on your home network, without having to assign IP addresses from a global pool. A NAT router instead maintains a local network such as 192.168.1.NNN from which it hands out IP addresses to local devices. The NAT router then translates network addresses between the ones it assigned locally to IP addresses on the Internet.

In other words, NAT routers perform a bit of magical subterfuge. Local devices aren't directly connected to the Internet. The connect instead to the local WiFi router. The NAT router connects to the Internet instead.

Most importantly, NAT routers allow devices on its local network to connect OUT to the Internet, but they do not allow outside devices to connect IN to devices on the local network.

This is great for the typical use-case of people browsing the Internet. They simply turn on their device, connect to the local WiFi, and start browsing.

In this project we're doing the opposite. We want a computer outside our local network to connect to a VNC session on a computer on our local network. To do this we must do a bit of virtual tunneling.

Opening ports on the router

Most NAT routers (a.k.a. WiFi routers) let you set up port forwarding. This means a port will be open on the public side of the router, and any connections to that port will be connected to a port on a computer on the local network.

In other words -- we want to support an SSH connection to a local computer. We want the router to have a public port that then connects to the SSH port on the target computer. Additionally, the public port probably should not be on the standard SSH port (port 22) because miscreants have scripts scanning for open SSH ports to try and hack into remote computers.

In the admin area of your router, hunt around for the port forwarding section. Define a connection with these characteristics:

  • Public TCP port number 2222
  • Private IP address matching your local computer
  • Private TCP port number 22 (for SSH)

With that setup, any connection to port 2222 of your public IP address will go to port 22 on the local computer.

At this point it is also useful to have a fixed IP address for your home network, or to use a Dynamic DNS service. Otherwise, your public IP address will be reassigned at the whim of your internet service provider and you'll always have to check what's your current IP address. Setting up fixed IP addresses or dynamic DNS is beyond our scope. (I have a fixed IP address thanks to the geek-friendly service at (sonic.net) sonic.net)

The next step is taking your laptop computer to a remote place, and SSH'ing into the target computer. Like:

$ ssh -l YOUR-USER-NAME -p 2222 YOUR-PUBLIC-IP-ADDRESS

If all went well, you should be able to log in using SSH.

Connecting to the remote VNC -- SSH tunneling

In the previous step you could have opened up the VNC port (port 5901) to forward to your computer. You would then connect the VNC client to YOUR-PUBLIC-IP-ADDRESS and voila have the VNC session. But, that leaves you vulnerable to security intrusions if VNC security is weak.

Instead we can make an SSH tunnel. Connecting the VNC client through an SSH session means it is encrypted and has other strong protections, especially if you use passwordless SSH. SSH tunnels are extremely useful, for example it's fairly easy to remotely access a MySQL server with an SSH tunnel: (davidherron.com) http://davidherron.com/book-page/4-using-ssh-or-putty-remotely-access-mysql-server

An SSH tunnel sets up a port on the local computer that connect through to a port on the remote computer, passing data back and forth seamlessly.

The command looks like this:

$ ssh -l YOUR-USER-NAME -p 2222 -L5901:localhost:5901 YOUR-PUBLIC-IP-ADDRESS

It's the same as above except for the -L5901:localhost:5901 parameter. This is where the SSH tunnel is described. The 5901 in this case corresponds to the port number for the VNC session, so adjust this as appropriate.

Once you've done this, you tell the VNC client to connect to localhost on port 5901.

ChickenVNC specifying remote connection

You specify the remote connection as so. The connection is named remote but it connects to localhost on port 1.

ChickenVNC connecting to a remote BeagleBone Black

And then voila, it connects to the remote computer. In this case a remote BeagleBone Black sitting behind a firewall.

Unfortunately throughput is very slow. But we must remember that we can even do this is, by itself, amazing.

« Initial notes on using MAX485 based TTL-to-RS485 adapter boards with Arduino or Raspberry Pi Scientists looking for a Giant Elephant at the center of the galaxy; Taking pictures of Black Holes »
2016 Election Acer C720 Ad block AkashaCMS Amiga Android Anti-Fascism Apple Apple Hardware History Apple iPhone Hardware April 1st Arduino ARM Compilation Astronomy Asynchronous Programming Authoritarianism Automated Social Posting Bells Law Big Brother Black Holes Blade Runner Blogger Blogging Books Botnet Botnets Cassette Tapes Cellphones Christopher Eccleston Chrome Chrome Apps Chromebook Chromebooks Chromebox ChromeOS CIA CitiCards Civil Liberties Clinton Cluster Computing Command Line Tools Computer Hardware Computer Repair Computers Cross Compilation Crouton Curiosity Rover Cyber Security Cybermen Daleks Darth Vader Data backup Data Storage Database Database Backup Databases David Tenant DDoS Botnet Detect Adblocker Digital Photography DIY DIY Repair Docker Doctor Who Doctor Who Paradox Drobo Drupal Drupal Themes DVD Early Computers Election Hacks Electric Bicycles Electric Vehicles Electron Emdebian Enterprise Node ESP8266 Ethical Curation Eurovision Event Driven Asynchronous Express Facebook Fake News File transfer without iTunes FireFly Fraud Freedom of Speech Gallifrey git Gitlab GMAIL Google Google Chrome Google Gnome Google+ Government Spying Great Britain Home Automation HTTPS I2C Protocol Image Analysis Image Conversion Image Processing ImageMagick InfluxDB Internet Internet Advertising Internet Law Internet of Things Internet Policy Internet Privacy iOS Devices iPad iPhone iPhone hacking Iron Man Iternet of Things iTunes Java JavaScript JavaScript Injection JDBC John Simms Joyent Lets Encrypt LibreOffice Linux Linux Hints Linux Single Board Computers Logging Mac OS Mac OS X Make Money Online MariaDB Mars Matt Lucas MEADS Anti-Missile Mercurial Michele Gomez Military Hardware Minification Minimized CSS Minimized HTML Minimized JavaScript Missy Mobile Applications MODBUS Mondas Monty Python MQTT Music Player Music Streaming MySQL NanoPi Nardole NASA Net Neutrality Node Web Development Node.js Node.js Database Node.js Testing Node.JS Web Development Node.x North Korea Online advertising Online Fraud Open Media Vault Open Source Governance Open Source Software OpenAPI OpenVPN Personal Flight Peter Capaldi Photography PHP Plex Media Server Political Protest Postal Service Power Control Privacy Production use Public Violence Raspberry Pi Raspberry Pi 3 Raspberry Pi Zero Recycling Remote Desktop Republicans Retro-Technology Reviews Right to Repair River Song Rocket Ships RSS News Readers rsync Russia Russia Troll Factory Scheme Science Fiction Season 1 Season 10 Season 11 Security Security Cameras Server-side JavaScript Shell Scripts Silence Simsimi Skype Social Media Warfare Social Networks Software Development Space Flight Space Ship Reuse Space Ships SpaceX Spring Spring Boot SQLite3 SSD Drives SSD upgrade SSH SSH Key SSL Swagger Synchronizing Files Telescopes Terrorism The Cybermen The Daleks The Master Time-Series Database Torchwood Total Information Awareness Trump Trump Administration Ubuntu UDOO Virtual Private Networks VirtualBox VLC VNC VOIP Web Applications Web Developer Resources Web Development Web Development Tools Weeping Angels WhatsApp Wordpress YouTube