~ubuntu-branches/ubuntu/dapper/postfix/dapper-security

« back to all changes in this revision

Viewing changes to proto/FILTER_README.html

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2005-02-27 09:33:07 UTC
  • Revision ID: james.westby@ubuntu.com-20050227093307-cn789t27ibnlh6tf
Tags: upstream-2.1.5
ImportĀ upstreamĀ versionĀ 2.1.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 After-Queue Content Filter </title>
 
9
 
 
10
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
 
11
 
 
12
</head>
 
13
 
 
14
<body>
 
15
 
 
16
<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix After-Queue Content Filter </h1>
 
17
 
 
18
<hr>
 
19
 
 
20
<h2>Introduction</h2>
 
21
 
 
22
<p> This document requires Postfix version 2.1 or later. </p>
 
23
 
 
24
<p> Normally, Postfix receives mail, stores it in the mail queue
 
25
and then delivers it. With the external content filter described
 
26
here, mail is filtered AFTER it is queued. This approach decouples
 
27
mail receiving processes from mail filtering processes, and gives
 
28
you maximal control over how many filtering processes you are
 
29
willing to run in parallel.  </p>
 
30
 
 
31
<p> The after-queue content filter is meant to be used as follows: </p>
 
32
 
 
33
<blockquote>
 
34
 
 
35
<table>
 
36
 
 
37
<tr>
 
38
 
 
39
        <td bgcolor="#f0f0ff" align="center" valign="middle">
 
40
        Network or<br> local users </td>
 
41
 
 
42
    <td align="center" valign="middle"> <tt> -&gt; </tt> </td>
 
43
 
 
44
        <td bgcolor="#f0f0ff" align="center" valign="middle">
 
45
        Postfix<br> queue </td>
 
46
 
 
47
    <td align="center" valign="middle"> <tt> -&gt; </tt> </td>
 
48
 
 
49
        <td bgcolor="#f0f0ff" align="center" valign="middle">
 
50
        <b>Content<br> filter</b> </td>
 
51
 
 
52
    <td align="center" valign="middle"> <tt> -&gt; </tt> </td>
 
53
 
 
54
        <td bgcolor="#f0f0ff" align="center" valign="middle">
 
55
        Postfix<br> queue </td>
 
56
 
 
57
    <td align="center" valign="middle"> <tt> -&gt; </tt> </td>
 
58
 
 
59
        <td bgcolor="#f0f0ff" align="center" valign="middle">
 
60
        Network or<br> local mailbox </td>
 
61
 
 
62
</tr>
 
63
 
 
64
</table>
 
65
 
 
66
</blockquote>
 
67
 
 
68
<p> This document describes implementations that use a single
 
69
Postfix instance for everything: receiving, filtering and delivering
 
70
mail.  Applications that use two separate Postfix instances will
 
71
be covered by a later version of this document.  </p>
 
72
 
 
73
<p> The after-queue content filter is not to be confused with the
 
74
approach that is described in the SMTPD_PROXY_README document,
 
75
where incoming SMTP mail is filtered BEFORE it is stored into the
 
76
Postfix queue.  </p>
 
77
 
 
78
<p> This document describes two approaches to content filter
 
79
all email, as well as several options filter mail selectively: </p>
 
80
 
 
81
<ul>
 
82
 
 
83
<li><a href="#principles">Principles of operation</a>
 
84
 
 
85
<li><a href="#simple_filter">Simple content filter example</a>
 
86
 
 
87
<li><a href="#simple_limitations">Simple content filter limitations</a>
 
88
 
 
89
<li><a href="#advanced_filter">Advanced content filter example</a>
 
90
 
 
91
<li><a href="#performance">Advanced content filter performance</a>
 
92
 
 
93
<li><a href="#remote_only">Filtering mail from outside users only</a>
 
94
 
 
95
<li><a href="#domain_dependent">Different filters for different domains</a>
 
96
 
 
97
<li><a href="#dynamic_filter">FILTER actions in access or header/body tables</a>
 
98
 
 
99
</ul>
 
100
 
 
101
 
 
102
<h2><a name="principles">Principles of operation</a> </h2>
 
103
 
 
104
<p> An external content filter receives unfiltered mail from Postfix
 
105
(as described further below) and does one of the following: </p>
 
106
 
 
107
<ol>
 
108
 
 
109
<li> <p> Re-inject the mail back into Postfix, perhaps after changing
 
110
    content and/or destination. </p>
 
111
 
 
112
<li> <p> Reject the mail (by sending a suitable status code back to
 
113
    Postfix). Postfix will return the mail to the sender. </p>
 
