Postfix Overview - Global Architecture
Up one level | Introduction | Goals and features | Global
architecture | Queue
Management | Security
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 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 master server that runs Postfix daemon
processes on demand: daemon processes to send or receive network mail messages,
daemon 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. For example, the plan is to provide an
alternate local delivery program that runs at a fixed low privilege, for
POP/IMAP users that never log into the shell, and that may not even have a UNIX
account.
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 mail 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.
Up one level | Introduction | Goals and features | Global
architecture | Queue
Management | Security