summaryrefslogtreecommitdiffstats
path: root/html/BACKSCATTER_README.html
blob: f4e26edde7c5be322776ddb769b240a69369cd0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<title>Postfix Backscatter Howto</title>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

</head>

<body>

<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix
Backscatter Howto</h1>

<hr>

<h2>Overview </h2>

<p> This document describes features that require Postfix version
2.0 or later. </p>

<p> Topics covered in this document: </p>

<ul>

<li><a href="#wtf">What is backscatter mail?</a>

<li><a href="#random">How do I block backscatter mail to random
recipient addresses?</a>

<li><a href="#real">How do I block backscatter mail to real
recipient addresses?</a>

<ul>

<li><a href="#forged_helo">Blocking backscatter mail with forged
mail server information</a>

<li><a href="#forged_sender">Blocking backscatter mail with forged
sender information</a>

<li><a href="#forged_other">Blocking backscatter mail with other
forged information</a>

<li><a href="#scanner">Blocking backscatter mail from virus
scanners</a>

</ul>

</ul>

<p> The examples use Perl Compatible Regular Expressions (Postfix
<a href="pcre_table.5.html">pcre</a>: tables), but also provide a translation to POSIX regular
expressions (Postfix <a href="regexp_table.5.html">regexp</a>: tables). PCRE is preferred primarily
because the implementation is often faster.</p>

<h2><a name="wtf">What is backscatter mail?</a></h2>

<p> When a spammer or worm sends mail with forged sender addresses,
innocent sites are flooded with undeliverable mail notifications.
This is called backscatter mail.  With Postfix, you know that you're
a backscatter victim when your logfile goes on and on like this:
</p>

<blockquote>
<pre>
Dec  4 04:30:09 hostname postfix/smtpd[58549]: NOQUEUE: reject:
RCPT from xxxxxxx[x.x.x.x]: 550 5.1.1 &lt;yyyyyy@your.domain.here&gt;:
Recipient address rejected: User unknown; from=&lt;&gt;
to=&lt;yyyyyy@your.domain.here&gt; proto=ESMTP helo=&lt;zzzzzz&gt;
</pre>
</blockquote>

<p> What you see are lots of "user unknown" errors with "from=&lt;&gt;".
These are error reports from MAILER-DAEMONs elsewhere on the Internet,
about email that was sent with a false sender address in your domain.
</p>

<h2><a name="random">How do I block backscatter mail to random
recipient addresses?</a></h2>

<p> If your machine receives backscatter mail to random addresses,
configure Postfix to reject all mail for non-existent recipients
as described in the <a href="LOCAL_RECIPIENT_README.html">LOCAL_RECIPIENT_README</a> and
<a href="STANDARD_CONFIGURATION_README.html">STANDARD_CONFIGURATION_README</a> documentation.  </p>

<p> If your machine runs Postfix 2.0 and earlier, disable the "pause
before reject" feature in the SMTP server. If your system is under
stress then it should not waste time. </p>

<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
    # Not needed with Postfix 2.1 and later.
    <a href="postconf.5.html#smtpd_error_sleep_time">smtpd_error_sleep_time</a> = 0

    # Not needed with Postfix 2.4 and later.
    <a href="postconf.5.html#unknown_local_recipient_reject_code">unknown_local_recipient_reject_code</a> = 550
</pre>
</blockquote>

<h2><a name="real">How do I block backscatter mail to real
recipient addresses?</a></h2>

<p> When backscatter mail passes the "unknown recipient" barrier,
there still is no need to despair.  Many mail systems are kind
enough to attach the message headers of the undeliverable mail in
the non-delivery notification. These message headers contain
information that you can use to recognize and block forged mail.
</p>

<h3><a name="forged_helo">Blocking backscatter mail with forged
mail server information</a></h3>

<p> Although my email address is "wietse@porcupine.org", all my
mail systems announce themselves with the SMTP HELO command as
"hostname.porcupine.org".  Thus, if returned mail has a Received:
message header like this: </p>

<blockquote>
<pre>
Received: from porcupine.org ...
</pre>
</blockquote>

<p> Then I know that this is almost certainly forged mail (almost;
see <a href="#caveats">next section</a> for the fly in the ointment).
Mail that is really
sent by my systems looks like this: </p>

<blockquote>
<pre>
Received: from hostname.porcupine.org ...
</pre>
</blockquote>

<p> For the same reason the following message headers are very likely
to be the result of forgery:</p>

<blockquote>
<pre>
Received: from host.example.com ([1.2.3.4] helo=porcupine.org) ...
Received: from [1.2.3.4] (port=12345 helo=porcupine.org) ...
Received: from host.example.com (HELO porcupine.org) ...
Received: from host.example.com (EHLO porcupine.org) ...
</pre>
</blockquote>

<p> Some forgeries show up in the way that a mail server reports
itself in Received: message headers. Keeping in mind that all my
systems have a mail server name of <i>hostname</i>.porcupine.org,
the following is definitely a forgery:</p>