114
 
 
115
</ol>
 
116
 
 
117
<p> NOTE: in this time of mail worms and forged spam, it is a VERY
 
118
BAD IDEA to send viruses back to the sender address, because the
 
119
sender address is almost certainly not the originator. It is better
 
120
to discard known viruses, and to quarantine material that is
 
121
suspect so that a human can decide what to do with it. </p>
 
122
 
 
123
<h2><a name="simple_filter">Simple content filter example</a></h2>
 
124
 
 
125
<p> The first example is simple to set up.  Postfix receives
 
126
unfiltered mail from the network with the smtpd(8) server, and
 
127
delivers unfiltered mail to a content filter with the Postfix
 
128
pipe(8) delivery agent.  The content filter injects filtered mail
 
129
back into Postfix with the Postfix sendmail(1) command, so that
 
130
Postfix can deliver it to the final destination. </p>
 
131
 
 
132
<p> This means that mail submitted via the Postfix sendmail(1)
 
133
command cannot be content filtered. </p>
 
134
 
 
135
<p> In the figure below, names followed by a number represent
 
136
Postfix commands or daemon programs. See the OVERVIEW
 
137
document for an introduction to the Postfix architecture. </p>
 
138
 
 
139
<blockquote>
 
140
 
 
141
<table>
 
142
 
 
143
<tr>
 
144
 
 
145
        <td align="center" valign="top"> Unfiltered<br> <br> </td>
 
146
 
 
147
    <td align="center" valign="top"> <tt> -&gt;</tt><br> <br> </td>
 
148
 
 
149
       <td bgcolor="#f0f0ff" align="center" valign="middle">
 
150
       smtpd(8)<br> <br> pickup(8) </td>
 
151
 
 
152
   <td align="center" valign="middle"> <tt> &gt;- </tt> </td>
 
153
 
 
154
       <td bgcolor="#f0f0ff" align="center" valign="middle">
 
155
       cleanup(8) </td>
 
156
 
 
157
   <td align="center" valign="middle"> <tt> -&gt; </tt> </td>
 
158
 
 
159
       <td bgcolor="#f0f0ff" align="center" valign="middle">
 
160
       qmgr(8)<br> Postfix <br> queue </td>
 
161
 
 
162
   <td align="center" valign="middle"> <tt> -&lt; </tt> </td>
 
163
 
 
164
       <td bgcolor="#f0f0ff" align="center" valign="middle">
 
165
       local(8)<br> smtp(8)<br> pipe(8) </td>
 
166
 
 
167
   <td align="center" valign="top"> <tt> -&gt;</tt><br> <tt>
 
168
   -&gt;</tt><br> </td>
 
169
 
 
170
       <td align="center" valign="top"> Filtered<br> Filtered<br>
 
171
       </td>
 
172
 
 
173
</tr>
 
174
 
 
175
<tr>
 
176
 
 
177
   <td colspan="2"> </td>
 
178
 
 
179
       <td align="center" valign="middle"> ^<br> <tt> | </tt> </td>
 
180
 
 
181
   <td colspan="5"> </td>
 
182
 
 
183
       <td align="center" valign="middle"> <tt> |<br> v </tt> </td>
 
184
 
 
185
   <td colspan="2"> </td>
 
186
 
 
187
</tr>
 
188
 
 
189
<tr>
 
190
 
 
191
   <td colspan="2"> </td>
 
192
 
 
193
        <td bgcolor="#f0f0ff" align="center" valign="middle">
 
194
        <a href="QSHAPE_README.html#maildrop_queue"> maildrop <br>
 
195
        queue </a> </td>
 
196
 
 
197
   <td align="center" valign="middle"> <tt> &lt;- </tt> </td>
 
198
 
 
199
        <td bgcolor="#f0f0ff" align="center" valign="middle">Postfix<br>
 
200
        postdrop(1) </td>
 
201
 
 
202
   <td align="center" valign="middle"> <tt> &lt;- </tt> </td>
 
203
 
 
204
        <td bgcolor="#f0f0ff" align="center" valign="middle">Postfix<br>
 
205
        sendmail(1) </td>
 
206
 
 
207
   <td align="center" valign="middle"> <tt> &lt;- </tt> </td>
 
208
 
 
209
        <td bgcolor="#f0f0ff" align="center" valign="middle">Content
 
210
        <br> filter </td>
 
211
 
 
212
   <td colspan="2"> </td>
 
213
 
 
214
</tr>
 
215
 
 
216
</table>
 
217
 
 
218
</blockquote>
 
