372 lines
13 KiB
HTML
372 lines
13 KiB
HTML
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
|
|
"http://www.w3.org/TR/html4/loose.dtd">
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>Postfix Before-Queue Content Filter </title>
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix Before-Queue Content Filter </h1>
|
|
|
|
<hr>
|
|
|
|
<h2>WARNING </h2>
|
|
|
|
<p> The before-queue content filtering feature described in
|
|
this document is suitable only for low-traffic sites. See the "<a
|
|
href="#pros_cons">Pros and Cons</a>" section below for details.
|
|
</p>
|
|
|
|
<h2>The Postfix before-queue content filter feature</h2>
|
|
|
|
<p> As of version 2.1, the Postfix SMTP server can forward all
|
|
incoming mail to a content filtering proxy server that inspects all
|
|
mail BEFORE it is stored in the Postfix mail queue. It is roughly
|
|
equivalent in capabilities to the approach described in MILTER_README,
|
|
except that the latter uses a dedicated protocol instead of SMTP.
|
|
|
|
<p> The before-queue content filter is meant to be used as follows: </p>
|
|
|
|
<blockquote>
|
|
|
|
<table>
|
|
|
|
<tr>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> Internet </td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -> </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> <a href="smtpd.8.html">Postfix SMTP server</a>
|
|
</td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -> </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> <b>Before</b> <b>queue</b> <b>filter</b> </td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -> </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> <a href="smtpd.8.html">Postfix SMTP server</a>
|
|
</td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -> </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> <a href="cleanup.8.html">Postfix cleanup
|
|
server</a> </td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -> </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> Postfix queue </td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -< </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> <a href="smtp.8.html">smtp</a><br> <a
|
|
href="local.8.html">local</a><br> <a
|
|
href="virtual.8.html">virtual</a> </td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</blockquote>
|
|
|
|
<p> The before-queue content filter is not to be confused with the
|
|
approach described in the FILTER_README document, where mail is
|
|
filtered AFTER it is stored in the Postfix mail queue. </p>
|
|
|
|
<p> This document describes the following topics: </p>
|
|
|
|
<ul>
|
|
|
|
<li><a href="#principles">Principles of operation</a>
|
|
|
|
<li><a href="#pros_cons">Pros and cons of before-queue content filtering</a>
|
|
|
|
<li><a href="#config">Configuring the Postfix SMTP pass-through
|
|
proxy feature</a>
|
|
|
|
<li><a href="#parameters">Configuration parameters</a>
|
|
|
|
<li><a href="#protocol">How Postfix talks to the before-queue content
|
|
filter</a>
|
|
|
|
</ul>
|
|
|
|
<h2><a name="principles">Principles of operation</a></h2>
|
|
|
|
<p> The before-filter Postfix SMTP server accepts connections from the
|
|
Internet and does the usual relay access control, SASL authentication,
|
|
TLS negotiation,
|
|
RBL lookups, rejecting non-existent sender or recipient addresses,
|
|
etc. The before-queue filter receives unfiltered mail content from
|
|
Postfix and does one of the following: </p>
|
|
|
|
<ol>
|
|
|
|
<li> <p> Re-inject the mail back into Postfix via SMTP, perhaps
|
|
after changing its content and/or destination. </p>
|
|
|
|
<li> <p> Discard or quarantine the mail. </p>
|
|
|
|
<li> <p> Reject the mail by sending a suitable SMTP status code
|
|
back to Postfix. Postfix passes the status back to the remote
|
|
SMTP client. This way, Postfix does not have to send a bounce
|
|
message. </p>
|
|
|
|
</ol>
|
|
|
|
<p>The after-filter Postfix SMTP server receives mail from the
|
|
content filter. From then on Postfix processes the mail as usual. </p>
|
|
|
|
<p> The before-queue content filter described here works just like
|
|
the after-queue content filter described in the FILTER_README
|
|
document. In many cases you can use the same software, within the
|
|
limitations as discussed in the "<a href="#pros_cons">Pros and
|
|
Cons</a>" section below. </p>
|
|
|
|
<h2><a name="pros_cons">Pros and cons of before-queue content
|
|
filtering</a></h2>
|
|
|
|
<ul>
|
|
|
|
<li> <p> Pro: Postfix can reject mail before the incoming SMTP mail
|
|
transfer completes, so that Postfix does not have to send rejected
|
|
mail back to the sender (which is usually forged anyway). Mail
|
|
that is not accepted remains the responsibility of the remote SMTP
|
|
client. </p>
|
|
|
|
<li> <p> Con: The remote SMTP client expects an SMTP reply within
|
|
a deadline. As the system load increases, fewer and fewer CPU
|
|
cycles remain available to answer within the deadline, and eventually
|
|
you either have to stop accepting mail or you have to stop filtering
|
|
mail. It is for this reason that the before-queue content filter
|
|
can be used only on low-traffic sites. </p>
|
|
|
|
<li> <p> Con: Content filtering software can use lots of memory
|
|
resources. In order to not run out of memory you have to reduce
|
|
the number of before-filter SMTP server processes so that a burst
|
|
of mail will not drive your system into the ground with too many
|
|
content filter processes. This, in turn, means that SMTP clients
|
|
have to wait for a long time before they receive service. </p>
|
|
|
|
</ul>
|
|
|
|
<h2><a name="config">Configuring the Postfix SMTP pass-through
|
|
proxy feature</a></h2>
|
|
|
|
<p> In the following example, the before-filter Postfix SMTP server
|
|
gives mail to a content filter that listens on localhost port 10025.
|
|
The after-filter Postfix SMTP server receives mail from the content
|
|
filter via localhost port 10026. From then on mail is processed as
|
|
usual. </p>
|
|
|
|
<p> The content filter itself is not described here. You can use
|
|
any filter that is SMTP enabled. For non-SMTP capable content
|
|
filtering software, Bennett Todd's SMTP proxy implements a nice
|
|
PERL/SMTP content filtering framework. See:
|
|
http://bent.latency.net/smtpprox/. </p>
|
|
|
|
<blockquote>
|
|
|
|
<table border="0">
|
|
|
|
<tr>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> Internet </td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -> </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> <a href="smtpd.8.html">Postfix SMTP server on
|
|
port 25</a> </td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -> </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> filter on localhost port 10025 </td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -> </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> <a href="smtpd.8.html">Postfix SMTP server on
|
|
localhost port 10026</a> </td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -> </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> <a href="cleanup.8.html">Postfix cleanup
|
|
server</a> </td>
|
|
|
|
<td align="center" valign="middle" width="5%"> <tt> -> </tt> </td>
|
|
|
|
<td bgcolor="#f0f0ff" align="center" valign="middle"
|
|
width="10%"> Postfix incoming queue </td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</blockquote>
|
|
|
|
<p> This is configured by editing the master.cf file: </p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
# =============================================================
|
|
# service type private unpriv chroot wakeup maxproc command
|
|
# (yes) (yes) (yes) (never) (100)
|
|
# =============================================================
|
|
#
|
|
# Before-filter SMTP server. Receive mail from the network and
|
|
# pass it to the content filter on localhost port 10025.
|
|
#
|
|
smtp inet n - n - 20 smtpd
|
|
-o smtpd_proxy_filter=127.0.0.1:10025
|
|
-o smtpd_client_connection_count_limit=10
|
|
#
|
|
# After-filter SMTP server. Receive mail from the content filter
|
|
# on localhost port 10026.
|
|
#
|
|
127.0.0.1:10026 inet n - n - - smtpd
|
|
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
|
|
-o smtpd_client_restrictions=
|
|
-o smtpd_helo_restrictions=
|
|
-o smtpd_sender_restrictions=
|
|
-o smtpd_recipient_restrictions=permit_mynetworks,reject
|
|
-o smtpd_data_restrictions=
|
|
-o mynetworks=127.0.0.0/8
|
|
-o receive_override_options=no_unknown_recipient_checks
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p> Note: do not specify spaces around the "=" or "," characters. </p>
|
|
|
|
<p> The before-filter SMTP server entry is a modified version of the
|
|
default Postfix SMTP server entry that is normally configured at
|
|
the top of the master.cf file: </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> The number of SMTP sessions is reduced from the default
|
|
100 to only 20. This prevents a burst of mail from running your
|
|
system into the ground with too many content filter processes. </p>
|
|
|
|
<li> <p> The "-o smtpd_client_connection_count_limit=10" prevents
|
|
one SMTP client from using up all 20 SMTP server processes.
|
|
This limit is not necessary if you receive all mail from a
|
|
trusted relay host. </p>
|
|
|
|
<p> Note: this setting is available in Postfix version 2.2 and
|
|
later. Earlier Postfix versions will ignore it. </p>
|
|
|
|
<li> <p> The "-o smtpd_proxy_filter=127.0.0.1:10025" tells the
|
|
before filter SMTP server that it should give incoming mail to
|
|
the content filter that listens on localhost TCP port 10025.
|
|
|
|
<li> <p> Postfix 2.3 supports both TCP and UNIX-domain filters.
|
|
The above filter could be specified as "inet:127.0.0.1:10025".
|
|
To specify a UNIX-domain filter, specify "unix:<i>pathname</i>".
|
|
A relative pathname is interpreted relative to the Postfix queue
|
|
directory. </p>
|
|
|
|
</ul>
|
|
|
|
<p> The after-filter SMTP server is a new master.cf entry: </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> The "127.0.0.1:10026" makes the after-filter SMTP
|
|
server listen
|
|
on the localhost address only, without exposing it to the
|
|
network. NEVER expose the after-filter SMTP server to the
|
|
Internet :-) </p>
|
|
|
|
<li> <p> The "-o smtpd_authorized_xforward_hosts=127.0.0.0/8"
|
|
allows the after-filter SMTP server to receive remote SMTP
|
|
client information from the before filter SMTP server, so that
|
|
the after-filter Postfix daemons log the remote SMTP client
|
|
information instead of logging localhost[127.0.0.1]. </p>
|
|
|
|
<li> <p> The other after-filter SMTP server settings avoid
|
|
duplication of work that is already done in the "before filter"
|
|
SMTP server. </p>
|
|
|
|
</ul>
|
|
|
|
<p> By default, the filter has 100 seconds to do its work. If it
|
|
takes longer then Postfix gives up and reports an error to the
|
|
remote SMTP client. You can increase this time limit (see configuration
|
|
parameter section below) but doing so is pointless because you
|
|
can't control when the remote SMTP client times out. </p>
|
|
|
|
<h2><a name="parameters">Configuration parameters</a></h2>
|
|
|
|
<p> Parameters that control proxying: </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> smtpd_proxy_filter (syntax: host:port): The host and TCP
|
|
port of the before-queue content filter. When no host or host:
|
|
is specified here, localhost is assumed. </p>
|
|
|
|
<li> <p> smtpd_proxy_timeout (default: 100s): Timeout for connecting
|
|
to the before-queue content filter and for sending and receiving
|
|
commands and data. All proxy errors are logged to the maillog
|
|
file. For privacy reasons, all the remote SMTP client sees is "451
|
|
Error: queue file write error". It would not be right to disclose
|
|
internal details to strangers. </p>
|
|
|
|
<li> <p> smtpd_proxy_ehlo (default: $myhostname): The hostname to
|
|
use when sending an EHLO command to the before-queue content filter.
|
|
</p>
|
|
|
|
</ul>
|
|
|
|
<h2><a name="protocol">How Postfix talks to the before-queue content
|
|
filter</a></h2>
|
|
|
|
<p> The before-filter Postfix SMTP server connects to the content
|
|
filter, delivers one message, and disconnects. While sending mail
|
|
into the content filter, Postfix speaks ESMTP but uses no command
|
|
pipelining. Postfix generates its own EHLO, XFORWARD (for logging
|
|
the remote client IP address instead of localhost[127.0.0.1]), DATA
|
|
and QUIT commands, and forwards unmodified copies of all the MAIL
|
|
FROM and RCPT TO commands that the before-filter Postfix SMTP server
|
|
didn't reject itself.
|
|
Postfix sends no other SMTP commands. </p>
|
|
|
|
<p> The content filter should accept the same MAIL FROM and RCPT
|
|
TO command syntax as the before-filter Postfix SMTP server, and
|
|
should forward the commands without modification to the after-filter
|
|
SMTP server. If the content filter or after-filter SMTP server
|
|
does not support all the ESMTP features that the before-filter
|
|
Postfix SMTP server supports, then the missing features must be
|
|
turned off in the before-filter Postfix SMTP server with the
|
|
smtpd_discard_ehlo_keywords parameter. </p>
|
|
|
|
<p> When the filter rejects content, it should send a negative SMTP
|
|
response back to the before-filter Postfix SMTP server, and it
|
|
should abort the connection with the after-filter Postfix SMTP
|
|
server without completing the SMTP conversation with the after-filter
|
|
Postfix SMTP server. </p>
|
|
|
|
</body>
|
|
|
|
</html>
|