<blockquote>
<pre>
Received: by porcupine.org ...
Received: from host.example.com ( ... ) by porcupine.org ...
</pre>
</blockquote>

<p> Another frequent sign of forgery is the Message-ID: header. My
systems produce a Message-ID: of
&lt;<i>stuff</i>@<i>hostname</i>.porcupine.org&gt;.  The following
are forgeries, especially the first one:

<blockquote>
<pre>
Message-ID: &lt;1cb479435d8eb9.2beb1.qmail@porcupine.org&gt;
Message-ID: &lt;yulszqocfzsficvzzju@porcupine.org&gt;
</pre>
</blockquote>

<p> To block such backscatter I use <a href="postconf.5.html#header_checks">header_checks</a> and <a href="postconf.5.html#body_checks">body_checks</a>
patterns like this: </p>

<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
    <a href="postconf.5.html#header_checks">header_checks</a> = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/header_checks
    <a href="postconf.5.html#body_checks">body_checks</a> = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/body_checks

/etc/postfix/header_checks:
    # Do not indent the patterns between "if" and "endif".
    if /^Received:/
    /^Received: +from +(porcupine\.org) +/
        reject forged client name in Received: header: $1
    /^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
        reject forged client name in Received: header: $2
    /^Received:.* +by +(porcupine\.org)\b/
        reject forged mail server name in Received: header: $1
    endif
    /^Message-ID:.* &lt;!&amp;!/ DUNNO
    /^Message-ID:.*@(porcupine\.org)/
        reject forged domain name in Message-ID: header: $1