219
 
 
220
<p> The content filter can be a simple shell script like this: </p>
 
221
 
 
222
<blockquote>
 
223
<pre>
 
224
 1 #!/bin/sh
 
225
 2 
 
226
 3 # Simple shell-based filter. It is meant to be invoked as follows:
 
227
 4 #       /path/to/script -f sender recipients...
 
228
 5 
 
229
 6 # Localize these.
 
230
 7 INSPECT_DIR=/var/spool/filter
 
231
 8 SENDMAIL="/usr/sbin/sendmail -i"
 
232
 9 
 
233
10 # Exit codes from &lt;sysexits.h&gt;
 
234
11 EX_TEMPFAIL=75
 
235
12 EX_UNAVAILABLE=69
 
236
13 
 
237
14 # Clean up when done or when aborting.
 
238
15 trap "rm -f in.$$" 0 1 2 3 15
 
239
16 
 
240
17 # Start processing.
 
241
18 cd $INSPECT_DIR || {
 
242
19     echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; }
 
243
20 
 
244
21 cat &gt;in.$$ || { 
 
245
22     echo Cannot save mail to file; exit $EX_TEMPFAIL; }
 
246
23 
 
247
24 # Specify your content filter here.
 
248
25 # filter &lt;in.$$ || {
 
249
26 #   echo Message content rejected; exit $EX_UNAVAILABLE; }
 
250
27 
 
251
28 $SENDMAIL "$@" &lt;in.$$
 
252
29 
 
253
30 exit $?
 
254
</pre>
 
255
</blockquote>
 
256
 
 
257
<p> Notes: </p>
 
258
 
 
259
<ul>
 
260
 
 
261
<li> <p> Line 21: The idea is to first capture the message to
 
262
file and then run the content through a third-party content filter
 
263
program. </p>
 
264
 
 
265
<li> <p> Line 22: If the mail cannot be captured to file, mail
 
266
delivery is deferred by terminating with exit status 75 (EX_TEMPFAIL).
 
267
Postfix places the message in the deferred mail queue and tries
 
268
again later.  </p>
 
269
 
 
270
<li> <p> Line 25: You will need to specify a real content filter
 
271
program here that receives the content on standard input. </p>
 
272
 
 
273
<li> <p> Line 26: If the content filter program finds a problem,
 
274
the mail is bounced by terminating with exit status 69 (EX_UNAVAILABLE).
 
275
Postfix will return the message to the sender as undeliverable.
 
276
</p>
 
277
 
 
278
<li> <p> Note: in this time of mail worms and spam, it is a BAD
 
279
IDEA to send known viruses or spam back to the sender, because that
 
280
address is likely to be forged. It is safer to discard known to be
 
281
bad content and to quarantine suspicious content so that it can
 
282
be inspected by a human being. </p>
 
283
 
 
284
<li> <p> Line 28: If the content is OK, it is given as input to
 
285
the Postfix sendmail command, and the exit status of the filter
 
286
command is whatever exit status the Postfix sendmail command
 
287
produces. Postfix will deliver the message as usual. </p>
 
288
 
 
289
<li> <p> Line 30: Postfix returns the exit status of the Postfix
 
290
sendmail command. </p>
 
291
 
 
292
</ul>
 
293
 
 
294
<p> I suggest that you first run this script by hand until you are
 
295
satisfied with the results. Run it with a real message (headers+body)
 
296
as input: </p>
 
297
 
 
298
<blockquote>
 
299
<pre>
 
300
% /path/to/script -f sender recipient... &lt;message-file
 
301
</pre>
 
302
</blockquote>
 
303
 
 
304
<p> Once you're satisfied with the content filtering script: </p>
 
305
 
 
306
<ul>
 
307
 
 
308
<li> <p> Create a dedicated local user account called "filter".  This
 
309
user handles all potentially dangerous mail content - that is
 
310
why it should be a separate account. Do not use "nobody", and
 
311
most certainly do not use "root" or "postfix". </p>
 
312
 
 
313
<li> <p> Create a directory /var/spool/filter that is accessible only
 
314
to the "filter" user. This is where the content filtering script
 
315
is supposed to store its temporary files. </p>
 
316
 
 
317
<li> <p> Configure Postfix to deliver mail to the content filter
 
318
with the pipe(8) delivery agent. </p>
 
319
 
 
320
<pre>
 
321
/etc/postfix/master.cf:
 
322
  # =============================================================
 
323
  # service type  private unpriv  chroot  wakeup  maxproc command
 
