diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 01:46:30 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 01:46:30 +0000 |
commit | b5896ba9f6047e7031e2bdee0622d543e11a6734 (patch) | |
tree | fd7b460593a2fee1be579bec5697e6d887ea3421 /proto/FILTER_README.html | |
parent | Initial commit. (diff) | |
download | postfix-b5896ba9f6047e7031e2bdee0622d543e11a6734.tar.xz postfix-b5896ba9f6047e7031e2bdee0622d543e11a6734.zip |
Adding upstream version 3.4.23.upstream/3.4.23upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | proto/FILTER_README.html | 980 |
1 files changed, 980 insertions, 0 deletions
diff --git a/proto/FILTER_README.html b/proto/FILTER_README.html new file mode 100644 index 0000000..522e728 --- /dev/null +++ b/proto/FILTER_README.html @@ -0,0 +1,980 @@ +<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> + +<html> + +<head> + +<title>Postfix After-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 After-Queue Content Filter </h1> + +<hr> + +<h2>Introduction</h2> + +<p> This document requires Postfix version 2.1 or later. </p> + +<p> Normally, Postfix receives mail, stores it in the mail queue +and then delivers it. With the external content filter described +here, mail is filtered AFTER it is queued. This approach decouples +mail receiving processes from mail filtering processes, and gives +you maximal control over how many filtering processes you are +willing to run in parallel. </p> + +<p> The after-queue content filter is meant to be used as follows: </p> + +<blockquote> + +<table> + +<tr> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + Network or<br> local users </td> + + <td align="center" valign="middle"> <tt> -> </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + Postfix<br> queue </td> + + <td align="center" valign="middle"> <tt> -> </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + <b>Content<br> filter</b> </td> + + <td align="center" valign="middle"> <tt> -> </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + Postfix<br> queue </td> + + <td align="center" valign="middle"> <tt> -> </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + Network or<br> local mailbox </td> + +</tr> + +</table> + +</blockquote> + +<p> This document describes implementations that use a single +Postfix instance for everything: receiving, filtering and delivering +mail. Applications that use two separate Postfix instances will +be covered by a later version of this document. </p> + +<p> The after-queue content filter is not to be confused with the +approaches described in the SMTPD_PROXY_README or MILTER_README +documents, +where incoming SMTP mail is filtered BEFORE it is stored into the +Postfix queue. </p> + +<p> This document describes two approaches to content filter +all email, as well as several options to filter mail selectively: </p> + +<ul> + +<li><a href="#principles">Principles of operation</a> + +<li>Simple content filter + +<ul> + +<li><a href="#simple_filter">Simple content filter example</a> + +<li><a href="#simple_performance">Simple content filter performance</a> + +<li><a href="#simple_limitations">Simple content filter limitations</a> + +<li><a href="#simple_turnoff">Turning off the simple content filter</a> + +</ul> + +<li>Advanced content filter + +<ul> + +<li><a href="#advanced_filter">Advanced content filter example</a> + +<li><a href="#performance">Advanced content filter performance</a> + +<li><a href="#advanced_turnoff">Turning off the advanced content filter</a> + +</ul> + +<li>Selective content filtering + +<ul> + +<li><a href="#remote_only">Filtering mail from outside users only</a> + +<li><a href="#domain_dependent">Different filters for different domains</a> + +<li><a href="#dynamic_filter">FILTER actions in access or header/body tables</a> + +</ul> + +</ul> + + +<h2><a name="principles">Principles of operation</a> </h2> + +<p> An after-queue content filter receives unfiltered mail from Postfix +(as described further below) and can do one of the following: </p> + +<ol> + +<li> <p> Re-inject the mail back into Postfix, perhaps after changing + content and/or destination. </p> + +<li> <p> Discard or quarantine the mail. </p> + +<li> <p> Reject the mail (by sending a suitable status code back to + Postfix). Postfix will send the mail back to the sender address. </p> + +</ol> + +<p> NOTE: in this time of mail worms and forged spam, it is a VERY +BAD IDEA to send viruses back to the sender address, because the +sender address is almost certainly not the originator. It is better +to discard known viruses, and to quarantine material that is +suspect so that a human can decide what to do with it. </p> + +<h2><a name="simple_filter">Simple content filter example</a></h2> + +<p> The first example is simple to set up, but has major limitations +that will be addressed in a second example. Postfix receives +unfiltered mail from the network with the smtpd(8) server, and +delivers unfiltered mail to a content filter with the Postfix +pipe(8) delivery agent. The content filter injects filtered mail +back into Postfix with the Postfix sendmail(1) command, so that +Postfix can deliver it to the final destination. </p> + +<p> This means that mail submitted via the Postfix sendmail(1) +command cannot be content filtered. </p> + +<p> 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. </p> + +<blockquote> + +<table> + +<tr> + + <td align="center" valign="top"> Unfiltered<br> <br> </td> + + <td align="center" valign="top"> <tt> -></tt><br> <br> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + smtpd(8)<br> <br> pickup(8) </td> + + <td align="center" valign="middle"> <tt> >- </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + cleanup(8) </td> + + <td align="center" valign="middle"> <tt> -> </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + qmgr(8)<br> Postfix <br> queue </td> + + <td align="center" valign="middle"> <tt> -< </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + local(8)<br> smtp(8)<br> pipe(8) </td> + + <td align="center" valign="top"> <tt> -></tt><br> <tt> + -></tt><br> </td> + + <td align="center" valign="top"> Filtered<br> Filtered<br> + </td> + +</tr> + +<tr> + + <td colspan="2"> </td> + + <td align="center" valign="middle"> ^<br> <tt> | </tt> </td> + + <td colspan="5"> </td> + + <td align="center" valign="middle"> <tt> |<br> v </tt> </td> + + <td colspan="2"> </td> + +</tr> + +<tr> + + <td colspan="2"> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + <a href="QSHAPE_README.html#maildrop_queue"> maildrop <br> + queue </a> </td> + + <td align="center" valign="middle"> <tt> <- </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle">Postfix<br> + postdrop(1) </td> + + <td align="center" valign="middle"> <tt> <- </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle">Postfix<br> + sendmail(1) </td> + + <td align="center" valign="middle"> <tt> <- </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle">Content + <br> filter </td> + + <td colspan="2"> </td> + +</tr> + +</table> + +</blockquote> + +<p> The content filter can be a simple shell script like this: </p> + +<blockquote> +<pre> + 1 #!/bin/sh + 2 + 3 # Simple shell-based filter. It is meant to be invoked as follows: + 4 # /path/to/script -f sender recipients... + 5 + 6 # Localize these. The -G option does nothing before Postfix 2.3. + 7 INSPECT_DIR=/var/spool/filter + 8 SENDMAIL="/usr/sbin/sendmail -G -i" # NEVER NEVER NEVER use "-t" here. + 9 +10 # Exit codes from <sysexits.h> +11 EX_TEMPFAIL=75 +12 EX_UNAVAILABLE=69 +13 +14 # Clean up when done or when aborting. +15 trap "rm -f in.$$" 0 1 2 3 15 +16 +17 # Start processing. +18 cd $INSPECT_DIR || { +19 echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; } +20 +21 cat >in.$$ || { +22 echo Cannot save mail to file; exit $EX_TEMPFAIL; } +23 +24 # Specify your content filter here. +25 # filter <in.$$ || { +26 # echo Message content rejected; exit $EX_UNAVAILABLE; } +27 +28 $SENDMAIL "$@" <in.$$ +29 +30 exit $? +</pre> +</blockquote> + +<p> Notes: </p> + +<ul> + +<li> <p> Line 8: The -G option says the filter output is not a local +mail submission: don't do silly things like appending the local +domain name to addresses in message headers. This option does +nothing before Postfix version 2.3. </p> + +<li> <p> Line 8: The -i option says don't stop reading input when +a line contains "." only. </p> + +<li> <p> Line 8: NEVER NEVER NEVER use the "-t" command-line option +here. It will mis-deliver mail, like sending messages from a mailing +list back to the mailing list. </p> + +<li> <p> Line 21: The idea is to first capture the message to +file and then run the content through a third-party content filter +program. </p> + +<li> <p> Line 22: If the message cannot be captured to file, mail +delivery is deferred by terminating with exit status 75 (EX_TEMPFAIL). +Postfix places the message in the deferred mail queue and tries +again later. </p> + +<li> <p> Line 25: You will need to specify a real content filter +program here that receives the content on standard input. </p> + +<li> <p> Line 26: If the content filter program finds a problem, +the mail is bounced by terminating with exit status 69 (EX_UNAVAILABLE). +Postfix will send the message back to the sender as undeliverable +mail. +</p> + +<li> <p> NOTE: in this time of mail worms and spam, it is a BAD +IDEA to send known viruses or spam back to the sender, because that +address is likely to be forged. It is safer to discard known viruses +and to quarantine suspicious content so that it can +be inspected by a human being. </p> + +<li> <p> Line 28: If the content is OK, it is given as input to +the Postfix sendmail command, and the exit status of the filter +command is whatever exit status the Postfix sendmail command +produces. Postfix will deliver the message as usual. </p> + +<li> <p> Line 30: Postfix returns the exit status of the Postfix +sendmail command. </p> + +</ul> + +<p> I suggest that you first run this script by hand until you are +satisfied with the results. Run it with a real message (headers+body) +as input: </p> + +<blockquote> +<pre> +% /path/to/script -f sender -- recipient... <message-file +</pre> +</blockquote> + +<p> Once you're satisfied with the content filtering script: </p> + +<ul> + +<li> <p> Create a dedicated local user account called "filter". This +user handles all potentially dangerous mail content - that is +why it should be a separate account. Do not use "nobody", and +most certainly do not use "root" or "postfix". </p> + +<li> <p> Create a directory /var/spool/filter that is accessible only +to the "filter" user. This is where the content filtering script +is supposed to store its temporary files. </p> + +<li> <p> Configure Postfix to deliver mail to the content filter +with the pipe(8) delivery agent (see the pipe(8) manpage for a +description of the command syntax below). </p> + +<pre> +/etc/postfix/master.cf: + # ============================================================= + # service type private unpriv chroot wakeup maxproc command + # (yes) (yes) (yes) (never) (100) + # ============================================================= + filter unix - n n - 10 pipe + flags=Rq user=filter null_sender= + argv=/path/to/script -f ${sender} -- ${recipient} +</pre> + +<p> 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. The empty null_sender setting is +required with Postfix 2.3 and later. </p> + +<li> <p> To turn on content filtering for mail arriving via SMTP +only, append "-o content_filter=filter:dummy" to the master.cf +entry that defines the Postfix SMTP server: </p> + +<pre> +/etc/postfix/master.cf: + # ============================================================= + # service type private unpriv chroot wakeup maxproc command + # (yes) (yes) (yes) (never) (100) + # ============================================================= + smtp inet ...other stuff here, do not change... smtpd + -o content_filter=filter:dummy +</pre> + +<p> The "-o content_filter" line causes Postfix to add one content +filter request record to each incoming mail message, with content +"filter:dummy". This record overrides the normal mail routing +and causes mail to be given to the content filter instead. </p> + +<p> The content_filter configuration parameter expects a value of +the form <i>transport:destination</i>. The <i>transport</i> name +specifies the first field of a mail delivery agent definition in +master.cf; the syntax of the next-hop <i>destination</i> is described +in the manual page of the corresponding delivery agent. </p> + +<p> The meaning of an empty next-hop filter <i>destination</i> is +version dependent. Postfix 2.7 and later will use the recipient +domain; earlier versions will use $myhostname. Specify +"default_filter_nexthop = $myhostname" for compatibility with Postfix +2.6 or earlier, or specify a non-empty next-hop filter <i>destination</i>. +</p> + +<p> The content_filter setting has lower precedence than a FILTER +action that is specified in an access(5), header_checks(5) or +body_checks(5) table. </p> + +<li> <p> Execute "<b>postfix reload</b>" to complete the change. +</p> + +</ul> + +<h2> <a name="simple_performance">Simple content filter performance</a> </h2> + +<p> With the shell script as shown above you will lose a factor of +four in Postfix performance for transit mail that arrives and leaves +via SMTP. You will lose another factor in transit performance for +each additional temporary file that is created and deleted in the +process of content filtering. The performance impact is less for +mail that is submitted or delivered locally, because such deliveries +are already slower than SMTP transit mail. </p> + +<h2><a name="simple_limitations">Simple content filter limitations</a></h2> + +<p> The problem with content filters like the one above is that +they are not very robust. The reason is that the software does not +talk a well-defined protocol with Postfix. If the filter shell +script aborts because the shell runs into some memory allocation +problem, the script will not produce a nice exit status as defined +in the file /usr/include/sysexits.h. Instead of going to the +deferred queue, mail will bounce. The same lack of robustness can +happen when the content filtering software itself runs into a +resource problem. </p> + +<p> The simple content filter method is not suitable for content +filter actions that are invoked via header_checks or body_checks +patterns. These patterns will be applied again after mail is +re-injected with the Postfix sendmail command, resulting in a mail +filtering loop. The advanced content filtering method (see below) +makes it possible to turn off header_checks or body_checks patterns +for filtered mail. </p> + +<h2><a name="simple_turnoff">Turning off the simple content filter</a> </h2> + +<p> To turn off "simple" content filtering: </p> + +<ul> <li> <p> Edit the master.cf file, remove the "-o +content_filter=filter:dummy" text from the entry that defines the +Postfix SMTP server. </p> + +<li> <p> Execute "<b>postsuper -r ALL</b>" to remove content +filter request records from existing queue files. </p> + +<li> <p> Execute another "<b>postfix reload</b>". </p> + +</ul> + +<h2><a name="advanced_filter">Advanced content filter example</a></h2> + +<p> 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. </p> + +<p> 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> + +<p> 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. </p> + +<blockquote> + +<table> + +<tr> + + <td align="center" valign="middle"> Unfiltered<br> <br> + Unfiltered</td> + + <td align="center" valign="middle"> <tt> -></tt><br> <br> + <tt> -> </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + smtpd(8)<br> <br> pickup(8) </td> + + <td align="center" valign="middle"> <tt> >- </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + cleanup(8) </td> + + <td align="center" valign="middle"> <tt> -> </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + qmgr(8)<br> Postfix <br> queue </td> + + <td align="center" valign="middle"> <tt> -< </tt> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + smtp(8)<br> <br> local(8) </td> + + <td align="center" valign="middle"> <tt> -></tt><br> <br> + <tt> -> </tt></td> + + <td align="center" valign="middle"> Filtered<br> <br> + Filtered</td> + +</tr> + +<tr> + + <td colspan="4"> </td> + + <td align="center" valign="middle"> ^<br> <tt> | </tt> </td> + + <td> </td> + + <td align="center" valign="middle"> <tt> |<br> v </tt> </td> + + <td colspan="4"> </td> + +</tr> + +<tr> + + <td colspan="4"> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + smtpd(8)<br> 10026 </td> + + <td> </td> + + <td bgcolor="#f0f0ff" align="center" valign="middle"> + smtp(8)<br> </td> + + <td colspan="4"> </td> + +</tr> + +<tr> + + <td colspan="4"> </td> + + <td align="center" valign="middle"> ^<br> <tt> | </tt> </td> + + <td> </td> + + <td align="center" valign="middle"> <tt> |<br> v </tt> </td> + + <td colspan="4"> </td> + +</tr> + +<tr> + + <td colspan="4"> </td> + + <td colspan="3" bgcolor="#f0f0ff" align="center" + valign="middle">content filter 10025</td> + + <td colspan="4"> </td> + +</tr> + +</table> + +</blockquote> + +<p> The example given here filters all mail, including mail that +arrives via SMTP and mail that is locally submitted via the Postfix +sendmail command (local submissions enter Postfix via the pickup(8) +server; to keep the figure simple we omit local submission details). +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. </p> + +<p> 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. </p> + +<h3>Advanced content filter: requesting that all mail is filtered</h3> + +<p> To enable the advanced content filter method for all mail, +specify in main.cf: </p> + +<blockquote> +<pre> +/etc/postfix/main.cf: + content_filter = scan:localhost:10025 + receive_override_options = no_address_mappings +</pre> +</blockquote> + +<ul> + +<li> <p> 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. </p> + +<li> <p> 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). </p> + +<li> <p> 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. </p> + +<li> <p> The content_filter configuration parameter expects a value +of the form <i>transport:destination</i>. The <i>transport</i> name +specifies the first field of a mail delivery agent definition in +master.cf; the syntax of the next-hop <i>destination</i> is described +in the manual page of the corresponding delivery agent. </p> + +<li> <p> The meaning of an empty next-hop filter <i>destination</i> +is version dependent. Postfix 2.7 and later will use the recipient +domain; earlier versions will use $myhostname. Specify +"default_filter_nexthop = $myhostname" for compatibility with Postfix +2.6 or earlier, or specify a non-empty next-hop filter <i>destination</i>. + +<li> <p> The content_filter setting has lower precedence than a +FILTER action that is specified in an access(5), header_checks(5) +or body_checks(5) table. </p> + +</ul> + +<h3> Advanced content filter: sending unfiltered mail to the content +filter</h3> + +<p> 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: +</p> + +<blockquote> +<pre> +/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 + -o smtp_generic_maps= +</pre> +</blockquote> + +<ul> + +<li> <p> 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. </p> + +<li> <p> 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. </p> + +<li> <p> 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 8-bit mail. </p> + +<li> <p> The "-o smtp_generic_maps=" is a workaround that prevents +local address rewriting with generic(5) maps. Such rewriting should +happen only when mail is sent out to the Internet. </p> + +</ul> + +<h3>Advanced content filter: running the content filter</h3> + +<p> 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: </p> + +<blockquote> +<pre> +/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 +</pre> +</blockquote> + +<ul> + +<li> <p> "filter" is a dedicated local user account. The user will +never log in, and can be given a "*" password and non-existent +shell and home directory. This user handles all potentially +dangerous mail content - that is why it should be a separate account. +</p> + +<li> <p> By default, Postfix will terminate a command that runs +longer than command_time_limit seconds (default: 1000s). This is a +safety measure that prevents filters from running forever. </p> + +</ul> + +<p> 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. </p> + +<h3>Advanced filter: injecting mail back into Postfix</h3> + +<p> 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. </p> + +<p> 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. </p> + +<blockquote> +<pre> +/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= + # Postfix 2.10 and later: specify empty smtpd_relay_restrictions. + -o smtpd_relay_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 +</pre> +</blockquote> + +<ul> + +<li> <p> NOTE: do not use spaces around the "=" or "," characters. </p> + +<li> <p> NOTE: the SMTP server must not have a smaller process +limit than the "filter" master.cf entry. </p> + +<li> <p> 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 loop. </p> + +<li> <p> 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: </p> + +<ul> + + <li> <p> We specify "no_unknown_recipient_checks" to disable + attempts to find out if a recipient is unknown. </p> + + <li> <p> We specify "no_header_body_checks" to disable header/body + checks. </p> + + <li> <p> We specify "no_milters" to disable Milter applications + (this option is available only in Postfix 2.3 and later). </p> + + <li> <p> We don't specify "no_address_mappings" 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. </p> + +</ul> + + <p> These receive override options are either implemented by the + SMTP server itself, or they are passed on to the cleanup server. + </p> + +<li> <p> 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. + +<li> <p> 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). </p> + +</ul> + +<h2><a name="performance">Advanced content filter performance</a></h2> + +<p> With the "sandwich" approach to content filtering described +here, it is important to match the filter concurrency to the +available CPU, memory and I/O resources. Too few content filter +processes and mail accumulates in the active queue even with low +traffic volume; too much concurrency and Postfix ends up deferring +mail destined for the content filter because processes fail due to +insufficient resources. </p> + +<p> Currently, content filter performance tuning is a process of +trial and error; analysis is handicapped because filtered and +unfiltered messages share the same queue. As mentioned in the +introduction of this document, content filtering with multiple +Postfix instances will be covered in a future version. </p> + +<h2><a name="advanced_turnoff">Turning off the advanced content filter</a> </h2> + +<p> To turn off "advanced" content filtering: </p> + +<ul> <li> <p> Delete or comment out the two following main.cf lines. +The other changes made for advanced content filtering have no effect +when content filtering is turned off. </p> + +<blockquote> +<pre> +/etc/postfix/main.cf: + content_filter = scan:localhost:10025 + receive_override_options = no_address_mappings +</pre> +</blockquote> + +<li> <p> Execute "<b>postsuper -r ALL</b>" to remove content +filter request records from existing queue files. </p> + +<li> <p> Execute another "<b>postfix reload</b>". </p> + +</ul> + +<h2><a name="remote_only">Filtering mail from outside users only</a></h2> + +<p> The easiest approach is to configure ONE Postfix instance with +multiple SMTP server IP addresses in master.cf: </p> + +<ul> + +<li> <p> Two SMTP server IP addresses for mail from inside users only, +with content filtering turned off. </p> + +<pre> +/etc/postfix.master.cf: + # ================================================================== + # service type private unpriv chroot wakeup maxproc command + # (yes) (yes) (yes) (never) (100) + # ================================================================== + 1.2.3.4:smtp inet n - n - - smtpd + -o smtpd_client_restrictions=permit_mynetworks,reject + 127.0.0.1:smtp inet n - n - - smtpd + -o smtpd_client_restrictions=permit_mynetworks,reject +</pre> + +<li> <p> One SMTP server address for mail from outside users with +content filtering turned on. </p> + +<pre> +/etc/postfix.master.cf: + # ================================================================= + # service type private unpriv chroot wakeup maxproc command + # (yes) (yes) (yes) (never) (100) + # ================================================================= + 1.2.3.5:smtp inet n - n - - smtpd + -o content_filter=filter-service:filter-destination + -o receive_override_options=no_address_mappings +</pre> + +</ul> + +<p> After this, you can follow the same procedure as outlined in +the "advanced" or "simple" content filtering examples above, except +that you must not specify "content_filter" or "receive_override_options" +in the main.cf file. </p> + +<h2><a name="domain_dependent">Different filters for different +domains</a></h2> + +<p> If you are an MX service provider and want to apply different +content filters for different domains, you can configure ONE Postfix +instance with multiple SMTP server IP addresses in master.cf. Each +address provides a different content filter service. </p> + +<blockquote> +<pre> +/etc/postfix.master.cf: + # ================================================================= + # service type private unpriv chroot wakeup maxproc command + # (yes) (yes) (yes) (never) (100) + # ================================================================= + # SMTP service for domains that are filtered with service1:dest1 + 1.2.3.4:smtp inet n - n - - smtpd + -o content_filter=service1:dest1 + -o receive_override_options=no_address_mappings + + # SMTP service for domains that are filtered with service2:dest2 + 1.2.3.5:smtp inet n - n - - smtpd + -o content_filter=service2:dest2 + -o receive_override_options=no_address_mappings +</pre> +</blockquote> + +<p> After this, you can follow the same procedure as outlined in +the "advanced" or "simple" content filtering examples above, except +that you must not specify "content_filter" or "receive_override_options" +in the main.cf file. </p> + +<p> Set up MX records in the DNS that route each domain to the +proper SMTP server instance. </p> + +<h2><a name="dynamic_filter">FILTER actions in access or header/body +tables</a></h2> + +<p> The above filtering configurations are static. Mail that follows +a given path is either always filtered or it is never filtered. As +of Postfix 2.0 you can also turn on content filtering on the fly. +</p> + +<p> To turn on content filtering with an access(5) table rule: </p> + +<blockquote> +<pre> +/etc/postfix/access: + <i>whatever</i> FILTER foo:bar +</pre> +</blockquote> + +<p> To turn on content filtering with a header_checks(5) or +body_checks(5) table pattern: </p> + +<blockquote> +<pre> +/etc/postfix/header_checks: + /<i>whatever</i>/ FILTER foo:bar +</pre> +</blockquote> + +<p> You can do this in smtpd access maps as well as the cleanup +server's header/body_checks. This feature must be used with great +care: you must disable all the UCE features in the after-filter +smtpd and cleanup daemons or else you will have a content filtering +loop. </p> + +<p> Limitations: </p> + +<ul> + +<li> <p> FILTER actions from smtpd access maps and header/body_checks +take precedence over filters specified with the main.cf content_filter +parameter. </p> + +<li> <p> If a message triggers more than one filter action, only +the last one takes effect. </p> + +<li> <p> The same content filter is applied to all the recipients +of a given message. </p> + +</ul> + +</body> + +</html> |