Book Image

Qmail Quickstarter: Install, Set Up and Run your own Email Server

Book Image

Qmail Quickstarter: Install, Set Up and Run your own Email Server

Overview of this book

This book starts with setting up a qmail server and takes you through virtualization, filtering, and other advanced features like hosting multiple domains, mailing lists, and SSL Encryption. Finally, it discusses the log files and how to make qmail work faster. Qmail is a secure, reliable, efficient, simple message transfer agent. It is designed for typical Internet-connected UNIX hosts. Qmail is the second most common SMTP server on the Internet, and has by far the fastest growth of any SMTP server. Qmail's straight-paper-path philosophy guarantees that a message, once accepted into the system, will never be lost. Qmail also optionally supports maildir, a new, super-reliable user mailbox format.
Table of Contents (13 chapters)

Administrative Conveniences


Qmail setup as described so far can provide full email service. This setup is, however, rather minimal, and lacks many administrative, maintenance, and troubleshooting features. Because qmail is designed to be modular, these deficiencies are easily remedied with additional programs.

About Patches

There are a great number of patches available for qmail that provide various sundry features, behavioral tweaks, and even minor bug fixes. There are two schools of thought on how to approach qmail with its plethora of patches. One is to come up with some "official" collection of patches (or just all the patches that sound sufficiently nifty or useful), apply them all, and go from there. The other is to treat qmail more like an efficient mechanism to achieve exactly what needs to be done and no more. This book falls into the latter category. There are several projects that provide "mega"-patches or that package qmail in a way that includes many patches, such as qmailrocks (http://www.qmailrocks.com), Bill Shupp's megapatch (http://www.shupp.org/), Matt Simerson's megatoaster (http://www.tnpi.biz/internet/mail/qmail/qmail.toaster1.2.shtml), and many others.

It is very tempting, particularly when new to qmail, to simply grab a bunch of (neat-sounding) patches and apply them all. This can be a dangerous thing to do unless you know C and SMTP well and can resolve patch conflicts. Even if the patches apply cleanly, the new features may be unnecessary and/or confusing (and may still conflict in terms of their effect). Keep in mind that qmail works just fine without them, and many of them provide features that can be obtained in other ways. Patching is an option, and one that should be used carefully. Every unused feature is memory (and CPU-time) wasted, and a potential source for an unexpected bug or security flaw—many patches have not been as rigorously designed or tested as qmail.

The approach encouraged in this book is one of being pragmatic and efficient (and, consequently, rather minimalist): use patches because the features they provide are necessary, and understand them before applying them. Thus, in this book patch URLs are presented alongside more lengthy explanations of the goal they accomplish and the alternatives and/or downsides.

ucspi-tcp and daemontools

The most widely recommended method for running qmail uses the daemontools and ucspi-tcp packages, both written by the author of qmail, Dr. Bernstein.

The ucspi-tcp package consists of a set of useful programs for connecting to the network and maintaining simple databases of environment-variable/connection rules. For example, tcpserver is included as part of ucspi-tcp.

The daemontools package contains the svscan/supervise programs for running, monitoring, and controlling long-running programs (daemons), and for connecting them to safe logging mechanisms (e.g. multilog). The default installation of daemontools creates a /service directory. To control a daemon with svscan, add a directory for that daemon to the /service directory. The svscan program starts up an instance of the supervise program for each subdirectory of the /service directory. Each of these directories must contain a shell script named run that contains all the necessary commands for starting the specific daemon. The run script must not exit until the daemon it commands exits. When the run script exits, the directory's supervise process restarts it, unless the supervise process has been told not to do so (for e.g. by placing a file named down in the subdirectory).

The combination of these two packages is a powerful setup for controlling, monitoring, and maintaining a qmail server.

Installation

Installing these packages is very simple. The ucspi-tcp package can be installed by simply downloading it (http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz), decompressing it, and running make setup check in the decompressed source directory.

The daemontools' installation is slightly more complicated.

  1. 1. You must create a /package directory:

mkdir -p /package
chmod 1755 /package
cd /package

  1. 2. Download the daemontools source into this /package directory, decompress it, and move into the resulting folders, as follows:

wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
tar xzvf daemontools-0.76.tar.gz
rm daemontools-0.76.tar.gz
cd admin/daemontools-0.76

  1. 3. Compile and install the daemontools programs:

    ./package/install
    
    
  2. 4. If you're on a BSD system, reboot to start up the svscan program, or run it manually as follows:

csh -cf '/command/svscanboot &'

  • If you're using a system that uses /etc/inittab, you should add svscanboot to the /etc/inittab, for example, with a line similar to the following:

    SV:123456:respawn:/command/svscanboot
    
    

Using tcpserver

Basic use of the tcpserver program from the ucspi-tcp package has been covered previously. However, the tcpserver program has many options that are of importance to a well-maintained qmail installation. There are two main areas where tcpserver shines and is often configured according to the system-administrator's personal preference. The first is in data collection; the second is in setting appropriate environment variables and asserting behaviors based on which remote system connects to tcpserver.

The tcpserver program can collect some basic information about the remote server, as described by the possible environment variables in the previous table. However, in many cases, such information is either irrelevant or unnecessary, and the collection of such data can be eliminated to improve connection latency. For example, looking up the remote host's IP address in DNS or attempting to make an ident query to identify the remote user may not provide much benefit, but does slow down connection attempts. Turning off such queries may improve initial connection latency, if that is a concern.

For example, by default, tcpserver looks up the remote host's hostname in DNS. If this is unnecessary, giving tcpserver the -H flag prevents this, and consequently prevents tcpserver from providing the TCPREMOTEHOST environment variable to whatever program it runs (e.g. qmail-smtpd). Similarly, if ident information is unnecessary, giving tcpserver the -R flag will prevent it from performing that query.

The tcpserver program can also be configured to use a small database (in CDB format) of rules defining when to allow or deny connections and which (if any) environment variables to set, based on the data it knows about the remote host.

The most common method of specifying these connection rules is to create a text file, /etc/tcp.smtp, in a specific format that is compiled by the tcprules program into the CDB database used by tcpserver (e.g. /etc/tcp.smtp.cdb). The format of a rule in a tcprules file (such as /etc/tcp.smtp) is:

matcher : decision , environment-variables (if any)

Connection rules are matched on a first-match-wins basis. For example:

192.168.1.2:deny
192.168.1.:allow,RELAYCLIENT=""
=www.example.com:allow,RELAYCLIENT=""
=:allow
:deny

This rule file would deny all connections from the 192.168.1.2 IP address, but would allow anything else in the 192.168.1.x IP range to connect and would set the RELAYCLIENT environment variable for those connections. If the DNS hostname of the remote host is www.example.com, this file allows that host to connect and sets the RELAYCLIENT environment variable. Any other host that has a hostname (denoted by the = sign) is allowed to connect, and finally any other connection attempt (i.e. from a host without a hostname) is rejected.

This rule file can be compiled into a CDB database file as follows:

tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp

The tcpserver program can then be told to use that CDB database by giving it the -x flag with the name of the CDB file, for example:

tcpserver -u `id -u qmaild` -g `id -g qmaild` \
-x /etc/tcp.smtp.cdb \
0 smtp /var/qmail/bin/qmail-smtpd

Using svscan

The basic format of a supervise-controlled service is a folder containing a shell script named run. This shell script eventually must run the service (daemon) that is to be controlled and must not exit until that daemon does. A good example of what might go into a run file is the /var/qmail/rc script built as part of the previously discussed basic qmail install. This script prepares qmail to run, and then runs it. As long as qmail-start is still running, the script does not exit. Thus, a very simple service folder for the delivery side of qmail is a folder containing that rc file, renamed run.

Logging

An extension to the previously described basic service-directory format is possible. The extension is to add a folder named log within the daemon's directory, which contains another shell script named run. In this extension, the standard output of the first first-level run file is piped as input to the log directory's run file. In this way, the daemon can be stopped and started independently of the logging mechanism, which can be any logging mechanism that accepts standard input, such as splogger or something similar. An easy, powerful method of logging is the multilog program (a part of the daemontools package), which saves log output in a crash-resistant, automatically rotating manner with high-precision timestamps.

Ordinarily, qmail-start uses the logging mechanism specified in the rc file, usually splogger. However, if the rc file (and thus, qmail-start) is controlled by svscan, it can be more useful to remove the logging argument from the rc file. This change causes qmail-send's log messages to be sent to standard output, which can then be used by svscan's more flexible logging architecture. There's no benefit from this if you are using the splogger utility, but more powerful logging tools, such as multilog, do benefit from the change. The run file for the qmail-send service directory might look something like the following:

#!/bin/sh
exec env - PATH="/var/qmail/bin:$PATH" \
qmail-start ./Mailbox

A log/run file for the qmail-send service directory might look similar to the following:

#!/bin/sh
exec setuidgid qmaill multilog t /var/log/qmail/qmail-send/

The beginning of this command, setuidgid qmaill uses the setuidgid tool from the ucspi-tcp package. The previous command is essentially equivalent to the following:

exec su qmaill -c 'multilog t /var/log/qmail/qmail-send/'

This is because both switch to a different user (qmaill) before running the rest of the command, but the setuidgid version is easier to read and type. The reason for using the qmaill user for logging is that it prevents the logs from being altered even if an attacker controls the process generating the logs (qmail-send, in this case).

This same structure can be used for running qmail-smtpd in a controllable, monitorable fashion. Simply create a directory for it (e.g. /var/qmail/supervise/smtpd) and create a run file for it, such as:

#!/bin/sh
QUID=`id -u qmaild`
QGID=`id -g qmaild`
LOCAL=`head -1 /var/qmail/control/me`
if [ ! f /var/qmail/control/rcpthosts ]; then
echo "Without a rcpthosts file, qmail is an open relay."
echo "Open relays are spammer havens."
echo "Please use a rcpthosts file."
exit 1
fi
exec tcpserver -R -l "$LOCAL" -H \
-x /etc/tcp.smtp.cdb \
-u "$QUID" -g "$QGID" \
0 smtp \
/var/qmail/bin/qmail-smtpd 2>&1

Then create in that directory another directory named log, and in the log directory, a run file such as:

#!/bin/sh
exec setuidgid qmail multilog t /var/log/qmail/smtpd/

Once these files are created, telling svscan to use them to control the service they specify is a two-step process. First, make sure that the run files are executable:

chmod +x /var/qmail/supervise/smtpd/run
chmod +x /var/qmail/supervise/smtpd/log/run

Then link the daemon's directory into /service, as follows:

ln -s /var/qmail/supervise/smtpd /service/qmail-smtpd

Wait a few moments, and then run the following to double-check that all is well.

svstat /service/qmail-smtpd

If it started as it should, the output of that command should indicate that the service in question (qmail-smtpd) has been running for a few seconds already. You can perform essentially the same procedure on the qmail-start service directory, or any other daemon to be controlled by svscan.

Once svscan is controlling a folder and the associated daemon, you can command the daemon with the svc command. For example:

svc -d /service/qmail-smtpd

This will order the qmail-smtpd service to stop by sending it a TERM signal. Using the -h flag instead of -d will cause the service to receive a HUP signal; in the case of qmail-start, this causes qmail to re-read many of its configuration files. This reread-config-on-HUP is a behavior shared by many UNIX daemons. The -u flag will cause the service to start again after having been stopped by the -d flag. The -t flag, like the -d flag, also sends a TERM signal. However, unlike the -d flag, the service is restarted as soon as it exits.

It is important to note that the TERM signal sent by the -t and -d flags does not cause all daemons to exit immediately. For example, when qmail-send receives a TERM signal, it finishes all deliveries currently in progress before exiting—which means that it may take several minutes to exit. To bring a daemon down immediately, use the -k flag, which sends the un-ignorable KILL signal. Note, though, that while the KILL signal will immediately terminate any process not protected by the kernel, the signal is not propagated to any of the daemon's child processes. Also, the -k flag alone allows the server to restart once it exits (similar to the -t flag). Thus, it is often used after the -d flag has been used first, to terminate a recalcitrant daemon.