Postfix Architecture
Table of Contents |
Back: Why Bother Writing Postfix? |
Next: Postfix Performance Results
Introduction
Some mail systems such as Sendmail are implemented as one large
monolithic program that does everything. One large program certainly
makes it easy to share data between different parts of the system.
Unfortunately, one large program also also makes it easy to make
fatal mistakes. Other mailers such as qmail use a rigid hierarchy
of programs that run other programs in a fixed order and throw them
away after use. This approach gives better insulation, at the cost
of some process creation overhead and inter-process communication.
The additional cost can be kept within acceptable limits by
partitioning the work in a sensible manner.
Postfix architecture
Postfix is based on semi-resident, mutually-cooperating, processes
that perform specific tasks for each other, without any particular
parent-child relationship. Again, doing work in separate processes
gives better insulation than using one big program. In addition,
the Postfix approach has the advantage that a service such as address
rewriting is available to every Postfix component program, without
incurring the cost of process creation just to rewrite one address.
By the way: I do not claim that Postfix is the only (mail) program
using this approach. Even in this relatively young discipline it
is hard to come up something new that no-one ever did before.
Postfix is implemented as a resident inetd-like master server
that runs Postfix processes on demand: processes to send or receive
network mail messages, processes to deliver mail locally, etc.
These processes are created up to a configurable number, are
re-used for a configurable number of times, and go away after a
configurable amount of idle time. This approach drastically reduces
process creation overhead while still providing the good insulation
from separate processes.
Postfix is intended to be a Sendmail replacement. For this reason it
tries to be compatible with existing infrastructure. However, many
parts of the Postfix system, such as the local delivery program, are
easily replaced by editing an inetd-like configuration file.
I intend to provide an alternate local delivery program that runs
unprivileged (for POP/IMAP mail databases, and for users that never
log into the shell).
As a result of this architecture, Postfix is easy to strip down to
the bare minimum. Subsystems that are turned off cannot be exploited.
Firewalls do not need local delivery. On client workstations, one
disables both the smtp listener and local delivery subsystems; or
the client mounts the maildrop directory from a file server,
and runs no resident Postfix processes at all.
Communication between Postfix processes
The core of the Postfix system is implemented by a dozen semi-resident
programs. For privacy reasons, these Postfix processes communicate
via UNIX-domain sockets or FIFOs that live in a protected directory.
Despite this privacy, Postfix processes do not really trust the
data that they receive in this manner; just like the contents of
Postfix queue files, they merely treat it as gossip.
The amount of information passed on between Postfix processes is
limited. In many cases, the only information exchanged between
Postfix processes is a queue file name and a list of recipients or
some status information. Once an email message is saved to file it
stays there until it is read by a local or remote message delivery
program.
Postfix takes the usual precautions to avoid loss of information:
flush and fsync() all data before acknowledging receipt, and check
all system call results for error conditions. This style of
programming may be new to some people, but I can assure you that
it has been standard practice for years in many places.
Postfix Component Programs
The programs that make up the core Postfix system are listed below.
Unless indicated otherwise, all programs are (semi) resident
daemons that run chrooted with vmailer privileges.
- sendmail
- The local posting agent. This non-resident program is not
set-uid and runs with the privileges of the user. The
sendmail program deposits messages into a world-writable maildrop
directory, in the form of files readable only by the user. The
sendmail program also supports sendmail-like options
such as: as go into daemon mode, list the mail queue, etc. These
options are typically implemented by running other Postfix programs.
- master
- The Postfix resident inetd-like process that runs all other
Postfix daemon programs. This is a small program that runs as
root and that is started at system boot time.
- Front-end programs
- All front-end programs pass on their messages to the cleanup
program which inserts messages into the queue.
- smtpd
- The Postfix SMTP server. This program receives messages from
the network. All it has to do is to implement SMTP without screwing
up. And, unavoidably, it implements SPAM and relay controls.
The SMTP server optionally sends to the postmaster transcripts of
unusual SMTP sessions, such as sessions with SMTP syntax/protocol
errors, or sessions with mail rejected because of SPAM restrictions
that rejected the client host name/address, the sender address, or
the destination address.
- pickup
- Pick up locally posted mail from the maildrop directory.
This program runs as root (but chrooted) so that it can open
a submitted file with the privileges of the owner of that file.
However, it runs as vmailer most of the time.
- Queue access programs
- cleanup
- Rewrites addresses to canonical form, and adds missing message
headers. Drops its result into the incoming queue. This
program implements permissive parsing. Unlike qmail-1.01, it does
not reject the entire message when it has a problem parsing a sender
or destination address.
- qmgr
- The Postfix queue manager. Takes messages from the incoming
and deferred queues and lets a limited number of messages
into the active queue. The queue manager moves messages that
cannot be delivered to the deferred queue, and scans that
queue periodically.
- Back-end programs
- All back-end programs get their message delivery requests from
the qmgr program.
- local
- The Postfix local delivery program. The default version of this
program delivers to UNIX-style mailboxes in /var[/spool]/mail, and
supports Sendmail-style alias databases and .forward files (with
include file expansion, with delivery to /file/name, and with
delivery to "|shell commands"). This program runs as root
and has access to the entire file system. However, it runs as
vmailer most of the time.
The local delivery program optionally informs the postmaster
of all mail that could not be delivered.
- smtp
- The Postfix SMTP client program. This program sends messages
across the network. All it has to do is to implement SMTP without
screwing up.
The SMTP client optionally sends to the postmaster transcripts
of unusual SMTP sessions, such as sessions with SMTP syntax/protocol
errors, or sessions with hosts that refuse to talk to us.
- pipe
- The Postfix interface to other delivery mechanisms. This
interface can be used to deliver mail via, for example, UUCP. The
pipe program runs as root and has acccess to the entire file
system. However, it runs as vmailer most of the time.
- Miscellaneous programs
- showq
- Show the contents of the Postfix queue. The output remarkably
resembles that of a sendmail queue listing.
- rewrite
- The address rewriting and resolving program. The default version
does only trivial address canonicalization (append or rewrite the
local hostname or domain and swap host!user to user@host), address
rewriting via table lookup, trivial address resolution (remote or
local), and address resolution via table lookup.
- bounce
- Deal with bounced or delayed mail. The result is fed into the
cleanup program.
Table of Contents |
Back: Why Bother Writing Postfix? |
Next: Postfix Performance Results