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

By: ( +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 ( ( 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: ( ... which lands you at:

The TightVNC team have a client program Remote Ripple (which seems to not support SSH tunneling) at ( and

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 (

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


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: (

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.

« Scientists looking for a Giant Elephant at the center of the galaxy; Taking pictures of Black Holes Make Live: PiKon Raspberry Pi Telescope »
2016 Election Acer C720 Ad block AkashaCMS Amazon Amazon Kindle Amazon Web Services America Amiga and Jon Pertwee Android Anti-Fascism AntiVirus Software Apple Apple Hardware History Apple iPhone Apple iPhone Hardware April 1st Arduino ARM Compilation Artificial Intelligence Astronomy Astrophotography Asynchronous Programming Authoritarianism Automated Social Posting AWS DynamoDB AWS Lambda Ayo.JS Bells Law Big Brother Big Finish Bitcoin Mining Black Holes Blade Runner Blockchain Blogger Blogging Books Botnets Cassette Tapes Cellphones China China Manufacturing Christopher Eccleston Chrome Chrome Apps Chromebook Chromebox ChromeOS CIA CitiCards Citizen Journalism Civil Liberties Clinton Cluster Computing Command Line Tools Comment Systems Computer Accessories Computer Hardware Computer Repair Computers Cross Compilation Crouton Cryptocurrency Curiosity Rover Currencies Cyber Security Cybermen Daleks Darth Vader Data backup Data Storage Database Database Backup Databases David Tenant DDoS Botnet Detect Adblocker Developers Editors Digital Photography Diskless Booting Disqus DIY DIY Repair DNP3 Do it yourself Docker Docker MAMP Docker Swarm Doctor Who Doctor Who Paradox Doctor Who Review Drobo Drupal Drupal Themes DVD E-Books E-Readers Early Computers Election Hacks Electric Bicycles Electric Vehicles Electron Emdebian Encabulators Energy Efficiency Enterprise Node EPUB ESP8266 Ethical Curation Eurovision Event Driven Asynchronous Express Face Recognition Facebook Fake News Fedora VirtualBox File transfer without iTunes FireFly Flickr Fraud Freedom of Speech Front-end Development Gallifrey git Github GitKraken Gitlab GMAIL Google Google Chrome Google Gnome Google+ Government Spying Great Britain Heat Loss Hibernate Hoax Science Home Automation HTTP Security HTTPS Human ID I2C Protocol Image Analysis Image Conversion Image Processing ImageMagick In-memory Computing InfluxDB Infrared Thermometers Insulation Internet Internet Advertising Internet Law Internet of Things Internet Policy Internet Privacy iOS Devices iPad iPhone iPhone hacking Iron Man iTunes Java JavaScript JavaScript Injection JDBC John Simms Journalism Joyent Kaspersky Labs Kindle Kindle Marketplace Lets Encrypt LibreOffice Linux Linux Hints Linux Single Board Computers Logging Mac Mini Mac OS Mac OS X Machine Learning Machine Readable ID macOS MacOS X setup Make Money Online March For Our Lives MariaDB Mars Mass Violence Matt Lucas MEADS Anti-Missile Mercurial MERN Stack Michele Gomez Micro Apartments Microsoft Military AI Military Hardware Minification Minimized CSS Minimized HTML Minimized JavaScript Missy Mobile Applications Mobile Computers MODBUS Mondas Monetary System MongoDB Mongoose Monty Python MQTT Music Player Music Streaming MySQL NanoPi Nardole NASA Net Neutrality Network Attached Storage Node Web Development Node.js Node.js Database Node.js Testing Node.JS Web Development Node.x North Korea npm NVIDIA NY Times Online advertising Online Community Online Fraud Online Journalism Online Photography Online Video Open Media Vault Open Source Open Source Governance Open Source Licenses Open Source Software OpenAPI OpenVPN Palmtop PDA Patrick Troughton Paywalls Personal Flight Peter Capaldi Phishing Photography PHP Plex Plex Media Server Political Protest Postal Service Power Control Privacy Production use Public Violence Raspberry Pi Raspberry Pi 3 Raspberry Pi Zero ReactJS Recaptcha Recycling Refurbished Computers Remote Desktop Removable Storage Republicans Retro Computing Retro-Technology Reviews RFID Right to Repair River Song Robotics Rocket Ships RSS News Readers rsync Russia Russia Troll Factory Russian Hacking Rust SCADA Scheme Science Fiction SD Cards Search Engine Ranking Season 1 Season 10 Season 11 Security Security Cameras Server-side JavaScript Serverless Framework Servers Shell Scripts Silence Simsimi Skype SmugMug Social Media Social Media Warfare Social Network Management Social Networks Software Development Space Flight Space Ship Reuse Space Ships SpaceX Spear Phishing Spring Spring Boot Spy Satellites SQLite3 SSD Drives SSD upgrade SSH SSH Key SSL Stand For Truth Strange Parts Swagger Synchronizing Files Telescopes Terrorism The Cybermen The Daleks The Master Time-Series Database Tom Baker Torchwood Total Information Awareness Trump Trump Administration Trump Campaign Twitter Ubuntu Udemy UDOO US Department of Defense Virtual Private Networks VirtualBox VLC VNC VOIP Vue.js Web Applications Web Developer Resources Web Development Web Development Tools Web Marketing Webpack Website Advertising Weeping Angels WhatsApp William Hartnell Window Insulation Windows Windows Alternatives Wordpress World Wide Web Yahoo YouTube YouTube Monetization