324
  #               (yes)   (yes)   (yes)   (never) (100)
 
325
  # =============================================================
 
326
  filter    unix  -       n       n       -       10      pipe
 
327
    flags=Rq user=filter argv=/path/to/script -f ${sender} -- ${recipient}
 
328
</pre>
 
329
 
 
330
<p> This runs up to 10 content filters in parallel. Instead of a
 
331
limit of 10 concurrent processes, use whatever process limit is
 
332
feasible for your machine.  Content inspection software can gobble
 
333
up a lot of system resources, so you don't want to have too much
 
334
of it running at the same time. </p>
 
335
 
 
336
<li> <p> To turn on content filtering for mail arriving via SMTP
 
337
only, append "-o content_filter=filter:dummy" to the master.cf
 
338
entry that defines the Postfix SMTP server: </p>
 
339
 
 
340
<pre>
 
341
/etc/postfix/master.cf:
 
342
  # =============================================================
 
343
  # service type  private unpriv  chroot  wakeup  maxproc command
 
344
  #               (yes)   (yes)   (yes)   (never) (100)
 
345
  # =============================================================
 
346
  smtp      inet  ...other stuff here, do not change...   smtpd
 
347
        -o content_filter=filter:dummy
 
348
</pre>
 
349
 
 
350
<p> The "content_filter" line causes Postfix to add one content
 
351
filter request record to each incoming mail message, with content
 
352
"filter:dummy". This record overrides the normal mail routing
 
353
and causes mail to be given to the content filter instead. </p>
 
354
 
 
355
<p> The content_filter configuration parameter accepts the same syntax
 
356
as the right-hand side in a Postfix transport table.  </p>
 
357
 
 
358
<li> <p> Execute "<b>postfix reload</b>" to complete the change.  </p>
 
359
 
 
360
</ul>
 
361
 
 
362
<p> To turn off content filtering, edit the master.cf file, remove
 
363
the "-o content_filter=filter:dummy" text from the entry that
 
364
defines the Postfix SMTP server, and execute another "<b>postfix
 
365
reload</b>". </p>
 
366
 
 
367
<p> With the shell script as shown above you will lose a factor of
 
368
four in Postfix performance for transit mail that arrives and leaves
 
369
via SMTP. You will lose another factor in transit performance for
 
370
each additional temporary file that is created and deleted in the
 
371
process of content filtering.  The performance impact is less for
 
372
mail that is submitted or delivered locally, because such deliveries
 
373
are already slower than SMTP transit mail. </p>
 
374
 
 
375
<h2><a name="simple_limitations">Simple content filter limitations</a></h2>
 
376
 
 
377
<p> The problem with content filters like the one above is that
 
378
they are not very robust. The reason is that the software does not
 
379
talk a well-defined protocol with Postfix. If the filter shell
 
380
script aborts because the shell runs into some memory allocation
 
381
problem, the script will not produce a nice exit status as defined
 
382
in the file /usr/include/sysexits.h.  Instead of going to the
 
383
deferred queue, mail will bounce.  The same lack of robustness can
 
384
happen when the content filtering software itself runs into a
 
385
resource problem. </p>
 
386
 
 
387
<p> The simple content filter method is not suitable for content
 
388
filter actions that are invoked via header_checks or body_checks
 
389
patterns.  These patterns will be applied again after mail is
 
390
re-injected with the Postfix sendmail command, resulting in a mail
 
391
filtering loop.  The advanced content filtering method (see below)
 
392
makes it possible to turn off header_checks or body_checks patterns
 
393
for filtered mail. </p>
 
394
 
 
395
<h2><a name="advanced_filter">Advanced content filter example</a></h2>
 
396
 
 
397
<p> The second example is more complex, but can give better
 
398
performance, and is less likely to bounce mail when the machine
 
399
runs into some resource problem.  This content filter receives
 
400
unfiltered mail with SMTP on localhost port 10025, and sends filtered
 
401
mail back into Postfix with SMTP on localhost port 10026. </p>
 
402
 
 
403
<p> For non-SMTP capable content filtering software, Bennett Todd's
 
404
SMTP proxy implements a nice PERL/SMTP content filtering framework.
 
405
See: http://bent.latency.net/smtpprox/. </p>
 
406
 
 
407
<p> In the figure below, names followed by a number represent
 
408
Postfix commands or daemon programs. See the OVERVIEW
 
409
document for an introduction to the Postfix architecture. </p>
 
410
 
 
411
<blockquote>
 
412
 
 
413
<table>
 
414
 
 
415
<tr>
 
