Hacking Linux Exposed





previous article
next article
SSH Tunneling part 1 - Local Forwarding
By Bri Hatch.

Summary: Want to encrypt an otherwise cleartext transmission? SSH Tunneling may be the tool for you.

Two readers, let's call them Alice and Bob, asked me to settle a debate between them. Alice claimed that she was able to securely access her email over POP[1] even though the server didn't support any encryption such as POP over SSL. Bob disagreed.

Alice's solution involved using SSH[2] to tunnel her POP connection over the SSH connection.

Unfortunately, in order to settle their dispute publicly (and to determine which of them will be buying the other a very expensive dinner) I need to explain how SSH tunneling works. Next week we'll describe Alice's setup and one of the two will need to shell out some hefty cash for a seven course meal.

SSH tunneling is, in a word, cool. If you can SSH from one host to another, you can tunnel other TCP connections over the secure encrypted SSH session.[3] This allows you to protect an otherwise cleartext protocol, or allow arbitrary connections to machines that would otherwise be unaccessible.

There are two kinds of tunneling - LocalForwards and RemoteForwards. Let's cover the first, which is used more frequently.

A local forward is a tunnel from your local machine through the SSH server. You can create one on the command line by adding ssh arguments of the following form:

  -L local_port:destination_host:destination_port

where the bits are defined as follows:

Create a local forward (bind a local port, and forward it through the remote end.)

The port on the local machine that /usr/bin/ssh will listen on. This can be a port number or a service name like http, pop3, or mysql.

The destination host (name or IP address) from the perspective of the SSH server. This can be a host that is not accessible at all from the SSH client. For example if your SSH sessions ends behind a firewall and the SSH server can resolve "somebox.internal.our_company.com" that's fine, even if the SSH client can't reach or find an IP address for that machine directly.

The port on the destination_host to which it should connect.

For example if you used the following

  homebox$ ssh mail.my_isp.net -L 2525:localhost:smtp sleep 99999

then when you connected to port 2525 on homebox, it would be silently tunnelled to localhost's smtp port (25). Remember - in this case localhost is being evaluated on the SSH server, so localhost is the SSH server, not homebox. The sleep 99999 line just makes sure that the connection stays alive for a while. From another window you can run the following:

  homebox$ nc -v localhost 2525
  homebox [] 2525 open
  220 mail.my_isp.net ESMTP ReegenMail

You can see that connecting to the local port 2525 resulted in a connection to the smtp port (25) on the remote mail server. Since this connection was tunnelled inside the existing SSH session, it is completely[4] encrypted, with almost no work on your part, requiring no knowledge of cryptographic algorithms whatsoever. Isn't this great?

While this connection is active, you can see it from the window in which you ran the ssh command by hitting ~# :

  The following connections are open:
    #1 direct-tcpip: listening port 2525 for port 25, connect ...

You can open multiple connections at a time, and each is tunnelled securely through the encrypted SSH channel.

Recent versions of OpenSSH only allow the local SSH client machine to connect to the tunnelled connection.[5] If you need to allow other machines to use this tunnel[6] then you can supply the -g option to ssh as well.

Above I've described how to create these tunnels from the command line. Luckily you can also define your tunnels inside your ~/.ssh/config file. For example if I want to create the above tunnel any time I connect to my mail server by running 'ssh mailtunnel' I can add the following in my config file:

  Host mailtunnel
  HostName mail.my_isp.net
  LocalForward 2525:localhost:25
  GatewayPorts no

Then any time I 'ssh mailtunnel' it will automatically create this local forward. (I included 'GatewayPorts no' above, but that is actually the default anyway.) If I want to connect without the port forwarding, I just ssh mail.my_isp.net like normal.

Next week I'll discuss SSH's Remote Forwarding, and discuss one of the finer points of these two forwarding methods which will resolve the debate between Alice and Bob.


[1] Post Office Protocol, one of two main methods of accessing remote email, IMAP (Internet Mail Access Protocol) being the other one.

[2] SSH is a protocol that allows secure remote login/remote execution/file copy abilities. See http://www.openssh.com for information about OpenSSH, the most widely used Linux/Unix SSH software. They also maintain a list of non-unix software for those of you unfortunate to sit on a windows box, or lucky enough to have a Palm-enabled phone.

[3] Actually, you can tunnel any protocol over any other protocol if you try hard enough. SOAP is just one example of the lets-tunnel-everything-over-HTTP category. You could tunnel a PPP connection over SSH to create a poor man's VPN. Anything is possible.

[4] "Completely" because the endpoint was the SSH server

[5] It does this by only binding the port for localhost - no other machines should be able to reach this IP address.

[6] You better do this with great care if it is a protected resource you are accessing - you do not want to let some random cracker into a private network.

Bri Hatch is Chief Hacker at Onsight, Inc and author of Hacking Linux Exposed and Building Linux VPNs. Bri can be reached at bri@hackinglinuxexposed.com.

Copyright Bri Hatch, 2003

This is the February 28, 2003 issue of the Linux Security: Tips, Tricks, and Hackery newsletter. If you wish to subscribe, visit http://lists.onsight.com/ or send email to Linux_Security-request@lists.onsight.com.

previous article
next article