How to SMTP Over an SSH Tunnel?

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:

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:

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:

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:

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:

Now regenerate your sendmail.cf, restart sendmail, and you’re ready to use your SSH tunnel to send mail.