416
 
 
417
       <td align="center" valign="middle"> Unfiltered<br> <br>
 
418
       Unfiltered</td>
 
419
 
 
420
    <td align="center" valign="middle"> <tt> -&gt;</tt><br> <br>
 
421
    <tt> -&gt; </tt> </td>
 
422
 
 
423
       <td bgcolor="#f0f0ff" align="center" valign="middle">
 
424
       smtpd(8)<br> <br> pickup(8) </td>
 
425
 
 
426
   <td align="center" valign="middle"> <tt> &gt;- </tt> </td>
 
427
 
 
428
       <td bgcolor="#f0f0ff" align="center" valign="middle">
 
429
       cleanup(8) </td>
 
430
 
 
431
   <td align="center" valign="middle"> <tt> -&gt; </tt> </td>
 
432
 
 
433
       <td bgcolor="#f0f0ff" align="center" valign="middle">
 
434
       qmgr(8)<br> Postfix <br> queue </td>
 
435
 
 
436
   <td align="center" valign="middle"> <tt> -&lt; </tt> </td>
 
437
 
 
438
       <td bgcolor="#f0f0ff" align="center" valign="middle">
 
439
       smtp(8)<br> <br> local(8) </td>
 
440
 
 
441
   <td align="center" valign="middle"> <tt> -&gt;</tt><br> <br>
 
442
   <tt> -&gt; </tt></td>
 
443
 
 
444
       <td align="center" valign="middle"> Filtered<br> <br>
 
445
       Filtered</td>
 
446
 
 
447
</tr>
 
448
 
 
449
<tr>
 
450
 
 
451
   <td colspan="4"> </td>
 
452
 
 
453
       <td align="center" valign="middle"> ^<br> <tt> | </tt> </td>
 
454
 
 
455
   <td> </td>
 
456
 
 
457
       <td align="center" valign="middle"> <tt> |<br> v </tt> </td>
 
458
 
 
459
   <td colspan="4"> </td>
 
460
 
 
461
</tr>
 
462
 
 
463
<tr>
 
464
 
 
465
   <td colspan="4"> </td>
 
466
 
 
467
       <td bgcolor="#f0f0ff" align="center" valign="middle">
 
468
       smtpd(8)<br> 10026 </td>
 
469
 
 
470
   <td> </td>
 
471
 
 
472
       <td bgcolor="#f0f0ff" align="center" valign="middle">
 
473
       smtp(8)<br> </td>
 
474
 
 
475
   <td colspan="4"> </td>
 
476
 
 
477
</tr>
 
478
 
 
479
<tr>
 
480
 
 
481
   <td colspan="4"> </td>
 
482
 
 
483
       <td align="center" valign="middle"> ^<br> <tt> | </tt> </td>
 
484
 
 
485
   <td> </td>
 
486
 
 
487
       <td align="center" valign="middle"> <tt> |<br> v </tt> </td>
 
488
 
 
489
   <td colspan="4"> </td>
 
490
 
 
491
</tr>
 
492
 
 
493
<tr>
 
494
 
 
495
   <td colspan="4"> </td>
 
496
 
 
497
        <td colspan="3" bgcolor="#f0f0ff" align="center"
 
498
        valign="middle">content filter 10025</td>
 
499
 
 
500
   <td colspan="4"> </td>
 
501
 
 
502
</tr>
 
503
 
 
504
</table>
 
505
 
 
506
</blockquote>
 
507
 
 
508
<p> The example given here filters all mail, including mail that
 
509
arrives via SMTP and mail that is locally submitted via the Postfix
 
510
sendmail command. See examples near the end of this document for
 
511
how to exclude local users from filtering, or how to configure a
 
512
destination dependent content filter. </p>
 
513
 
 
514
<p> You can expect to lose about a factor of two in Postfix
 
515
performance for mail that arrives and leaves via SMTP, provided
 
516
that the content filter creates no temporary files. Each temporary
 
517
file created by the content filter adds another factor to the
 
518
performance loss. </p>
 
519
 
 
520
<h3>Advanced content filter: requesting that all mail is filtered</h3>  
 
521
 
 
522
<p> To enable the advanced content filter method for all mail,
 
523
specify in main.cf:  </p>
 
524
 
 
525
<blockquote>
 
526
<pre>
 
527
/etc/postfix/main.cf:
 
528
    content_filter = scan:localhost:10025
 
529
    receive_override_options = no_address_mappings
 
530
</pre>
 
531
</blockquote>
 
532
 
 
533
<ul>
 
534
 
 
535
<li> <p> The "content_filter" line causes Postfix to add one content
 
