Ssh tunnelling

From Granizada

Jump to: navigation, search

This note tries to uncomplicate the art of ssh tunnelling, also known as port forwarding. I'm convinced so many people get confused because the ssh man page for the options -L and -R is badly written in a subtle way. So in addition to providing examples I include a proposed fix to the OpenSSH man page. I've also sent it to the OpenSSH project.

Dan 06:03, 11 April 2007 (CST)




After reading about -L in the OpenSSH man page for the ssh command:

    -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.  Whenever a con‐
             nection is made to this port, the connection is forwarded over
             the secure channel, and a connection is made to host port
             hostport from the remote machine.

someone wrote to me (as many have before) saying:

> Sorry, I have read this 4 times and tried experimenting but I just can't
> grasp it!

Which is exactly what I thought when I first met this too. That's because, in a subtle way, it is one of the most obscurely-written man pages ever. It looks like it should make sense, but the sense always slides just out of sight around the corner :-)

Here's the key to everything:


ssh -L answer
Image:Crystal_Clear_app_kate.png


We'll illustrate this by tunnelling the SMTP mail protocol, but it works in the same way for any other TCP protocols and, with some magic, for UDP protocols as well.

Here is most simple version of the effect we want:

  • Computer A (local computer) running ssh and nothing else
  • Computer B (remote computer) running an smtpd mail server and the ssh daemon
  • I type a particular ssh command on computer A and leave that command running...
  • Then in another window I type "telnet localhost 25" and start talking to the smtpd on the far machine

This is a transparent tunnel and it is what you want to magically stretch the listening SMTP process from some remote machine securely to a local port.

So, let's implement the above scenario in one single command at computer A's root prompt, as you'll find in plenty of documentation:

    # ssh -L 25:localhost:25 unprivuser@computerB

You should be able to log in via ssh in the usual way, and get a prompt that appears the same. Now in a separate window, telnet to port 25 on your local machine. You should see a prompt for the remote mail server come up, eg:

    $ telnet localhost 25
    Trying 127.0.0.1...
    Connected to localhost.localdomain.
    Escape character is '^]'.
    220 elsewhere.example.com ESMTP - Mail server ready.

Voila, computer A now answers on port 25 as if it were running an SMTP daemon, even though it isn't. And you can't eavesdrop on the traffic between the two machines because it is encrypted by the ssh protocol.

So as well as providing you with an interactive prompt on the remote machine you also got a forwarded port. As soon as you log out of your ssh session the forwarded port vanishes.

But you might well have got it right by accident! This only works if on the remote machine the same daemon is listening on the external IP address as on localhost. I think this is wrong at many levels, not least because having programs listening on all interfaces by default is very bad design. But you'll find it used quite a bit, so this example is valid.

Let's make this a bit more precise:

    # ssh -L 25:computerB:25 unprivuser@computerB

But you might still have got this going by accident, because both port numbers are the same. It is also very common for the port numbers to need to be different. For example, you might not want or be able to use root privilege locally, and Unix design requires only processes owned by root can listen on ports lower than 1024.

Imagine a salesman with a laptop in Hong Kong. All outgoing company mail is required to go via the corporate SMTP server in Paris and the mail client on the laptop really can't be trusted to be clever or reliable (a very common situation.) The laptop is able to make an ssh connection to the mail system in Paris.

By forwarding port 25 of the server in Paris to a local port higher than 25, and getting the mail software to send all mail via the local port, we have achieved the goal without having insecure email crossing the Internet. And the Paris mail server is only accessible by people with ssh access, so there is no chance of spam or malware being sent.

Here's how it is done:

    $ ssh -L 12345:paris.example.com:25 unprivuser@paris.example.com

-R is exactly the same only in the opposite direction, and the tip about the colons is reversed too.

Beyond the ssh Endpoint

The previous example only takes you as far as tunnelling services running on a machine that you also have ssh access to. In fact the OpenSSH lets you forward any service the remote computer can see. So in the previous example, imagine the SMTP service is not in fact on the machine called paris, but on some other machine on the same network as paris. This other machine is not at all visible to the outside world, even less so than paris is, which at least exposes the ssh port. Here's the command:

    $ ssh -L 12345:lyons.example.com:25 unprivuser@paris.example.com

This says "log in to the machine paris.example.com, then connect from paris to port 25 on the machine lyons, and forward all traffic to and from there to port 12345 on the local machine."


Fixing the OpenSSH Man Page

This addresses the problem by defining the terms more clearly:

    -L [bind_address:]localhostport:remotehost:remoteport

           Specifies that the given localhostport on the local (client) host is 
           to be forwarded to the given remotehost and remoteport on the remote side.
           This works by allocating a socket to listen to localhostport on the local 
           side, optionally bound to the specified bind_address.  Whenever a con-
           nection is made to the local port, the connection is forwarded over
           the secure channel, and a connection is made to remotehost on remoteport
           from the remote machine. Note: remotehost may be any host that the 
           ssh endpoint machine (ie the machine specified with ''user@hostname'') can
           access, not just the endpoint machine itself.

           Examples forwarding a remote SMTP port to local port, where the remote
           service is running on the same machine as the ssh login:

             $ ssh -Nf -L 12345:faraway.example.com:25 \
                                unprivuser@faraway.example.com
             $ telnet localhost 12345
               Trying 127.0.0.1...
               Connected to localhost.localdomain.
               Escape character is '^]'.
               220 faraway.example.com ESMTP - Mail server ready.

           Example forwarding a remote web server inside a network to a local port,
           where the ssh login is on a machine that can see the remote server but 
           not on it. This will work for any TCP service visible to the ssh login:

             $ ssh -Nf -L 9876:intranet-server.example.com:80 \
                          unprivuser@firewall.example.com
             $ firefox localhost:9876
                (web page for protected intranet displayed.)



Creative Commons License
Creative Commons Attribution iconCreative Commons Share Alike icon
This content is licensed under the Creative Commons
Attribution ShareAlike License v. 2.5:
http://creativecommons.org/licenses/by-sa/2.5/
GNU head GFDL: Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". (shearer.org uses but does not currently recommend the GDFL and here's the explanation why. )
Personal tools
Navigation