/etc/postfix/body_checks:
    # Do not indent the patterns between "if" and "endif".
    if /^[&gt; ]*Received:/
    /^[&gt; ]*Received: +from +(porcupine\.org) /
        reject forged client name in Received: header: $1
    /^[&gt; ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
        reject forged client name in Received: header: $2
    /^[&gt; ]*Received:.* +by +(porcupine\.org)\b/
        reject forged mail server name in Received: header: $1
    endif
    /^[&gt; ]*Message-ID:.* &lt;!&amp;!/ DUNNO
    /^[&gt; ]*Message-ID:.*@(porcupine\.org)/
        reject forged domain name in Message-ID: header: $1
</pre>
</blockquote>

<p> Notes: </p>

<ul>

<li> <p> The example uses <a href="pcre_table.5.html">pcre</a>: tables mainly for speed; with minor
modifications, you can use <a href="regexp_table.5.html">regexp</a>: tables as explained below. </p>

<li> <p> The example is simplified for educational purposes.  In
reality my patterns list multiple domain names, as
"<tt>(domain|domain|...)</tt>".  </p>

<li> <p> The "<tt>\.</tt>" matches "<tt>.</tt>" literally. Without
the "<tt>\</tt>", the "<tt>.</tt>" would match any character. </p>

<li> <p> The "<tt>\(</tt>" and "<tt>\)</tt>" match "<tt>(</tt>"
and "<tt>)</tt>" literally. Without the "<tt>\</tt>", the "<tt>(</tt>"
and "<tt>)</tt>" would be grouping operators.  </p>

<li> <p> The "<tt>\b</tt>" is used here to match the end of a word.
If you use <a href="regexp_table.5.html">regexp</a>: tables, specify "<tt>[[:&gt;:]]</tt>" (on some
systems you should specify "<tt>\&gt;</tt>" instead; for details
see your system documentation).

<li> <p> The "if /pattern/" and "endif" eliminate unnecessary
matching attempts. DO NOT indent lines starting with /pattern/
between the "if" and "endif"! </p>

<li> <p> The two "<tt>Message-ID:.* &lt;!&amp;!</tt>" rules are
workarounds for some versions of Outlook express, as described in
the <a href="#caveats"> caveats </a> section below.

</ul>

<p><a name="caveats"><strong>Caveats</strong></a></p>

<ul>

<li>

<p> Netscape Messenger (and reportedly, Mozilla) sends a HELO name
that is identical to the sender address domain part. If you have
such clients then the above patterns would block legitimate email.
</p>

<p> My network has only one such machine, and to prevent its mail
from being blocked I have configured it to send mail as
user@hostname.porcupine.org. On the Postfix server, a canonical
mapping translates this temporary address into user@porcupine.org.
</p>

<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
    <a href="postconf.5.html#canonical_maps">canonical_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/canonical

/etc/postfix/canonical:
    @hostname.porcupine.org @porcupine.org
</pre>
</blockquote>

<p> This is of course practical only when you have very few systems
that send HELO commands like this, and when you never have to send
mail to a user on such a host. </p>

<p> An alternative would be to remove the hostname from
"hostname.porcupine.org" with address
masquerading, as described in the <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a> document.
</p>

<li> <p> Reportedly, Outlook 2003 (perhaps Outlook Express, and
other versions as well) present substantially different Message-ID
headers depending upon whether or not a DSN is requested (via Options
"Request a delivery receipt for this message"). </p>

<p> When a DSN is requested, Outlook 2003 uses a Message-ID string
that ends in the sender's domain name: </p>

<blockquote>
<pre>
Message-ID: &lt;!&amp;! ...very long string... ==@example.com&gt;
</pre>
</blockquote>

<p> where <i>example.com</i> is the domain name part of the email
address specified in Outlook's account settings for the user.  Since
many users configure their email addresses as <i>username@example.com</i>,
messages with DSN turned on will trigger the REJECT action in the
previous section. </p>

<p> If you have such clients then you can exclude their Message-ID
strings with the two "<tt>Message-ID:.* &lt;!&amp;!</tt>" patterns
that are shown in the previous section.  Otherwise you will not be
able to use the two backscatter rules to stop forged Message ID
strings.  Of course this workaround may break the next time Outlook
is changed.  </p>

</ul>

<h3><a name="forged_sender">Blocking backscatter mail with forged
sender information</a></h3>

Like many people I still have a few email addresses in domains that
I used in the past. Mail for those addresses is forwarded to my
current address.  Most of the backscatter mail that I get claims
to be sent from these addresses.  Such mail is obviously forged
and is very easy to stop.

<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
    <a href="postconf.5.html#header_checks">header_checks</a> = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/header_checks
    <a href="postconf.5.html#body_checks">body_checks</a> = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/body_checks

/etc/postfix/header_checks:
    /^(From|Return-Path):.*\b(user@domain\.tld)\b/ 
        reject forged sender address in $1: header: $2

/etc/postfix/body_checks:
    /^[&gt; ]*(From|Return-Path):.*\b(user@domain\.tld)\b/ 
        reject forged sender address in $1: header: $2
</pre>
</blockquote>

<p> Notes: </p>

<ul>

<li> <p> The example uses <a href="pcre_table.5.html">pcre</a>: tables mainly for speed; with minor
modifications, you can use <a href="regexp_table.5.html">regexp</a>: tables as explained below. </p>

<li> <p> The example is simplified for educational purposes.  In
reality, my patterns list multiple email addresses as
"<tt>(user1@domain1\.tld|user2@domain2\.tld)</tt>".  </p>

<li> <p> The two "<tt>\b</tt>" as used in "<tt>\b(user@domain\.tld)\b</tt>"
match the beginning and end of a word, respectively.  If you use
<a href="regexp_table.5.html">regexp</a>: tables, specify "<tt>[[:&lt;:]]</tt> and <tt>[[:&gt;:]]</tt>"
(on some systems you should specify "<tt>\&lt;</tt> and <tt>\&gt;</tt>"
instead; for details see your system documentation).  </p>

<li> <p> The "<tt>\.</tt>" matches "<tt>.</tt>" literally. Without
the "<tt>\</tt>", the "<tt>.</tt>" would match any character. </p>

</ul>

<h3><a name="forged_other">Blocking backscatter mail with other
forged information</a></h3>

<p> Another sign of forgery can be found in the IP address that is
recorded in Received: headers next to your HELO host or domain name.
This information must be used with care, though. Some mail servers
are behind a network address translator and never see the true
client IP address.  </p>

<h3><a name="scanner">Blocking backscatter mail from virus
scanners</a></h3>

<p> With all the easily recognizable forgeries eliminated, there
is one category of backscatter mail that remains, and that is
notifications from virus scanner software. Unfortunately, some
virus scanning software doesn't know that viruses forge sender
addresses. To make matters worse, the software also doesn't know
how to report a mail delivery problem, so that we cannot use the
above techniques to recognize forgeries.  </p>

<p> Recognizing virus scanner mail is an error prone process,
because there is a lot of variation in report formats.  The following
is only a small example of message header patterns.  For a large
collection of header and body patterns that recognize virus
notification email, see
<a href="https://web.archive.org/web/20100317123907/http://std.dkuug.dk/keld/virus/">https://web.archive.org/web/20100317123907/http://std.dkuug.dk/keld/virus/</a>
or <a href="http://www.t29.dk/antiantivirus.txt">http://www.t29.dk/antiantivirus.txt</a>.  </p>

<blockquote>
<pre>
/etc/postfix/header_checks:
    /^Subject: *Your email contains VIRUSES/ DISCARD virus notification
    /^Content-Disposition:.*VIRUS1_DETECTED_AND_REMOVED/
        DISCARD virus notification
    /^Content-Disposition:.*VirusWarning.txt/ DISCARD virus notification
</pre>
</blockquote>

<p> Note: these documents haven't been updated since 2004, so they
are useful only as a starting point. </p>

<p> A plea to virus or spam scanner operators: please do not make
the problem worse by sending return mail to forged sender addresses.
You're only harassing innocent people. If you must return mail to
the purported sender, please return the full message headers, so
that the sender can filter out the obvious forgeries. </p>

</body>

</html>