The second example is more complex, but can give better
performance, and is less likely to bounce mail when the machine
runs into some resource problem. This content filter receives
unfiltered mail with SMTP on localhost port 10025, and sends filtered
mail back into Postfix with SMTP on localhost port 10026.
For non-SMTP capable content filtering software, Bennett Todd's
SMTP proxy implements a nice PERL/SMTP content filtering framework.
See:
https://bent.latency.net/smtpprox/.
In the figure below, names followed by a number represent
Postfix commands or daemon programs. See the
OVERVIEW
document for an introduction to the Postfix architecture.
The example given here filters all mail, including mail that
arrives via SMTP and mail that is locally submitted via the Postfix
sendmail command. See examples near the end of this document for
how to exclude local users from filtering, or how to configure a
destination dependent content filter.
You can expect to lose about a factor of two in Postfix
performance for mail that arrives and leaves via SMTP, provided
that the content filter creates no temporary files. Each temporary
file created by the content filter adds another factor to the
performance loss.
Advanced content filter: requesting that all mail is filtered
To enable the advanced content filter method for all mail,
specify in
main.cf:
/etc/postfix/
main.cf:
content_filter = scan:localhost:10025
receive_override_options =
no_address_mappings
-
The "
content_filter" line causes Postfix to add one content
filter request record to each incoming mail message, with content
"scan:localhost:10025". The content filter request records are
added by the
smtpd(8) and
pickup(8) servers (and
qmqpd(8) if you
decide to enable this service).
-
Content filter requests are stored in queue files; this
is how Postfix keeps track of what mail needs filtering. When a
queue file contains a content filter request, the queue manager
will deliver the mail to the specified content filter regardless
of its final destination.
-
The "
receive_override_options" line disables address
manipulation before the content filter, so that the content filter
sees the original mail addresses instead of the result of virtual
alias expansion, canonical mapping, automatic bcc, address
masquerading, etc.
Advanced content filter: sending unfiltered mail to the content
filter
In this example, "scan" is an instance of the Postfix SMTP
client with slightly different configuration parameters. This is
how one would set up the service in the Postfix
master.cf file:
/etc/postfix/
master.cf:
# =============================================================
# service type private unpriv chroot wakeup maxproc command
# (yes) (yes) (yes) (never) (100)
# =============================================================
scan unix - - n - 10 smtp
-o
smtp_send_xforward_command=yes
-o
disable_mime_output_conversion=yes
-
This runs up to 10 content filters in parallel. Instead
of a limit of 10 concurrent processes, use whatever process limit
is feasible for your machine. Content inspection software can
gobble up a lot of system resources, so you don't want to have too
much of it running at the same time.
-
With "-o
smtp_send_xforward_command=yes", the scan transport
will try to forward the original client name and IP address
through the content filter to the
after-filter smtpd process, so that filtered mail is logged with
the real client name IP address. See
smtp(8) and
XFORWARD_README
for more information.
-
The "-o
disable_mime_output_conversion=yes" is a workaround
that prevents the breaking of domainkeys and other digital signatures.
This is needed because some SMTP-based content filters don't announce
8BITMIME support, even though they can handle it just fine.
Advanced content filter: running the content filter
The content filter can be set up with the Postfix spawn service,
which is the Postfix equivalent of inetd. For example, to instantiate
up to 10 content filtering processes on localhost port 10025:
/etc/postfix/
master.cf:
# ===================================================================
# service type private unpriv chroot wakeup maxproc command
# (yes) (yes) (yes) (never) (100)
# ===================================================================
localhost:10025 inet n n n - 10 spawn
user=filter argv=/path/to/filter localhost 10026
If you want to have your filter listening on port localhost:10025
instead of Postfix, then you must run your filter as a stand-alone
program, and must not use the Postfix spawn service.
Advanced filter: injecting mail back into Postfix
The job of the content filter is to either bounce mail with a
suitable diagnostic, or to feed the mail back into Postfix through
a dedicated listener on port localhost 10026.
The simplest content filter just copies SMTP commands and data
between its inputs and outputs. If it has a problem, all it has to
do is to reply to an input of `.' from Postfix with `550 content
rejected', and to disconnect without sending `.' on the connection
that injects mail back into Postfix.
/etc/postfix/
master.cf:
# ===================================================================
# service type private unpriv chroot wakeup maxproc command
# (yes) (yes) (yes) (never) (100)
# ===================================================================
localhost:10026 inet n - n - 10 smtpd
-o
content_filter=
-o
receive_override_options=
no_unknown_recipient_checks,
no_header_body_checks,
no_milters
-o
smtpd_helo_restrictions=
-o
smtpd_client_restrictions=
-o
smtpd_sender_restrictions=
-o
smtpd_recipient_restrictions=
permit_mynetworks,reject
-o
mynetworks=127.0.0.0/8
-o
smtpd_authorized_xforward_hosts=127.0.0.0/8
-
Note: do not use spaces around the "=" or "," characters.
-
Note: the SMTP server must not have a smaller process
limit than the "filter"
master.cf entry.
-
The "-o
content_filter=" overrides
main.cf settings, and
requests no content filtering for mail from the content filter.
This is required or else mail will stay in the content filtering
loop.
-
The "-o
receive_override_options" overrides
main.cf settings
to avoid duplicating work that was already done before the content
filter. These options are complementary to the options that are
specified in
main.cf:
-
We specify "
no_unknown_recipient_checks" to disable
attempts to find out if a recipient is unknown.
-
We specify "
no_header_body_checks" to disable header/body
checks.
-
We specify "
no_milters" to disable Milter applications
(this option is available only in Postfix 2.3 and later).
-
We don't specify "no_address_mapping" here. This
enables virtual alias expansion, canonical mappings, address
masquerading, and other address mappings after the content
filter. The
main.cf setting of "
receive_override_options"
disables these mappings before the content filter.
These receive override options are either implemented by the
SMTP server itself, or they are passed on to the cleanup server.
-
The "-o smtpd_xxx_restrictions" and "-o
mynetworks=127.0.0.0/8"
override
main.cf settings. They turn off junk mail controls that
would only waste time here.
-
With "-o
smtpd_authorized_xforward_hosts=127.0.0.0/8",
the scan transport will try to forward the original client name
and IP address to the after-filter smtpd process, so that filtered
mail is logged with the real client name and IP address. See
XFORWARD_README and
smtpd(8).