536
filter request record to each incoming mail message, with content
 
537
"scan:localhost:10025".  The content filter request records are
 
538
added by the smtpd(8) and pickup(8) servers (and qmqpd(8) if you
 
539
decide to enable this service). </p>
 
540
 
 
541
<li> <p> Content filter requests are stored in queue files; this
 
542
is how Postfix keeps track of what mail needs filtering.  When a
 
543
queue file contains a content filter request, the queue manager
 
544
will deliver the mail to the specified content filter regardless
 
545
of its final destination. </p>
 
546
 
 
547
<li> <p> The "receive_override_options" line disables address
 
548
manipulation before the content filter, so that the content filter
 
549
sees the original mail addresses instead of the result of virtual
 
550
alias expansion, canonical mapping, automatic bcc, address
 
551
masquerading, etc. </p>
 
552
 
 
553
</ul>
 
554
 
 
555
<p> To turn off content filtering, delete or comment out the two
 
556
above main.cf lines. All other changes made for advanced content
 
557
filtering have no effect when content filtering is turned off.
 
558
</p>
 
559
 
 
560
<h3> Advanced content filter: sending unfiltered mail to the content
 
561
filter</h3>
 
562
 
 
563
<p> In this example, "scan" is an instance of the Postfix SMTP
 
564
client with slightly different configuration parameters. This is
 
565
how one would set up the service in the Postfix master.cf file:
 
566
</p>
 
567
 
 
568
<blockquote>
 
569
<pre>
 
570
/etc/postfix/master.cf:
 
571
    # =============================================================
 
572
    # service type  private unpriv  chroot  wakeup  maxproc command
 
573
    #               (yes)   (yes)   (yes)   (never) (100)
 
574
    # =============================================================
 
575
    scan      unix  -       -       n       -       10      smtp
 
576
        -o smtp_send_xforward_command=yes
 
577
</pre>
 
578
</blockquote>
 
579
 
 
580
<ul>
 
581
 
 
582
<li> <p> This runs up to 10 content filters in parallel. Instead
 
583
of a limit of 10 concurrent processes, use whatever process limit
 
584
is feasible for your machine.  Content inspection software can
 
585
gobble up a lot of system resources, so you don't want to have too
 
586
much of it running at the same time. </p>
 
587
 
 
588
<li> <p> With "-o smtp_send_xforward_command=yes", the scan transport
 
589
will try to forward the original client name and IP address to the
 
590
after-filter smtpd process, so that filtered mail is logged with
 
591
the real client name IP address. See smtp(8) and XFORWARD_README
 
592
for more information. </p>
 
593
 
 
594
</ul>
 
595
 
 
596
<h3>Advanced content filter: running the content filter</h3>
 
597
 
 
598
<p> The content filter can be set up with the Postfix spawn service,
 
599
which is the Postfix equivalent of inetd. For example, to instantiate
 
600
up to 10 content filtering processes on localhost port 10025: </p>
 
601
 
 
602
<blockquote>
 
603
<pre>
 
604
/etc/postfix/master.cf:
 
605
    # ===================================================================
 
606
    # service       type  private unpriv  chroot  wakeup  maxproc command
 
607
    #                     (yes)   (yes)   (yes)   (never) (100)
 
608
    # ===================================================================
 
609
    localhost:10025 inet  n       n       n       -       10      spawn
 
610
        user=filter argv=/path/to/filter localhost 10026
 
611
</pre>
 
612
</blockquote>
 
613
 
 
614
<ul>
 
615
 
 
616
<li> <p> "filter" is a dedicated local user account.  The user will
 
617
never log in, and can be given a "*" password and non-existent
 
618
shell and home directory.  This user handles all potentially
 
619
dangerous mail content - that is why it should be a separate account.
 
620
</p>
 
621
 
 
622
</ul>
 
623
 
 
624
<p> If you want to have your filter listening on port localhost:10025
 
625
instead of Postfix, then you must run your filter as a stand-alone
 
626
program, and must not use the Postfix spawn service.  </p>
 
627
 
 
628
<h3>Advanced filter: injecting mail back into Postfix</h3>
 
629
 
 
630
<p> The job of the content filter is to either bounce mail with a
 
631
suitable diagnostic, or to feed the mail back into Postfix through
 
632
a dedicated listener on port localhost 10026. </p>
 
633
 
 
634
<p> The simplest content filter just copies SMTP commands and data
 
635
between its inputs and outputs. If it has a problem, all it has to
 
636
do is to reply to an input of `.' from Postfix with `550 content
 
