7.5 PostfixWietse 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. The remainder of this 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. 7.5.1 Postfix ArchitectureOn 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:
7.5.2 Getting and Installing PostfixCurrent versions of Red Hat, SuSE, and Debian Linux all include Postfix packages; if you use some other distribution, it probably does too. Red Hat 7.1'spowertools directory (which, by the way, is not present on all mirrors) provides postfix-20010202-4.i386.rpm, which isn't the newest version of Postfix but is not known to have any major vulnerabilities. This RPM has been compiled with support for STARTTLS (SSL) and therefore depends on the package openssl. Oddly, Red Hat 7.2 doesn't appear to have a Postfix package, but the one from Red Hat 7.1 may be used. Under SuSE 7, postfix.rpm can be found in the n2 series. The SuSE RPM also supports TLS and therefore needs openssl, and it 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 Potato includes a package of Postfix v.19991231pl11-2. Postfix used date stamps rather than version numbers until the 20010228 release, which was dubbed "v.1.0.0." As of this writing, the most current version is 1.1.3. This old version supports neither SMTP AUTH nor TLS; if you need these, you'll either have to compile Postfix from source or upgrade to Debian "Woody" (currently the "testing" release), which has Postfix v1.1.3 in the "main" section and Postfix-TLS (also v1.1.3) in the "non-US" section. If for whatever reason you can't use a binary package, Postfix's source code is available 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.) 7.5.3 Postfix for the Lazy: A Quick-Start ProcedureOne 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:
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 ten minutes worth 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. 7.5.4 Configuring PostfixLike 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 file name, 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 comprise 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.
7.5.5 Hiding Internal Email Addresses by MasqueradingTo 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 10, 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 rather than hostnames. 7.5.6 Running Postfix in a chroot JailOne 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 7-20 shows part of a master.cf file. Example 7-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. 7.5.7 Postfix Aliases, RevealedYou 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 clear text by default.) As alluded to in the quick and dirty procedure, aliases are also 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 prefer meaningful email names and short host-domain names, e.g., [email protected] rather than [email protected]. Still another use of 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 addresses, i.e., to the mailing list. The addresses that comprise a mailing list 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 7-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 7-21. Excerpt from /etc/aliasespostmaster: root mailer-daemon: root hostmaster: root root: bdewinter mailguys: bdewinter,mick.bauer mick.bauer: [email protected] 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. 7.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):
|