Real Programmers/ Hack/ SSH/ Tunneling
Google site:

realprogrammers.com

SSH Tunneling

SSH is probably most commonly used to gain access to a remote shell. There are however many other rather interesting and often poorly understood tricks up SSH's sleeves. One such device is tunneling, the act of wrapping up one protocol in another, most often point-to-point. The application we're going to look at here is retrieving mail from a POP server, and logging into a website.

Motivation

The primary reason here for tunneling is that both POP and HTTP GET and POST operations happen over plain-text protocols (APOP mitigates this issue but is relatively infrequently seen or offered by ISPs). This means when you log into your POP server to retrieve mail the username & password appears on the network with no encryption whatsoever. Similarly, when logging in using a form over the Web the username & password are on the wire for all to read.

Port forwarding

There are two types of port forwarding that SSH offers: local & remote. They are quite similar and share some features. Here's how it works. In both cases, an SSH connection is made to a server.

Local

Running SSH with a local forward will result in a process listening on a port on the local machine (where the SSH session is started). This process/port will accept connections and forward them via the remote authenticated SSH (sshd) process to another host:port combination. Thus the local machine is accepting connections and forwarding them over SSH to the logged-into machine, and then there on to host:port as an ordinary IP connection.

Remote

This is similar to local port forwarding in that a listener process is set up by SSH to forward packets over an authenticated SSH session but this time the listener process is on the remote machine, started by the remote sshd daemon. Thus the remote machine is accepting connections and forwarding them back over SSH back to the machine that started the SSH port forward session, and then from there onto host:port as an ordinary IP connection as above.

Examples

Local

Browsing corporate intranet webserver via corporate firewall

You log in from your laptop to your corporate firewall box with SSH and set up a local port forward to the corporate intranet webserver behind the firewall. The intranet webserver server is not ordinarily contactable or even route-able from the Internet at large. What results is an SSH process running on your laptop listening on a port, say port 8080, where all data sent to that port ends up at the intranet webserver on the HTTP port 80 via the authenticated SSH session running to the firewall. As far as the webserver is concerned, it simply sees a normal IP connection from the firewall's internal address (e.g. a private 192.168.x.y IP address). The key thing to note is that the session from your laptop to the firewall is SSH encrypted but the connection from the firewall to the webserver is not. We presumably don't mind this since it's on an internal corporate network.

So the packets go like:

Browser -HTTP-> http://localhost:8080/
localhost:8080 -SSH-> firewall:22
firewall:some_high_port -HTTP-> http://www.intranet.local:80/

SSH command on the local machine required for this:

ssh -N -f -L 8080:www.intranet.local:80 user@firewall

Note: user@hostname is equivalent to -l user hostname. You may find the former a little more natural to type.

Checking mail on your mail server

This time there are only two machines involved, your desktop workstation and your mailserver (on which you have an SSH account) on the other side of town. You need to check your mail on your mail server but don't want your plain-text password appearing either locally (so your dastardly coworker can't sniff it) or anywhere else along the way. The process is nearly the same as above, except rather than continuing on from the logged-into host to another we're simply forwarding to another port on the host.

ssh -N -f -L 30110:mail.mydomain.example:110 user@firewall

Now you would configure your mail client to use POP3 server localhost, and port 30110. This is much like telling the browser in the last example to use "webserver" localhost in http://localhost:8080/ Note: You can combine these various port forwards on a single SSH session by simply having multiple -L options.

Connecting to your database that is only listening to localhost

It's often considered good practice to have database servers listening only on their 127.0.0.1 IP address to reduce the likelihood of a remote exploit, or even packet snooping. One solution is to forward a local port over SSH to a remote machine's database port. This is a straightforward example and presented here worked through as how to to set up an SSH tunnel with PuTTY (an excellent piece of Windows software).

Remote

Serving music files from your workstation to your friends on the 'Net

Typically workstations in an office environment are on a private network which only allows outgoing connections using NAT (Network Address Translation). In these cases, since the workstations are on a private network they cannot offer services to the outside world. Here's a way to get around this, if you have an SSH account on the gateway machine.

(Can you figure this out? See if you can. Then read on.)

Let's say your workstation is running a webserver on the usual HTTP port 80 serving some .ogg music files. A SSH connection is created from your workstation to the gateway which is connected to the Internet. The gateway sshd sets up a listener process for say port 8000. All connections on that port are forwarded back over the SSH connection to your workstation. From there they, just like the local forward, journey on to wherever the fixed address of the remote port forward is configured to point to. So in this example you would forward the connection to localhost:80.

Here is how the packets move about,

Friend's Browser -HTTP-> http://gateway.yourcorporation.example:8000/music/...
gateway:22 -SSH-> workstation:some_high_port
workstation:some_other_high_port -HTTP-> localhost:80

SSH command on the local machine required for this:

ssh -N -f -R 8000:localhost:80 user@firewall

Note: The localhost might appear at first sight a little confusing when the remote server is somehow connecting another machine but don't forget localhost is relative to the initiating end of this SSH connection, i.e. the workstation. In the case of local port forwarding, localhost is relative to the other end, i.e. the connected-to machine.

Exercises

Almost needless to say, all these problems assume you have an SSH account and access to it.
  1. What is the command line required to connect to a shell on your mail POP and SMTP server, mail, so that from your workstation you can send and retrieve mail?
  2. You are in a hurry to set a machine's clock. The problem is the machine is a thousand miles away behind a firewall that prevents all outgoing connections and there are no time servers yet configured on its LAN. You have SSH access to a shell account and rdate installed the on the remote machine, and a time server timeserver.your.domain that your workstation uses. How might you do this? Bonus point for explaining why this would be hard with NTP and e.g. ntpdate.
  3. You're on contract at a company that's operating a "net-nanny" firewall which is preventing you from booking a ticket to see a rock band since their website is blocked by the net-nanny software. How do you get access to that site? (Hint: may require additional software & a little creativity). Bonus point for explaining why a straight port-forward might not work. (Hint: requires a little knowledge of virtual hosting and/or HTTP/1.1)
  4. Try to think up situations where local or remote port forwarding might help you. If you can think of interesting examples, send 'em along!

All non-user content and code Copyright © 2000-2006 realprogrammers.com / Paul Makepeace. Comments & feedback welcome!