SMTP over an SSH Tunnel
Jim Mock <[email protected]>
Introduction
When I first got to Massachusetts in February, I was
put into temporary housing which was provided to me by
work. I was stuck using a dial-up account from home,
which wasn't so bad -- at least I had 'net access.
However, since I was using Earthlink, and
many mail servers block mail originating from them
even if relayed through their mail servers (which I
was doing), I wanted a way to use a machine at work
as my relay instead.
An easy way to do so would have been to allow relay
for earthlink.net through the machine I was
going to use as my relay. This would have been bad,
and as a result was an unacceptable option. You'd
have to be a serious cracksmoker to open up a machine
to relay for Earthlink. Spammers would sniff it out
fairly quickly, and proceed to hammer it. To get
around this, I decided to set up an SSH tunnel from a
port on my laptop to port 25 on the mail server. It
was a fairly easy task, and well worth it in the long
run. The remainder of this article will explain how I
set things up.
Set up the Tunnel
The first thing I decided was to establish the tunnel
as a non-root user. Since the tunnel was going to
exist for solely mail relaying purposes, I created a
relay user on both my laptop and the server
in question. I also ran ssh-keygen(1) and
gave the relay user an empty passphrase. If you're
overly paranoid, you can use a passphrase and then use
ssh-agent(1). The way I figure is if someone
gets into my laptop, I have more things to worry about
than them sending mail through my relay.
Ok, now that we have the user created, the next step
is to actually make sure we can establish the tunnel.
This is done by doing the following:
% su relay
Password:
% ssh -2 -N -f -L 9595:mail.domain.com:25 mail.domain.com
%
Here's an explanation of the above:
The % su relay part allows you to
become the relay user.
The ssh command is a little more
in-depth.
The -2 flag tells ssh
that we should use SSH v2. We want to use v2 because
the ssh process can be sent to the background without
running a command using the -N flag.
-N is only available in v2 and is very
useful when you want to simply forward ports.
The -f tells ssh
to go into the background.
-L tells ssh that the given
port on the local side is supposed to be forwarded to
the given port on the remote side. Therefore,
-L 9595:mail.domain.com:25 forwards local
port 9595 to remote port 25 on mail.domain.com.
The mail.domain.com at the end is the
hostname of the machine we're connecting
to.
After running the command above, you should be able
to telnet to port 9595 on the local machine and see
that it's really forwarded to port 25 on the remote
machine:
% telnet localhost 9595
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.domain.com ESMTP Sendmail 8.11.3/8.11.3; Wed, 4 Apr 2001
09:00:10 -0400 (EDT)
Now it's time to put this into a script that will run
from /usr/local/etc/rc.d at boot.
The Script
In order to keep our script up to par with the other
scripts put in /usr/local/etc/rc.d, and to
keep shutdown from complaining that we're using an
"old-style" script, we have to give it start and stop
options. An easy way to do this is look look at other
scripts in the directory (if there are any others
there). 00mysql-client.sh and
apache.sh are good examples if you have
either of those installed.
Here's what the script looks like:
#!/bin/sh
# define a few variables
sleep=/bin/sleep
su=/usr/bin/su
ssh=/usr/bin/ssh
sshflags="-2 -N -f -L"
host=mail.domain.com
tunnel=9595:mail.domain.com:25
killall=/usr/bin/killall
$sleep 4
case "$1" in
start)
$su relay -c "$ssh $sshflags $tunnel $host && echo -n ' mail relay'
;;
stop)
$killall -u relay ssh && echo -n ' mail relay'
;;
*)
echo "Usage: `basename $0` {start|stop" >&2
;;
esac
exit 0
This is more elaborate than what's needed, however, I
like the fact that changing part of the script can be
done by changing the variables at the top. If you
don't want to use the variables, you don't have to --
you can just replace them with the commands in the
script.
Put the script in /usr/local/etc/rc.d
(I've named it relay.sh, make it executable,
and it will start your tunnel at boot.
MTA Configuration
The only thing left to do now is set up your MTA to
use port 9595 on the local machine as your relay or
"smart host". I'm currently using Postfix on my
laptop. The relevant part of my
/usr/local/etc/postfix/main.cf looks like
this:
relayhost = [localhost]:9595
Add the above line and then restart postfix.
If you're using sendmail, it's a little more involved
than that. Here's what you'll need to add to the mc
file you use to generate your
sendmail.cf:
define(`RELAY_MAILER_ARGS', `TCP $h 9595')dnl
define(`SMART_HOST', `relay:localhost')dnl
MODIFY_MAILER_FLAGS(`RELAY', `-k')dnl
Now regenerate your sendmail.cf, restart
sendmail, and you're ready to use your SSH tunnel to
send mail.
Happy mailing,
- jim
Return to the
April 2001 Issue