637
rejected', and to disconnect without sending `.' on the connection
 
638
that injects mail back into Postfix. </p>
 
639
 
 
640
<blockquote>
 
641
<pre>
 
642
/etc/postfix/master.cf:
 
643
    # ===================================================================
 
644
    # service       type  private unpriv  chroot  wakeup  maxproc command
 
645
    #                     (yes)   (yes)   (yes)   (never) (100)
 
646
    # ===================================================================
 
647
    localhost:10026 inet  n       -       n       -       10      smtpd
 
648
        -o content_filter= 
 
649
        -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
 
650
        -o smtpd_helo_restrictions=
 
651
        -o smtpd_client_restrictions=
 
652
        -o smtpd_sender_restrictions=
 
653
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
 
654
        -o mynetworks=127.0.0.0/8
 
655
        -o smtpd_authorized_xforward_hosts=127.0.0.0/8
 
656
</pre>
 
657
</blockquote>
 
658
 
 
659
<ul>
 
660
 
 
661
<li> <p> Note: do not use spaces around the "=" or "," characters. </p>
 
662
 
 
663
<li> <p> Note: the SMTP server must not have a smaller process
 
664
limit than the "filter" master.cf entry. </p>
 
665
 
 
666
<li> <p> The "-o content_filter=" overrides main.cf settings, and
 
667
requests no content filtering for mail from the content filter.
 
668
This is required or else mail will stay in the content filtering
 
669
loop. </p>
 
670
 
 
671
<li> <p> The "-o receive_override_options" overrides main.cf
 
672
settings. It is complementary to the options that are specified in
 
673
main.cf: </p>
 
674
 
 
675
<ul>
 
676
 
 
677
    <li> <p> Disable attempts to find out if a recipient is unknown,
 
678
    and disable header/body checks. This work was already done
 
679
    before the content filter and repeating it would be wasteful.
 
680
    </p>
 
681
 
 
682
    <li> <p> Enable virtual alias expansion, canonical mappings,
 
683
    address masquerading, and other address mappings. </p>
 
684
 
 
685
</ul>
 
686
 
 
687
  <p> These receive override options are either implemented by the
 
688
  SMTP server itself, or they are passed on to the cleanup server.
 
689
  </p>
 
690
 
 
691
<li> <p> The "-o smtpd_xxx_restrictions" and "-o mynetworks=127.0.0.0/8"
 
692
override main.cf settings. They turn off junk mail controls that
 
693
would only waste time here.
 
694
 
 
695
<li> <p> With "-o smtpd_authorized_xforward_hosts=127.0.0.0/8",
 
696
the scan transport will try to forward the original client name
 
697
and IP address to the after-filter smtpd process, so that filtered
 
698
mail is logged with the real client name and IP address.  See
 
699
XFORWARD_README and smtpd(8). </p>
 
700
 
 
701
</ul>
 
702
 
 
703
<h2><a name="performance">Advanced content filter performance</a></h2>
 
704
 
 
705
<p> With the "sandwich" approach to content filtering described
 
706
here, it is important to match the filter concurrency to the
 
707
available CPU, memory and I/O resources.  Too few content filter
 
708
processes and mail accumulates in the active queue even with low
 
709
traffic volume; too much concurrency and Postfix ends up deferring
 
710
mail destined for the content filter because processes fail due to
 
711
insufficient resources. </p>
 
712
 
 
713
<p> Currently, content filter performance tuning is a process of
 
714
trial and error; analysis is handicapped because filtered and
 
715
unfiltered messages share the same queue.  As mentioned in the
 
716
introduction of this document, content filtering with multiple
 
717
Postfix instances will be covered in a future version.  </p>
 
718
 
 
719
<h2><a name="remote_only">Filtering mail from outside users only</a></h2>
 
720
 
 
721
<p> The easiest approach is to configure ONE Postfix instance with
 
722
multiple SMTP server IP addresses in master.cf: </p>
 
723
 
 
724
<ul>
 
725
 
 
726
<li> <p> Two SMTP server IP addresses for mail from inside users only,
 
727
with content filtering turned off. </p>
 
728
 
 
729
<pre>
 
730
/etc/postfix.master.cf:
 
731
    # ==================================================================
 
732
    # service      type  private unpriv  chroot  wakeup  maxproc command
 
733
    #                    (yes)   (yes)   (yes)   (never) (100)
 
734
    # ==================================================================
 
735
    1.2.3.4:smtp   inet  n       -       n       -       -       smtpd
 
736
        -o smtpd_client_restrictions=permit_mynetworks,reject
 
