Safe Remote Relaying with Postfix
Updated 1 April 2004
NOTE: With the introduction of Mac OS X Server 10.3, it is now quite simple to permit safe relaying by enabling SMTP authorization. You should use CRAM-MD5 authorization at minimum.
One of the most vexing problems facing administrators is how to handle remote users who need to retrieve and send mail through Mac OS X Server, but who are not located on static IP addresses. The simplest solution is to make them use the SMTP server(s) of whatever ISP(s) they use for remote network connectivity, but that’s hardly the most interesting solution!
The more “fun” solution is to use “POP before SMTP.” In this method, a client is able to send e-mail through your local mail server so long as she has connected to the server to retrieve mail within a reasonably short period of time. While the method is colloquially called “POP” before SMTP, our installation will work with both POP and the more effective IMAP method of e-mail retrieval.
We’re going to configure a standalone Postfix mail transport agent—one that is not tied into Apple Mail Server—in this article. We can’t use Apple Mail Server here because the daemon we’re going to run doesn’t understand how to read AMS’ authentication patterns in the mail log. (Hint: this is a great opportunity for a follow-up article!) Inspiration for this article comes from Ralf Hildebrandt’s page on the subject, which you can find online at http://www.stahl.bau.tu-bs.de/~hildeb/postfix/pop-before-smtp_en.shtml.
Getting everything to work is pretty complicated, and you may want to read Darian Lewis’ articles on CPAN beforehand if you’ve never used it before.
First off, you will need to have your Mac OS X Server configured to use Postfix for all SMTP services. There’s already an article on how to do this, so refer to it if you haven’t already configured your Server to stop using Apple Mail Service.
Next, we need to build support for the Berkeley DB. This is a fairly standard database library, and many other UNIX utilities depend on it—so having it installed and running is a good idea regardless. With luck, Apple will include a working copy of the database library in a future release of Mac OS X Server.
The latest version of Berkeley DB is 4.0.14. Obtain a copy by launching the Terminal, changing to your favorite source directory, and executing the command:
curl -O http://www.sleepycat.com/update/4.0.14/db-4.0.14.tar.gz
Uncompress it and change to the package directory with:
gnutar -zxf http://www.sleepycat.com/update/4.0.14/db-4.0.14.tar.gz cd db-4.0.14
Compile and install the software with the following commands:
cd build_unix ../dist/configure make sudo make install
This is a very lengthy process, so feel free to get it started before a meal or social break. It took our testbed (400 MHz Titanium PB) over half an hour to compile and install. When you’re done, you will see some new directories under /usr/local/:
/usr/local/BerkeleyDB.4.0 /usr/local/BerkeleyDB.4.0/bin /usr/local/BerkeleyDB.4.0/docs /usr/local/BerkeleyDB.4.0/include /usr/local/BerkeleyDB.4.0/lib
Change back to your favorite source directory. Now we’re going to get the daemon software, which is conveniently called “pop-before-smtp.” There are several versions of the software out there; we’re getting version 1.29, which you retrieve using the command
curl -O http://bent.latency.net/pop-before-smtp/pop-before-smtp-1.29.tar.gz
Uncompress and untar it with gnutar.
Pop-before-smtp relies on Perl for its magic, and we’ll need to get five Perl modules in order for the software to work. Four of them can be retrieved using CPAN; the fifth must be installed from source because the current version on CPAN doesn’t build under the version of Perl that ships with Mac OS X Server 10.1.3 With luck, again, this may change in the future. If the result of perl -v shows a version later that 5.6.0, then your fifth Perl package could simply be installed through CPAN as DB_File. Anyway—I’m getting ahead of myself.
We switch to the magic of Perl now, and using the CPAN (Comprehensive Perl Archive Network) we’re going to beef our distribution up some. Start CPAN with the command
sudo perl -MCPAN -e shell
You should be greeted with the prompt “cpan>”. We’re going to install four packages, each of which takes a fair amount of time to retrieve and install. If you have problems during this process, contact me and let me know; I can’t guarantee I will be able to fix the problem, but I’ll do my best! At the “cpan>” prompt, enter the following commands:
install Time::HiRes install File::Tail install Net::Netmask install Date::Parse
Use the ‘quit’ command to exit from CPAN and Perl. We need to modify Perl now to support Berkeley DB. The CPAN package is too new for Mac OS X, so we have to get an older version:
curl -O http://www.cpan.org/authors/id/PMQS/DB_File-1.73.tar.gz
Once it’s downloaded (into your favorite source directory!), use gnutar -zxf to expand and untar it. Change into the DB_File-1.73/ directory. Assume superuser rights (or prefix commands below with 'sudo').
We need to make a few changes to the config.in file; specifically:
- Find the INCLUDE lines, and comment all of them out by prefixing the line with the octothorpe ("#").
- Add the line
INCLUDE=/usr/local/BerkeleyDB.4.0/include
- Find the LIB lines, and comment all of them out.
- Add the line
LIB=/usr/local/BerkeleyDB.4.0/lib
I don’t recommend using TextEdit to do this; use a command line editor, like emacs, pico, vim or vi. Once you make the changes, save the file.
We need to build DB_File’s Makefile next, so execute the command
perl Makefile.PL
to do so. Then we follow a pretty standard process:
make make test make install
During the make test process, you’ll see some errors. Despite their ominous appearance, you can ignore them, as DB_File was able to successfully test the all-important (to us!) hash function.
Just to recap, at this point we've:
- Installed Berkeley DB 4.0.14
- Updated Perl with several CPAN modules
- Retrieved and uncompressed/untarred pop-before-smtp
Now we’re ready to configure and install pop-before-smtp. This tool was written for Linux users, so we have to make some changes to it to support Mac OS X' BSD-style UNIX core. Start by changing to the pop-before-smtp-1.29/ directory, and use a command line editor to open pop-before-smtp.init.
At line seven, change the line to read
/var/log/$progname
This sets up where pop-before-smtp will log its transactions. Normally the file will be small or even empty, unless you turn the --debug option on.
At line nine, change “/var/adm” to “/var/run".
At line eleven, change the line to read
mail=/var/log/mail.log
At line thirty-eight, change “/usr/bin/ps -fp” to “/bin/ps -p"
If you want to see how the program’s running, change the command line options on eighteen to include “--debug". You’ll want to remove it before you run the daemon properly, though, or your /var/log/pop-before-smtp log will grow quite large with time.
Save the file and exit. Just for safety’s sake, we’re going to make one change in the daemon itself, so load pop-before-smtp into your editor of choice and change “maillog” to “mail.log” on line 301.
Copy the pop-before-smtp daemon into /usr/sbin/. We need to run it at least once prior to making the Postfix changes, so that the necessary database is created. Do so by running the init script:
./pop-before-smtp.init start
Test whether the daemon is running with
./pop-before-smtp.init status
You should see output similar to the following:
PID TT STAT TIME COMMAND 5755 std- S 0:33.77 perl -wT /usr/sbin/pop-before-smtp --debug
You should also see a pop-before-smtp.db file in /etc/postfix/. Copy the pop-before-smtp.init script to /usr/sbin/.
Now, we need to tell Postfix to include the database in its anti-spam lookups. Managing anti-spam provisions is a personal preference, and the instructions here are based on AFP548.com’s measures.
Change to /etc/postfix/ and edit main.cf. Find the smtp_recipient_restrictions line, and add the line
check_client_access hash:/etc/postfix/pop-before-smtp,
after the last check_client_access line (if you have any). Note the comma at the end of the line, it tells Postfix there are more rules for smtp_recipient_restrictions. The comma isn’t necessary if your main.cf file just uses the whitespace and indentation separators. (If that doesn’t make any sense, take a look at AFP548.com’s anti-spam provisions to see how we format things.)
Save the main.cf file and issue the postfix reload command to force Postfix to update its configuration.
The last stage to this process is to create a StartupItem so that pop-before-smtp will launch with future machine reboots. To do this, change to the /Library/StartupItems/ directory. Create the directory “pop-before-smtp” and change into it.
Using a command line editor, edit a file called StartupParameters.plist and fill it with the following:
{
Description = “Receive before Send Daemon";
Provides = ("Authenticated Selected SMTP Relay through Postfix");
Requires = (Resolver, Network);
Uses = ("Network");
OrderPreference = “Late";
Messages =
{
start = “Starting Receive before Send Daemon...";
stop = “Stopping Receive before Send Daemon...";
};
}
Save the file and execute the following commands to assign it to root:
chmod 644 StartupParameters.plist chown root:wheel StartupParameters.plist
Now, edit a file called pop-before-smtp and fill it with the following:
#!/bin/sh
. /etc/rc.common
#
#
# Start pop-before-smtp
#
# Requires that a mail server be ON, otherwise it’s kind of useless
#
#
if [ “${MAILSERVER:=-NO-}” = “-YES-” ]; then
ConsoleMessage “Starting mail services"
/usr/sbin/pop-before-smtp.init start
fi
Save the file and execute the following commands to assign it to root and make it executible:
chmod 755 pop-before-smtp chown root:wheel pop-before-smtp
That’s it! Your server is set up to permit limited-time authenticated SMTP relaying to valid POP or IMAP clients.