SSH reverse tunneling

Want an easy way to SSH to a device behind a firewall but don’t want to set up a VPN? Welcome to the pragmatic man’s approach - Reverse SSH tunneling

Concepts

Skip the concepts, jump to the example.

Secure SHell

We’ve all used that. By formal definition a

cryptographic network protocol

Or simpler

a way to safely connect to a machine that (usually) isn’t the one you’re typing on

For example when I run ssh alan@32.42.53.12 I’m creating an SSH connection to 32.42.52.12 as the user alan.

SSH tunnel

So what’s an SSH tunnel and how does it differ from a connection?

The analogy with traffic can help here to a certain point. A road (connection) is the thing you build to connect two towns. You don’t build tunnels for the sake of tunnels but for the sake of roads.

You construct a tunnel to help the road pass an obstacle it couldn’t pass alone.

Let’s try to see what else can fit that definition of a tunnel except a whole in a mountain.

How about a ferry?

When you board a ferry it’s acting as a tunnel for the road. It’s extending the road to where it normally couldn’t go. So the ferry is a tunnel from the point of view of the road.

But the ferry is also running on its own naval route (connection) between two docks. So a connection (road) is being tunneled through another connection (naval route of the ferry).

An SSH tunnel is an SSH connection that serves as a ferry for other SSH connections allowing them to reach places they normally couldn’t.

Reverse SSH tunnel

What defines a direction of a tunnel?

The direction of a tunnel is defined by the direction of the ferry compared to the dock which created the naval route.

Say dock A wants to have a ferry line with dock B. They buy a ferry, do all the bureaucracy and cars are now flowing from A->B. This is a normal tunnel.

A reverse tunnel is when the dock A set’s everything up but the ferry is only taking people from B->A.


                           +-------->
                           Set up the ferry
                           Maintain the naval route
                           Keep the ferry running
                           +-------->

       Dock A                              The sea                           Dock B
  +---------------------+             +------------------+            +------------------+
  |                     |   FERRY     |                  |            |                  |
  |                     +---------------------------------->          |                  |
  |                                                                   |                  |
  |                    <----------------------------------------------+                  |
  |                                                                   |                  |
  |                     +---------------------------------->          |                  |
  |                     |             |                  |            |                  |
  +---------------------+             +------------------+            +------------------+



                       <--------------+
                        Cars riding towards the
                        original ferry dock


Does it make sense for Dock A to do this?

Yes if it’s surrounded by cannons that will shoot down every ferry or car that tries to reach it by any other means.

Well… That’s at least why it makes sense in computer networking :)

In more technical terms:

A reverse ssh tunnel is a method of SSH-ing to a computer (dock A) behind a NAT (cannons) by using an external server (the sea) the computer (dock A again) created a reverse tunnel on (naval route).

Hm…

That doesn’t seem tremendously clear. Let’s try with an example.

Example

Goal: SSH to a machine behind a NAT from the outside.

I prepared my example machines to show the concepts.

Local machine

  • The machine we want to SSH to behind a NAT
  • A virtual machine in bridge mode with Lubuntu 18.04

External machine

  • Something that can’t ssh to the local machine because of a firewall
  • It could connect if it was in the same network
    • External machine’s ~./ssh/id_rsa.pub is in Local machine’s ~./ssh/authorized_keys
  • A cloud server instance, can’t access the local subnet

Tunneling server

  • The server with a routable address
  • Accessible from the local machine
    • /~.ssh/id_rsa.pub from the local machine is in ~/.ssh/authorized_keys on the server
  • A cloud server instance, can’t access the local subnet

Commands

External machine (IP not important)

ssh-keygen 

Local machine (192.168.1.118)

ssh-keygen
# Move External machine:/~.ssh/id_rsa.pub to ~/.ssh/authorized_keys

Tunneling server (159.65.115.142)

# Move Local machine:/~.ssh/id_rsa.pub to ~/.ssh/authorized_keys
echo "GatewayPorts yes" >> /etc/ssh/sshd_config
systemctl restart sshd

Local machine (192.168.1.118)

sudo apt-get install ssh
# This is the user we'll be logging in from the External machine
echo $USER
# user
ssh -nNT -R 9000:localhost:22 root@159.65.115.142

External machine (46.101.239.231)

ssh -p 9000 user@159.65.115.142 

Graphically presented

   Local machine                      Tunneling server               External machine
(behind  a firewall)                (routable address)              (IP not important)
   192.168.1.118                      159.65.115.142
+---------------------+             +------------------+            +------------------+
|                     |       TUNNEL|:22               |            |                  |
|                     |---------------------------------->          |                  |
|                                                     :9000         |                  |
|       localhost:22 <----------------------------------------------+                  |
|                                                                   |                  |
|                     +---------------------------------->          |                  |
|                     |             |                  |            |                  |
+---------------------+             +------------------+            +------------------+

Debugging connections

For debugging or insightful experimentation try checking the command below before or during an active connection.

~# netstat -plant4 | grep ssh
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1749/sshd
tcp        0     36 95.179.161.87:22        85.179.40.72:57218      ESTABLISHED 1483/sshd: root@pts 
Written on September 29, 2018