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
-
-f
backgrounds the ssh process once it's
authenticated
-
-N
doesn't run a particular
command on the remote server (which ordinarily is the default behavior,
using the user's shell on the remote machine).
-
-L
(and -R
below) options take the
syntax
listener_port:remote_host:remote_port. I
think of it like listener_port ->
remote_host:remote_port where ->
means of course via the logged-into machine.
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.
- 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?
- 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
.
- 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)
- Try to think up situations where local or remote port forwarding
might help you. If you can think of interesting
examples, send 'em along!