9.5. Postfix
Wietse Venema's program, Postfix, provides an
alternative to Sendmail that is simpler in design, more modular, and
easier to configure and administer. Equally important,
it's designed with scalability, reliability, and
security as fundamental requirements.
This part of the chapter brings you up to speed quickly on how to use
Postfix as a secure means of exchanging your
network's email with Internet hosts. In particular,
I'll focus on deploying Postfix on firewalls, in
DMZs, and in other settings in which your SMTP server will have
contact with untrusted systems.
I won't go into nearly as much depth with Postfix as
I just did with Sendmail. The whole point of Postfix is ease of use:
you'll have no problem figuring out how to use
Postfix given little more than the documentation and example
configurations included with Postfix itself.
9.5.1. Postfix Architecture
On the one hand, since
Postfix
can do most of what Sendmail can, its architecture is arguably as
complex or even a little more so than Sendmail's.
Postfix consists of a suite of daemons and helper applications,
whereas Sendmail is essentially monolithic.
On the other hand, Postfix's modularity actually
makes it much simpler in practice. For Mr. Venema and the others who
maintain Postfix's code, it's
easier to fix a bug in the SMTP daemon if that
daemon's code is self-contained and not part of a
much larger whole. As for end users, Postfix is administered mainly
with the postfix command and a few others (most
users only need postqueue and
postalias).
Separating functions across different processes is a big factor in
Postfix's speed and stability. Another factor is the
intelligence with which Postfix handles mail. Rather than processing
mail out of one big queue as Sendmail does, Postfix uses four
different
queues:
Maildrop queue
Mail that is submitted locally on the system is accepted in the
maildrop queue. Here the mail is checked for proper formatting (and
fixed if necessary) before being handed to the incoming queue.
Incoming queue
Mail initially received both from local processes via the maildrop
queue and from external hosts via Postfix's
smtpd process is preformatted if necessary and
then sent to the incoming queue. Here it will stay until
there's room in the active queue.
Active queue
Since the active queue contains messages that Postfix is actively
trying to deliver, it has the greatest risk of something going wrong.
Accordingly, the active queue is intentionally kept small, and it
accepts messages only if there is space for them.
Deferred queue
Email that cannot be delivered is placed in the deferred queue. This
prevents the system from continuously trying to deliver email and
keeps the active queue as short as possible to give newer messages
priority. This also enhances stability. If your MTA cannot reach a
given domain, all the email for that domain is assigned a wait time
and placed in the deferred queue so that those messages will not
needlessly monopolize system resources.
When a deferred message's wait time has expired, the
message is placed in the active queue again for delivery (as soon as
there's room in the active queue). Each time
delivery is attempted and failed, the message's wait
time is increased, and it is returned to the deferred queue.
9.5.2. Getting and Installing Postfix
Current versions of Red Hat, SUSE,
and Debian Linux all include Postfix packages; other distributions
probably do, too. Red Hat Enterprise Linux 3 and Fedora Core 2 each
include a postfix RPM that has been compiled
with support for STARTTLS (SSL) and therefore
depends on the package openssl.
SUSE also has a postfix RPM that also supports
TLS and therefore needs openssl. The SUSE RPM
also needs the package pcre because
it's been compiled with support for Perl regular
expressions (which are extremely useful in Postfix's
map files).
Debian "Woody" has a deb file for
postfix in the
"main" section and, separately,
postfix-TLS (also v1.1.3) in the
"non-US" section.
If for whatever reason you can't use a binary
package, obtain Postfix's source code at http://www.postfix.org. If you wish to
compile Postfix with TLS (SSL) support, you'll also
need to obtain Lutz Jaenicke's patch, which is
available from his web site: http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/.
Note that Wietse Venema's reason for not building in
TLS support himself is that, according to the Postfix home page, he
hasn't yet "figured out a way to
avoid adding tens of thousands of lines of code to the SMTP client
and server programs." (In other words, this patch
adds complexity to a program whose main purpose in life is to be
simple and, presumably, more secure.)
9.5.3. Postfix for the Lazy: A Quick-Start Procedure
One of the best things about Postfix
is that it can be set up quickly and easily without sacrificing
security. Therefore, before we go any further, let's
look at a minimal Postfix quick-start procedure. For many users,
these are the only steps necessary to configure Postfix on an SMTP
gateway:
Install Postfix from a binary package via your local package tool
(rpm, dpkg, etc.) or by
compiling and installing from source (see "When and
How to Compile from Source").
Open /etc/postfix/main.cf with the text editor
of your choice, and set the parameter myhostname
to the fully qualified name of your host, e.g.:
myhostname = fearnley.polkatistas.org Set the parameter myorigin (the stated origin of
mail sent from your network) to equal your domain name (enter this
line verbatim):
myorigin = $mydomain Set the parameter mydestination as follows,
assuming this is the email gateway for your entire domain (enter this
line verbatim):
mydestination = $myhostname, localhost.$mydomain, $mydomain Save and close main.cf.
Redirect root's mail to an
unprivileged account by adding or editing this line in
/etc/aliases:
root: mick Add or change other email aliases as you see fit, then save and close
aliases.
Execute the command postalias /etc/aliases.
Execute the command postfix start.
In seven brief steps, we just installed, configured, and started SMTP
services for our machine and its local name domain. If this machine
is a firewall or an SMTP gateway on a firewall's DMZ
network, it can now be used by local users to route outbound email,
and it can be pointed to by our domain's
"MX" DNS record (i.e., it can be
advertised to the outside world as a mail server for email addressed
to our domain). Pretty good return on the investment of about 10
minutes of typing, no?
|
Succinct though the seven-step method is, it may not be enough to get
Postfix to do what needs to be done for your
network. Even if it is, it behooves you to dig a little deeper:
ignorance nearly always leads to bad security. Let's
take a closer look at what we just did and then move on to some
Postfix tricks.
9.5.4. Configuring Postfix
Like
Sendmail, Postfix uses a .cf text file as its
primary configuration file (logically enough, it's
called main.cf). However,
.cf files in Postfix use a simple
parameter=$value syntax.
What's more, these files are extremely well
commented and use highly descriptive variable names. If your email
needs are simple enough, it's possible for you to
figure out much of what you need to know by editing
main.cf and reading its comments as you go.
You may wonder why, in our little seven-step procedure, so little
information needed to be entered in main.cf. The
only thing we added to it was our fully qualified domain name. In
fact, depending on how your machine is configured, it may not have
been necessary to supply even that!
This is because Postfix can use system calls such as
gethostname( ) to glean as much information as
possible directly from your kernel. Furthermore, once it knows the
fully qualified domain name of your host, Postfix is smart enough to
know that everything past the first
"." is your domain, and it sets the
variable mydomain accordingly.
You may need to add additional names to
mydestination if your server has more than one
FQDN (that is, multiple A records in your domain's
DNS). For example, if your SMTP gateway doubles as your public FTP
server with the ftp name associated with it in
addition to its normal hostname, your
mydestination declaration might look something
like this:
mydestination = $myhostname, localhost.$mydomain, ftp.$mydomain, $mydomain It's important that this line contain any name to
which your server can be legitimately referred and that the entire
declaration occupy a single line.
If you have a very long list of local host or domain names, it might
be easier to specify a filename, e.g.:
mydestination = /path/to/mydests.txt where /path/to/mydests.txt is the name of a file
containing your domain or hostnames, one per line. Dr. Venema
suggests not using comments in this file, so as
"to avoid surprises." There were two other interesting things we did in the
"quick and dirty" procedure. One
was to start Postfix with the command postfix
start. Just as BIND uses ndc (or
rndc) to control the various processes that make
up BIND, the postfix command can be used to
manage Postfix.
The most common invocations of the
postfix command are postfix
start, postfix stop,
and postfix reload. start and
stop are obvious; reload causes
postfix to reload its configuration files without stopping and
restarting. Another handy one is postfix
flush, which forces Postfix to attempt to send all
queued messages immediately. This is useful after changing a setting
that may have been causing problems: in the event that your change
worked, all messages delayed by the problem will go out immediately.
(They would go out regardless, but not as quickly).
In Step 6, we added a line to /etc/aliases to
divert root's email to an
unprivileged account. This is healthy paranoia: we
don't want to log in as the superuser for mundane
activities such as viewing system reports, which are sometimes
emailed to root.
|
9.5.5. Hiding Internal Email Addresses by Masquerading
To
prevent giving out information that serves no legitimate purpose,
it's wise to set the parameter
masquerade_domains = $mydomain in the
main.cf file (remember, the string
$mydomain refers to a variable and will be
substituted with the domain name you specified as part of the
variable myhostname). This will strip internal
hostnames from the FQDSs in From: addresses of
outbound messages.
If you wish to make an exception for mail sent by
root, you can set the parameter
masquerade_exceptions = root. This is probably a
good idea, especially if you have one or more processes that send
host-specific warnings or other messages as
root. For example, if you configure a log
watcher like Swatch, described in Chapter 12, to
send you email whenever the filesystem starts to fill up, that email
will be more useful if you know which host sent it!
In general, however, you will want most outbound mail to be
masqueraded with domain names visible to the outside world rather
than hostnames.
9.5.6. Running Postfix in a chroot Jail
One of the niftier things you can do to
secure Postfix is to run selected parts of it chrooted (see Chapter 6 for more information on the
chroot technique). This usually requires you to
create copies of things needed by the chrooted process. For example,
if the process looks for /etc/mydaemon.conf on
startup but is chrooted to /var/mydaemon, the
process will actually look for mydaemon.conf in
/var/mydaemon/etc/mydaemon.conf.
Happily, the preparations required to chroot Postfix are explained
for a variety of architectures, including Linux, in the
examples/chroot-setup subdirectory of the
Postfix source code. If you install Postfix from a binary package,
the package may have an installation script to make these
preparations for you automatically after installing Postfix. In SUSE,
for example, the Postfix RPM package runs a script that creates a
complete directory tree for chrooted Postfix processes to use
(etc, usr,
lib, and so forth). This directory tree then
resides in /var/spool/postfix (the default
Postfix home directory and therefore the logical place to chroot its
processes to), with the appropriate ownerships and permissions
preset.
If your binary distribution doesn't do this for you,
simply download the
current Postfix source code from http://www.postfix.org and extract the
examples/chroot-setup directory to obtain the
chroot script LINUX2. If your Postfix home
directory isn't
/var/spool/postfix, set (and export) the
environment variable POSTFIX_DIR to the correct
path before running the chroot script, e.g.:
bash-# export POSTFIX_DIR=/var/postfix
bash-# ./LINUX2
|
After provisioning Postfix's chroot jail,
you'll need to edit
/etc/postfix/master.cf to toggle the Postfix
daemons you wish to run chrooted (i.e., by putting a
"y" in the
"chroot" column of each daemon to
be chrooted). Do not, however, do this for
entries that use the commands pipe,
local, or virtual (i.e.,
entries with pipe, local,
or virtual in the
"command" column): generally, you
can't chroot processes that deliver mail on the
server itself. Some binary-package distributions (such as
SUSE's) automatically toggle the appropriate daemons
to chroot during Postfix installation.
Example 9-20 shows part of a
master.cf file.
Example 9-20. A master.cf file
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (50)
# ==========================================================================
smtp inet n - y - - smtpd
pickup unix n n y 60 1 pickup
cleanup unix - - y - 0 cleanup
qmgr unix n - y 300 1 qmgr
#qmgr fifo n - n 300 1 nqmgr
tlsmgr fifo - - n 300 1 tlsmgr
rewrite unix - - y - - trivial-rewrite
bounce unix - - y - 0 bounce
defer unix - - y - 0 bounce
flush unix - - n 1000? 0 flush
smtp unix - - y - - smtp
showq unix n - y - - showq
error unix - - y - - error
local unix - n n - - local
lmtp unix - - y - - lmtp
procmail unix - n n - - pipe
flags=R user=cyrus argv=/usr/bin/procmail -t -m
USER=${user} EXT=${extension} /etc/procmailrc After configuring the chroot jail and editing
master.cf, all you need to do is start Postfix
the way you normally would: postfix start.
9.5.7. Postfix Aliases, Revealed
You probably don't want your users connecting to and
storing mail on a publicly accessible server. The greater the
separation between public servers and private servers, the better.
(Don't forget, POP3
passwords are transmitted in cleartext by default.) Therefore, your
SMTP relay should be configured to forward incoming mail to some
other server or servers on your internal network.
As alluded to in the quick-and-dirty procedure, aliases are useful
for mapping email
addresses for users who don't actually have accounts
on the SMTP gateway. This practice has two main benefits: first, most
users tend to prefer meaningful email names and short host-domain
namese.g., aliases is the maintenance of mailing
lists. If an alias points to a comma-separated list of addresses
rather than a single address, mail sent to that alias will be copied
and sent to all specified addressesi.e., to the mailing list.
The addresses that a mailing list comprises can also be stored in a
separate file (each address on its own line). To specify an entry in
aliases whose target is the name of such a file,
be sure to use the :include: tag as shown in the
second-to-last line of Example 9-21. Without this
tag, Postfix will append mail to the file specified rather than
sending mail to the recipients listed therein. (This is a feature,
not a bug; it's useful sometimes to write certain
types of messages to a text file rather than to a mailbox.)
Example 9-21. Excerpt from /etc/aliases
postmaster: root
mailer-daemon: root
hostmaster: root
root: bdewinter
mailguys: bdewinter,mick.bauer
mick.bauer: mbauer@biscuit.stpaul.dogpeople.org
clients: :include:/etc/postfix/clientlist.txt
spam-reports: /home/bdewinter/spambucket.txt
|
Don't forget to run postalias
/etc/aliases any time you edit
aliases. postalias converts
the alias file into a database file that can be searched repeatedly
and rapidly each time a destination address is parsed; neither
Postfix nor Sendmail directly use the text version of
aliases.
9.5.8. Keeping Out Unsolicited Commercial Email (UCE)
Postfix offers protection against UCE via several settings in
main.cf. Some caution is in order, however:
there's a fine line between spam and legitimate
dissemination, and it's entirely possible that even
modest UCE controls will cause some legitimate (i.e., desired) mail
to be dropped.
Having said that, for most sites, this is an acceptable risk
(avoidable, too, through end-user education), and we recommend that
at a minimum you set the following in
main.cf (for a complete list of anti-UCE
parameters and their exact syntax, see /etc/
postfix/sample-smtpd.cf):
smtpd_recipient_limit
Indicates how many recipients the SMTP server will accept per message
deliveryi.e., how many SMTP RCPT TO
commands may be sent by an SMTP client in a single delivery.
Normally, this should not exceed 250 or so. (Anyone who needs to send
one message to this many users should be sending it to an email list
server such as majordomo, not to individual
recipients.)
smtpd_recipient_restrictions
Instructs Postfix to check each message's recipient
address against one or more criteria. One of the easiest to maintain
is the access database. This file lists domains, hosts, networks, and
users who are allowed to receive mail from your server. To enable it:
Set check_recipient_access =
hash:/etc/postfix/access.
Specify a relaying policy with
smtp_recipient_restrictions, e.g.:
smtpd_recipient restrictions =
permit_mynetworks
hash:/etc/postfix/access
reject_unauth_destination Create /etc/postfix/access (check the
access(5) manpage for format/syntax).
Run postmap hash:/etc/postfix/access to convert
the file into a database. Repeat this step after each time you edit
/etc/postfix/access.
smtpd_client_restrictions
Use this parameter to block mail from specific senders or originating
domains. Senders to block may be named both specifically, via an
external map file such as the access database, and generally, via
values such as the following:
reject_maps_rbl
Enables use of the Real Time Blackhole List described in the
"Sendmail" section of this chapter;
this requires maps_rbl_domains to be set
reject_unknown_client
Rejects mail from clients whose hostname can't be
determined
See the file /etc/postfix/sample-smtpd.cf for a
full list of valid smtpd_client_
restrictions settings.
maps_rbl_domains
Specifies one or more Blackhole database providerse.g.,
blackholes.mail-abuse.org.
STARTTLS and SMTP AUTH in PostfixFor information on how to configure Postfix to use these two important features, I refer you to the ample documentation at (and linked to at) http://www.postfix.org. You'll find Patrick Ben Koetter's excellent "Postfix SMTP AUTH (and TLS) HOWTO" to be particularly helpfulit's at http://postfix.state-of-mind.de/patrick.koetter/smtpauth/. |