xref: /netbsd-src/external/ibm-public/postfix/dist/proto/BUILTIN_FILTER_README.html (revision 059c16a85b0b39d60ad6d18f53c09510815afa2b)
1<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
2        "http://www.w3.org/TR/html4/loose.dtd">
3
4<html>
5
6<head>
7
8<title>Postfix Built-in Content Inspection</title>
9
10<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
11<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
12
13</head>
14
15<body>
16
17<h1><img src="postfix-logo.jpg" width="203" height="98" alt="">
18Postfix Built-in Content Inspection</h1>
19
20<hr>
21
22<h2>Built-in content inspection introduction </h2>
23
24<p> Postfix supports a built-in filter mechanism that examines
25message header and message body content, one line at a time, before
26it is stored in the Postfix queue. The filter is usually implemented
27with POSIX or PCRE regular expressions, as described in the
28header_checks(5) manual page. </p>
29
30<p>  The original purpose of the built-in filter is to stop an
31outbreak of specific email worms or viruses, and it does this job
32well. The filter has also helped to block bounced junk email,
33bounced email from worms or viruses, and notifications from virus
34detection systems.  Information about this secondary application
35is given in the BACKSCATTER_README document.  </p>
36
37<p> Because the built-in filter is optimized for stopping specific
38worms and virus outbreaks, it has <a href="#limitations">limitations</a>
39that make it NOT suitable for general junk email and virus detection.
40For that, you should use one of the external content inspection
41methods that are described in the FILTER_README, SMTPD_PROXY_README
42and MILTER_README documents.  </p>
43
44<p> The following diagram gives an over-all picture of how Postfix
45built-in content inspection works: </p>
46
47<blockquote>
48
49<table>
50
51<tr>
52
53    <td colspan="4"> <td bgcolor="#f0f0ff" align="center"
54    valign="middle"> Postmaster<br> notifications </td>
55
56</tr>
57
58<tr>
59
60    <td colspan="4"> <td align="center"> <tt> |<br>v </tt></td>
61
62</tr>
63
64<tr>
65
66        <td bgcolor="#f0f0ff" align="center" valign="middle">
67        Network or<br> local users </td>
68
69    <td align="center" valign="middle"> <tt> -&gt; </tt> </td>
70
71        <td bgcolor="#f0f0ff" align="center" valign="middle">
72
73        <b> Built-in<br> filter</b> </td>
74
75    <td align="center" valign="middle"> <tt> -&gt; </tt> </td>
76
77        <td bgcolor="#f0f0ff" align="center" valign="middle">
78        Postfix<br> queue </td>
79
80    <td align="center" valign="middle"> <tt> -&gt; </tt> </td>
81
82	<td bgcolor="#f0f0ff" align="center" valign="middle">
83	Delivery<br> agents </td>
84
85    <td align="center" valign="middle"> <tt> -&gt; </tt> </td>
86
87	<td bgcolor="#f0f0ff" align="center" valign="middle">
88	Network or<br> local mailbox </td>
89
90</tr>
91
92<tr>
93
94    <td colspan="4"> <td align="center"> ^<br> <tt> | </tt> </td>
95    <td> </td> <td align="center"> <tt> |<br>v </tt> </td>
96
97</tr>
98
99<tr>
100
101    <td colspan="4"> <td colspan="3" bgcolor="#f0f0ff" align="center"
102    valign="middle"> Undeliverable mail<br> Forwarded mail</td>
103
104</tr>
105
106</table>
107
108</blockquote>
109
110<p> The picture makes clear that the filter works while Postfix is
111receiving new mail.  This means that Postfix can reject mail from
112the network without having to return undeliverable mail to the
113originator address (which is often spoofed anyway). However, this
114ability comes at a price:  if mail inspection takes too much time,
115then the remote client will time out, and the client may send the
116same message repeatedly. </p>
117
118<p>Topics covered by this document: </p>
119
120<ul>
121
122<li><a href="#what">What mail is subjected to header/body checks </a>
123
124<li><a href="#limitations">Limitations of Postfix header/body checks </a>
125
126<li><a href="#daily">Preventing daily mail status reports from being blocked </a>
127
128<li><a href="#remote_only">Configuring header/body checks for mail from outside users only</a>
129
130<li><a href="#mx_submission">Configuring different header/body checks for MX service and submission service</a>
131
132<li><a href="#domain_except">Configuring header/body checks for mail to some domains only</a>
133
134</ul>
135
136<h2><a name="what">What mail is subjected to header/body checks </a></h2>
137
138<p> Postfix header/body checks are implemented by the cleanup(8)
139server before it injects mail into the incoming queue.  The diagram
140below zooms in on the cleanup(8) server, and shows that this server
141handles mail from many different sources. In order to keep the
142diagram readable, the sources of postmaster notifications are not
143shown, because they can be produced by many Postfix daemon processes.
144</p>
145
146<blockquote>
147
148<table>
149
150<tr> <td colspan="2"> </td> <td bgcolor="#f0f0ff" align="center"
151valign="middle"> bounce(8)<br> (undeliverable) </td> </tr>
152
153<tr> <td bgcolor="#f0f0ff" align="center" valign="middle"> <b>
154smtpd(8)<br> (network)</b> </td> <td align="left" valign="bottom">
155<tt> \ </tt> </td> <td align="center" valign="middle"> <tt> |<br>v
156</tt> </td> </tr>
157
158<tr> <td> </td> <td> </td> </tr>
159
160<tr> <td bgcolor="#f0f0ff" align="center" valign="middle"> <b>
161qmqpd(8)<br> (network)</b> </td> <td align="center" valign="middle">
162<tt> -\<br>-/ </tt> </td> <td bgcolor="#f0f0ff" align="center"
163valign="middle"> cleanup(8) </td> <td align="center" valign="middle">
164<tt> -&gt; </tt> </td> <td bgcolor="#f0f0ff" align="center"
165valign="middle"> <a href="QSHAPE_README.html#incoming_queue">
166incoming<br> queue </a> </td> </tr>
167
168<tr> <td bgcolor="#f0f0ff" align="center" valign="middle"> <b>
169pickup(8)<br> (local)</b> </td> <td align="left" valign="top"> <tt>
170/ </tt> </td> <td align="center" valign="middle"> ^<br> <tt> |
171</tt> </td> </tr>
172
173<tr> <td colspan="2"> </td> <td bgcolor="#f0f0ff" align="center"
174valign="middle"> local(8)<br> (forwarded) </td> </tr>
175
176</table>
177
178</blockquote>
179
180<p> For efficiency reasons, only mail that enters from outside of
181Postfix is inspected with header/body checks. It would be inefficient
182to filter already filtered mail again, and it would be undesirable
183to block postmaster notifications.  The table below summarizes what
184mail is and is not subject to header/body checks. </p>
185
186<blockquote>
187
188<table border="1">
189
190<tr> <th> Message type </th> <th> Source </th> <th> Header/body checks? </th> </tr>
191
192<tr> <td> Undeliverable mail </td> <td> bounce(8) </td> <td> No </td> </tr>
193
194<tr> <td> Network mail </td> <td> smtpd(8) </td> <td> Configurable </td> </tr>
195
196<tr> <td> Network mail </td> <td> qmqpd(8) </td>  <td> Configurable </td> </tr>
197
198<tr> <td> Local submission </td> <td> pickup(8) </td>  <td> Configurable </td> </tr>
199
200<tr> <td> Local forwarding </td> <td> local(8) </td> <td> No </td> </tr>
201
202<tr> <td> Postmaster notice </td> <td> many </td> <td> No </td> </tr>
203
204</table>
205
206</blockquote>
207
208<p> How does Postfix decide what mail needs to be filtered? It
209would be clumsy to make the decision in the cleanup(8) server, as
210this program receives mail from so many different sources.  Instead,
211header/body checks are requested by the source.  Examples of how
212to turn off header/body checks for mail received with smtpd(8),
213qmqpd(8) or pickup(8) are given below under "<a
214href="#remote_only">Configuring header/body checks for mail from
215outside users only</a>", "<a href="#mx_submission">Configuring
216different header/body checks for MX service and submission
217service</a>", and "<a href="#domain_except">Configuring
218header/body checks for mail to some domains only</a>".  </p>
219
220<h2><a name="limitations">Limitations of Postfix header/body checks </a></h2>
221
222<ul>
223
224<li> <p> Header/body checks do not decode message headers or message
225body content. For example, if text in the message body is BASE64
226encoded (RFC 2045) then your regular expressions will have to match
227the BASE64 encoded form. Likewise, message headers with encoded
228non-ASCII characters (RFC 2047) need to be matched in their encoded
229form. </p>
230
231<li> <p> Header/body checks cannot filter on a combination of
232message headers or body lines. Header/body checks examine content
233one message header at a time, or one message body line at a time,
234and cannot carry a decision over to the next message header or body
235line.  </p>
236
237<li> <p> Header/body checks cannot depend on the recipient of a
238message.  </p>
239
240<ul>
241
242<li> <p> One message can have multiple recipients, and all recipients
243of a message receive the same treatment. Workarounds have been
244proposed that involve selectively deferring some recipients of
245multi-recipient mail, but that results in poor SMTP performance
246and does not work for non-SMTP mail.  </p>
247
248<li> <p> Some sources of mail send the headers and content ahead
249of the recipient information. It would be inefficient to buffer up
250an entire message before deciding if it needs to be filtered, and
251it would be clumsy to filter mail and to buffer up all the actions
252until it is known whether those actions need to be executed.  </p>
253
254</ul>
255
256<li> <p> Despite warnings, some people try to use the built-in
257filter feature for general junk email and/or virus blocking, using
258hundreds or even thousands of regular expressions. This can result
259in catastrophic performance failure. The symptoms are as follows:
260</p>
261
262<ul>
263
264<li> <p> The cleanup(8) processes use up all available CPU time in
265order to process the regular expressions, and/or they use up all
266available memory so that the system begins to swap. This slows down
267all incoming mail deliveries.  </p>
268
269<li> <p> As Postfix needs more and more time to receive an email
270message, the number of simultaneous SMTP sessions increases to the
271point that the SMTP server process limit is reached. </p>
272
273<li> <p> While all SMTP server processes are waiting for the
274cleanup(8) servers to finish, new SMTP clients have to wait until
275an SMTP server process becomes available. This causes mail deliveries
276to time out before they have even begun.  </p>
277
278</ul>
279
280<p> The remedy for this type of performance problem is simple:
281don't use header/body checks for general junk email and/or virus
282blocking, and don't filter mail before it is queued.  When performance
283is a concern, use an external content filter that runs after mail
284is queued, as described in the FILTER_README document. </p>
285
286</ul>
287
288<h2><a name="daily">Preventing daily mail status reports from being blocked </a></h2>
289
290<p>The following is quoted from Jim Seymour's Pflogsumm FAQ at
291http://jimsun.linxnet.com/downloads/pflogsumm-faq.txt. Pflogsumm
292is a program that analyzes Postfix logs, including the logging from
293rejected mail. If these logs contain text that was rejected by
294Postfix body_checks patterns, then the logging is also likely to
295be rejected by those same body_checks patterns. This problem does
296not exist with header_checks patterns, because those are not applied
297to the text that is part of the mail status report. </p>
298
299<blockquote>
300
301<p>You configure Postfix to do body checks, Postfix does its thing,
302Pflogsumm reports it and Postfix catches the same string in the
303Pflogsumm report.  There are several solutions to this. </p>
304
305<p> Wolfgang Zeikat contributed this: </p>
306
307<blockquote>
308<pre>
309#!/usr/bin/perl
310use MIME::Lite;
311
312### Create a new message:
313$msg = MIME::Lite-&gt;new(
314    From     =&gt; 'your@send.er',
315    To       =&gt; 'your@recipie.nt',
316    # Cc     =&gt; 'some@other.com, some@more.com',
317    Subject  =&gt; 'pflogsumm',
318    Date     =&gt; `date`,
319    Type     =&gt; 'text/plain',
320    Encoding =&gt; 'base64',
321    Path     =&gt; '/tmp/pflogg',
322);
323
324$msg-&gt;send;
325</pre>
326</blockquote>
327
328<p> Where "/tmp/pflogg" is the output of Pflogsumm.  This puts Pflogsumm's
329output in a base64 MIME attachment. </p>
330
331</blockquote>
332
333<p> Note by Wietse: if you run this on a machine that is accessible
334by untrusted users, it is safer to store the Pflogsumm report in
335a directory that is not world writable. </p>
336
337<blockquote>
338
339<p> In a follow-up to a thread in the postfix-users mailing list, Ralf
340Hildebrandt noted: </p>
341
342<blockquote> <p> "mpack does the same thing." </p> </blockquote>
343
344</blockquote>
345
346<p> And it does. Which tool one should use is a matter of preference.
347</p>
348
349<p> Other solutions involve additional body_checks rules that make
350exceptions for daily mail status reports, but this is not recommended.
351Such rules slow down all mail and complicate Postfix maintenance.
352</p>
353
354<h2><a name="remote_only">Configuring header/body checks for mail from outside users only</a></h2>
355
356<p> The following information applies to Postfix 2.1 and later.
357Earlier
358Postfix versions do not support the receive_override_options feature.
359</p>
360
361<p> The easiest approach is to configure ONE Postfix instance with
362multiple SMTP server IP addresses in master.cf: </p>
363
364<ul>
365
366<li> <p> Two SMTP server IP addresses for mail from inside users
367only, with header/body filtering turned off, and a local mail pickup
368service with header/body filtering turned off.  </p>
369
370<pre>
371/etc/postfix.master.cf:
372    # ==================================================================
373    # service      type  private unpriv  chroot  wakeup  maxproc command
374    #                    (yes)   (yes)   (yes)   (never) (100)
375    # ==================================================================
376    1.2.3.4:smtp   inet  n       -       n       -       -       smtpd
377        -o receive_override_options=no_header_body_checks
378    127.0.0.1:smtp inet  n       -       n       -       -       smtpd
379        -o receive_override_options=no_header_body_checks
380    pickup         fifo  n       -       n       60      1       pickup
381        -o receive_override_options=no_header_body_checks
382</pre>
383
384<li> <p> Add some firewall rule to prevent access to 1.2.3.4:smtp
385from the outside world. </p>
386
387<li> <p> One SMTP server address for mail from outside users with
388header/body filtering turned on via main.cf. </p>
389
390<pre>
391/etc/postfix.master.cf:
392    # =================================================================
393    # service     type  private unpriv  chroot  wakeup  maxproc command
394    #                   (yes)   (yes)   (yes)   (never) (100)
395    # =================================================================
396    1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
397</pre>
398
399</ul>
400
401<h2><a name="mx_submission">Configuring different header/body checks for MX service and submission service</a></h2>
402
403<p> If authorized user submissions require different header/body
404checks than mail from remote MTAs, then this is possible as long
405as you have separate mail streams for authorized users and for MX
406service. </p>
407
408<p> The example below assumes that authorized users connect to TCP
409port 587 (submission) or 465 (smtps), and that remote MTAs connect
410to TCP port 25 (smtp). </p>
411
412<p> First, we define a few "user-defined" parameters that will
413override settings for the submission and smtps services. </p>
414
415<blockquote>
416<pre>
417/etc/postfix/main.cf:
418    msa_cleanup_service_name = msa_cleanup
419    msa_header_checks = pcre:/etc/postfix/msa_header_checks
420    msa_body_checks = pcre:/etc/postfix/msa_body_checks
421</pre>
422</blockquote>
423
424<p> Next, we define msa_cleanup as a dedicated cleanup service that
425will be used only by the submission and smtps services.  This service
426uses the header_checks and body_checks overrides that were defined
427above. </p>
428
429<blockquote>
430<pre>
431/etc/postfix.master.cf:
432    # =================================================================
433    # service     type  private unpriv  chroot  wakeup  maxproc command
434    #                   (yes)   (yes)   (yes)   (never) (100)
435    # =================================================================
436    smtp          inet  n       -       n       -       -       smtpd
437    msa_cleanup   unix  n       -       n       -       0       cleanup
438        -o header_checks=$msa_header_checks
439        -o body_checks=$msa_body_checks
440    submission    inet  n       -       n       -       -       smtpd
441        -o cleanup_service_name=$msa_cleanup_service_name
442        -o syslog_name=postfix/submission
443        <i>...[see sample master.cf file for more]...</i>
444    smtps         inet  n       -       n       -       -       smtpd
445        -o cleanup_service_name=$msa_cleanup_service_name
446        -o syslog_name=postfix/smtps
447        -o smtpd_tls_wrappermode=yes
448        <i>...[see sample master.cf file for more]...</i>
449</pre>
450</blockquote>
451
452<p> By keeping the "msa_xxx" parameter settings in main.cf, you
453keep your master.cf file simple, and you minimize the amount
454of duplication. </p>
455
456<h2><a name="domain_except">Configuring header/body checks for mail to some domains only</a></h2>
457
458<p> The following information applies to Postfix 2.1. Earlier
459Postfix versions do not support the receive_override_options feature.
460</p>
461
462<p> If you are an MX service provider and want to enable header/body
463checks only for some domains, you can configure ONE Postfix
464instance with multiple SMTP server IP addresses in master.cf. Each
465address provides a different service. </p>
466
467<blockquote>
468
469<pre>
470/etc/postfix.master.cf:
471    # =================================================================
472    # service     type  private unpriv  chroot  wakeup  maxproc command
473    #                   (yes)   (yes)   (yes)   (never) (100)
474    # =================================================================
475    # SMTP service for domains with header/body checks turned on.
476    1.2.3.4:smtp  inet  n       -       n       -       -       smtpd
477
478    # SMTP service for domains with header/body checks turned off.
479    1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
480        -o receive_override_options=no_header_body_checks
481</pre>
482</blockquote>
483
484<p> Once this is set up you can configure MX records in the DNS
485that route each domain to the proper SMTP server instance. </p>
486
487</body>
488
489</html>
490