When the machine that needs to be accessed by SSH is located behind a NAT router or a firewall that allows only connections that have been established by the internal machine, an SSH Tunnel is a simple way to accomplish that. It creates an outbound connection to a public server, through which SSH access can be tunneled.

For this example, lets think of a machine ‘client’ behind a regular NAT router in an office space and a server ‘server’ with a public IP accessible over the internet. On the machine ‘server’, the clients ssh public key is installed for the user ‘server-user’. On the ‘client’ machine, a ssh public key is installed, which ssh private key is stored on the ‘server’ machine. This of course works without public and private Keys as well.

From the client machine, issue the following:

client-user@client ~$ ssh -v -N -R 7000:localhost:22 server-user@server

From the SSH manual page, edited for simplicity and relevance to this post. Please consult `man ssh` for further details:

-v: Be verbose. Its nice to add that in this case to see whats going on, as otherwise no output is given.
-N: Do not execute a remote command, used here for port forwarding.
-R: [bind_address:]port:host:hostport - Specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side.

This opens up the port 7000 on ‘server’. If you connect to this port using ssh, you will be forwarded to port 22 on the ‘client’ machine. You can check for the open port on ‘server’ with:

server-user@server ~$ lsof -i -P | grep 7000
sshd      8331 root    7u  IPv6 532052      0t0  TCP localhost:7000 (LISTEN)
sshd      8331 root    8u  IPv4 532053      0t0  TCP localhost:7000 (LISTEN)

Now you can connect to the ‘client’ machine by issuing the following command on ‘server’:

server-user@server ~$ ssh client-user@localhost -p 7000

As soon as somebody is logging into the ‘client’ machine, you will see output similar to the following in the clients ssh terminal:

debug1: channel 0: free: ::1, nchannels 1
debug1: client_input_channel_open: ctype forwarded-tcpip rchan 2 win 2097152 max 32768
debug1: client_request_forwarded_tcpip: listen localhost port 7000, originator ::1 port 59172
debug1: connect_next: host localhost ([]:22) in progress, fd=4
debug1: channel 0: new [::1]
debug1: confirm forwarded-tcpip
debug1: channel 0: connected to localhost port 22

To stop the connection on the client, all you have to do is hit CRTL+C to stop the running ssh program.

This is only a temporary solution, perfect for non-recurring logins. For a more permanent solution, you might want to look for setting up OpenVPN.