SSH Tunnelling or TCP Forwarding

Posted 4 years, 1 month ago | Originally written on 17 May 2014

This has to rank as the most confusing topic in using the Linux command line. It is even confusing using Fugu because there are three user, host and ports that can be used leading to a lot of possibilities to get it wrong. To the best of my understanding, SSH tunnelling is TCP forwarding - at least as far as the SSH man page goes.

The canonical problem that one would want to solve using tunnelling is to burrow through an intermediate public-facing machine to get to a private machine that shares an network with the public-facing machine. I'll label the three machines CLIENT, TUNNEL and TERMINAL. The goal is to get to TERMINAL from CLIENT through TUNNEL.

The syntax is as follows:

me@home:~$ ssh -f -L [CLIENT_NAME:]NEW_CLIENT_PORT:TERMINAL_NAME:TERMINAL_PORT \
TUNNEL_USER@TUNNEL_NAME [-p TUNNEL_PORT] sleep 10

NEW_CLIENT_PORT is a local port with value over 1023, say 2000.

Brackets ([]) indicate optional parameters:

  • You can omit CLIENT_NAME if it is 'localhost'
  • You can omit -p TUNNEL_PORT if you use SSH (-p 22) unless it is on a non-standard port

Notes:

  • CLIENT_NAME could refer to the hostname or the IP address.
  • The -f argument indicates that this command should be run in the background. You want SSH to return the console so that you can connect to TERMINAL.
  • The sleep 10 command will be run in TUNNEL upon successful connection to TUNNEL. In this case, you have 10 seconds to try to connect to TERMINAL. If 10 seconds elapses before a successful connection then the tunnel will be closed.

Once you are connected to TUNNEL and get back the command prompt type the following:

me@home:~$ ssh TERMINAL_USER@CLIENT_NAME -p NEW_CLIENT_PORT

Example:

CLIENT_NAME = localhost
NEW_CLIENT_PORT = 2000
TERMINAL_NAME = terminal.server.ten
TERMINAL_PORT = 22
TUNNEL_USER = tunneler
TUNNEL_NAME = public.server.ten
TUNNEL_PORT = 22
TERMINAL_USER = terminator
me@home:~$ ssh -f -L 2000:terminal.server.ten:22 [email protected] sleep 10
me@home:~$ ssh terminator@localhost -p 2000

Reference:

SSH man page