Personal website of Martin Tournoij (“arp242”); writing about programming (CV) and various other things.

Working on GoatCounter and moreGitHub Sponsors.

Contact at martin@arp242.net or GitHub.

This page's author

Here’s a little tip on how to tunnel ssh through another machine with the -L option. While not terribly difficult, I did spend some time figuring this out… Maybe this will save someone else some time ;-)

The network setup (simplified):

  [ Workstation ]
         |
         |
   [ Firewall ]
         |
         |
  ~ The Internet ~
         |
         |
[ Public web server ]

The problem is connecting to public web server from my workstation, first I had to ssh or sftp to the Linux firewall, and from that machine connect to the web server.

There has to be an easier way… And a look at the SSH man page provided the answer: The -L option.

Excerpt from ssh(1):

-L [bind_address:]port:host:hostport
    Specifies that the given port on the local (client) host is to be
    forwarded to the given host and port on the remote side. This
    works by allocating a socket to listen to port on the local side,
    optionally bound to the specified bind_address.

Example on how to create the tunnel:

$ ssh -f -N -p 22 username@firewall -L 2844/webserver.example.com/22

To briefly explain what the other options mean:

  • -f Runs the tunnel in the background.
  • -N Don’t execute a login command, only setup the tunnel.
  • -p Connect to the firewall on port 22

You can now connect with ssh, sftp, or scp through localhost:2844

$ ssh -p 2844 myusername@localhost
$ scp -P 2844 file.tar.gz myusername@localhost:file.tar.gz

ssh(1) requires -p and scp(1) -P.

Testing

For debugging, don’t forget you can specify -v up to three times to get more information about what’s going on. A quick telnet test is also useful:

$ telnet localhost 2844
Trying ::1...
Connected to localhost.
Escape character is '^]'.
SSH-2.0-OpenSSH_5.1p1 FreeBSD-20080901

If you don’t see the last line, something is wrong.

Bonus tip

As a free complimentary bonus tip, it’s also easy to setup a convenient shortcut in ~/.ssh/config:

Host webserver
    Hostname localhost
    Port 2844
    User myusername

Further reading

Responses

Over at the FreeBSD Forums, Freddie pointed out a clever way to accomplish the same thing using netcat and the ProxyCommand option