737
    127.0.0.1:smtp inet  n       -       n       -       -       smtpd
 
738
        -o smtpd_client_restrictions=permit_mynetworks,reject
 
739
</pre>
 
740
 
 
741
<li> <p> One SMTP server address for mail from outside users with
 
742
content filtering turned on. </p>
 
743
 
 
744
<pre>
 
745
/etc/postfix.master.cf:
 
746
    # =================================================================
 
747
    # service     type  private unpriv  chroot  wakeup  maxproc command
 
748
    #                   (yes)   (yes)   (yes)   (never) (100)
 
749
    # =================================================================
 
750
    1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
 
751
        -o content_filter=foo:bar 
 
752
        -o receive_override_options=no_address_mappings
 
753
</pre>
 
754
 
 
755
</ul>
 
756
 
 
757
<p> After this, you can follow the same procedure as outlined in
 
758
the "advanced" or "simple" content filtering examples above, except
 
759
that you must not specify "content_filter" or "receive_override_options"
 
760
in the main.cf file. </p>
 
761
 
 
762
<h2><a name="domain_dependent">Different filters for different
 
763
domains</a></h2>
 
764
 
 
765
<p> If you are an MX service provider and want to apply different
 
766
content filters for different domains, you can configure ONE Postfix
 
767
instance with multiple SMTP server IP addresses in master.cf. Each
 
768
address provides a different content filter service. </p>
 
769
 
 
770
<blockquote>
 
771
<pre>
 
772
/etc/postfix.master.cf:
 
773
    # =================================================================
 
774
    # service     type  private unpriv  chroot  wakeup  maxproc command
 
775
    #                   (yes)   (yes)   (yes)   (never) (100)
 
776
    # =================================================================
 
777
    # SMTP service for domains that are content filtered with foo:bar
 
778
    1.2.3.4:smtp  inet  n       -       n       -       -       smtpd
 
779
        -o content_filter=foo:bar 
 
780
        -o receive_override_options=no_address_mappings
 
781
 
 
782
    # SMTP service for domains that are content filtered with xxx:yyy
 
783
    1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
 
784
        -o content_filter=xxx:yyy 
 
785
        -o receive_override_options=no_address_mappings
 
786
</pre>
 
787
</blockquote>
 
788
 
 
789
<p> After this, you can follow the same procedure as outlined in
 
790
the "advanced" or "simple" content filtering examples above, except
 
791
that you must not specify "content_filter" or "receive_override_options"
 
792
in the main.cf file. </p>
 
793
 
 
794
<p> Set up MX records in the DNS that route each domain to the
 
795
proper SMTP server instance. </p>
 
796
 
 
797
<h2><a name="dynamic_filter">FILTER actions in access or header/body
 
798
tables</a></h2>
 
799
 
 
800
<p> The above filtering configurations are static. Mail that follows
 
801
a given path is either always filtered or it is never filtered. As
 
802
of Postfix 2.0 you can also turn on content filtering on the fly.
 
803
</p>
 
804
 
 
805
<p> To turn on content filtering with an access(5) table rule: </p>
 
806
 
 
807
<blockquote>
 
808
<pre>
 
809
/etc/postfix/access:
 
810
    <i>whatever</i>       FILTER foo:bar
 
811
</pre>
 
812
</blockquote>
 
813
 
 
814
<p> To turn on content filtering with a header_checks(5) or
 
815
body_checks(5) table pattern: </p>
 
816
 
 
817
<blockquote>
 
818
<pre>
 
819
/etc/postfix/header_checks:
 
820
    /<i>whatever</i>/     FILTER foo:bar
 
821
</pre>
 
822
</blockquote>
 
823
 
 
824
<p> You can do this in smtpd access maps as well as the cleanup
 
825
server's header/body_checks.  This feature must be used with great
 
826
care:  you must disable all the UCE features in the after-filter
 
827
smtpd and cleanup daemons or else you will have a content filtering
 
828
loop. </p>
 
829
 
 
830
<p> Limitations: </p>
 
831
 
 
832
<ul>
 
833
 
 
834
<li> <p> FILTER actions from smtpd access maps and header/body_checks
 
835
take precedence over filters specified with the main.cf content_filter
 
836
parameter. </p>
 
837
 
 
838
<li> <p> If a message triggers more than one filter action, only
 
839
the last one takes effect. </p>
 
840
 
 
841
<li> <p> The same content filter is applied to all the recipients
 
842
of a given message. </p>
 
843
 
 
844
</ul>
 
845
 
 
846
</body>
 
847
 
 
848
</html>