xref: /netbsd-src/external/ibm-public/postfix/dist/proto/BACKSCATTER_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 Backscatter Howto</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="">Postfix
18Backscatter Howto</h1>
19
20<hr>
21
22<h2>Overview </h2>
23
24<p> This document describes features that require Postfix version
252.0 or later. </p>
26
27<p> Topics covered in this document: </p>
28
29<ul>
30
31<li><a href="#wtf">What is backscatter mail?</a>
32
33<li><a href="#random">How do I block backscatter mail to random
34recipient addresses?</a>
35
36<li><a href="#real">How do I block backscatter mail to real
37recipient addresses?</a>
38
39<ul>
40
41<li><a href="#forged_helo">Blocking backscatter mail with forged
42mail server information</a>
43
44<li><a href="#forged_sender">Blocking backscatter mail with forged
45sender information</a>
46
47<li><a href="#forged_other">Blocking backscatter mail with other
48forged information</a>
49
50<li><a href="#scanner">Blocking backscatter mail from virus
51scanners</a>
52
53</ul>
54
55</ul>
56
57<p> The examples use Perl Compatible Regular Expressions (Postfix
58pcre: tables), but also provide a translation to POSIX regular
59expressions (Postfix regexp: tables). PCRE is preferred primarily
60because the implementation is often faster.</p>
61
62<h2><a name="wtf">What is backscatter mail?</a></h2>
63
64<p> When a spammer or worm sends mail with forged sender addresses,
65innocent sites are flooded with undeliverable mail notifications.
66This is called backscatter mail.  With Postfix, you know that you're
67a backscatter victim when your logfile goes on and on like this:
68</p>
69
70<blockquote>
71<pre>
72Dec  4 04:30:09 hostname postfix/smtpd[58549]: NOQUEUE: reject:
73RCPT from xxxxxxx[x.x.x.x]: 550 5.1.1 &lt;yyyyyy@your.domain.here&gt;:
74Recipient address rejected: User unknown; from=&lt;&gt;
75to=&lt;yyyyyy@your.domain.here&gt; proto=ESMTP helo=&lt;zzzzzz&gt;
76</pre>
77</blockquote>
78
79<p> What you see are lots of "user unknown" errors with "from=&lt;&gt;".
80These are error reports from MAILER-DAEMONs elsewhere on the Internet,
81about email that was sent with a false sender address in your domain.
82</p>
83
84<h2><a name="random">How do I block backscatter mail to random
85recipient addresses?</a></h2>
86
87<p> If your machine receives backscatter mail to random addresses,
88configure Postfix to reject all mail for non-existent recipients
89as described in the LOCAL_RECIPIENT_README and
90STANDARD_CONFIGURATION_README documentation.  </p>
91
92<p> If your machine runs Postfix 2.0 and earlier, disable the "pause
93before reject" feature in the SMTP server. If your system is under
94stress then it should not waste time. </p>
95
96<blockquote>
97<pre>
98/etc/postfix/main.cf:
99    # Not needed with Postfix 2.1 and later.
100    smtpd_error_sleep_time = 0
101
102    # Not needed with Postfix 2.4 and later.
103    unknown_local_recipient_reject_code = 550
104</pre>
105</blockquote>
106
107<h2><a name="real">How do I block backscatter mail to real
108recipient addresses?</a></h2>
109
110<p> When backscatter mail passes the "unknown recipient" barrier,
111there still is no need to despair.  Many mail systems are kind
112enough to attach the message headers of the undeliverable mail in
113the non-delivery notification. These message headers contain
114information that you can use to recognize and block forged mail.
115</p>
116
117<h3><a name="forged_helo">Blocking backscatter mail with forged
118mail server information</a></h3>
119
120<p> Although my email address is "wietse@porcupine.org", all my
121mail systems announce themselves with the SMTP HELO command as
122"hostname.porcupine.org".  Thus, if returned mail has a Received:
123message header like this: </p>
124
125<blockquote>
126<pre>
127Received: from porcupine.org ...
128</pre>
129</blockquote>
130
131<p> Then I know that this is almost certainly forged mail (almost;
132see <a href="#caveats">next section</a> for the fly in the ointment).
133Mail that is really
134sent by my systems looks like this: </p>
135
136<blockquote>
137<pre>
138Received: from hostname.porcupine.org ...
139</pre>
140</blockquote>
141
142<p> For the same reason the following message headers are very likely
143to be the result of forgery:</p>
144
145<blockquote>
146<pre>
147Received: from host.example.com ([1.2.3.4] helo=porcupine.org) ...
148Received: from [1.2.3.4] (port=12345 helo=porcupine.org) ...
149Received: from host.example.com (HELO porcupine.org) ...
150Received: from host.example.com (EHLO porcupine.org) ...
151</pre>
152</blockquote>
153
154<p> Some forgeries show up in the way that a mail server reports
155itself in Received: message headers. Keeping in mind that all my
156systems have a mail server name of <i>hostname</i>.porcupine.org,
157the following is definitely a forgery:</p>
158
159<blockquote>
160<pre>
161Received: by porcupine.org ...
162Received: from host.example.com ( ... ) by porcupine.org ...
163</pre>
164</blockquote>
165
166<p> Another frequent sign of forgery is the Message-ID: header. My
167systems produce a Message-ID: of
168&lt;<i>stuff</i>@<i>hostname</i>.porcupine.org&gt;.  The following
169are forgeries, especially the first one:
170
171<blockquote>
172<pre>
173Message-ID: &lt;1cb479435d8eb9.2beb1.qmail@porcupine.org&gt;
174Message-ID: &lt;yulszqocfzsficvzzju@porcupine.org&gt;
175</pre>
176</blockquote>
177
178<p> To block such backscatter I use header_checks and body_checks
179patterns like this: </p>
180
181<blockquote>
182<pre>
183/etc/postfix/main.cf:
184    header_checks = pcre:/etc/postfix/header_checks
185    body_checks = pcre:/etc/postfix/body_checks
186
187/etc/postfix/header_checks:
188    # Do not indent the patterns between "if" and "endif".
189    if /^Received:/
190    /^Received: +from +(porcupine\.org) +/
191        reject forged client name in Received: header: $1
192    /^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
193        reject forged client name in Received: header: $2
194    /^Received:.* +by +(porcupine\.org)\b/
195        reject forged mail server name in Received: header: $1
196    endif
197    /^Message-ID:.* &lt;!&amp;!/ DUNNO
198    /^Message-ID:.*@(porcupine\.org)/
199	reject forged domain name in Message-ID: header: $1
200
201/etc/postfix/body_checks:
202    # Do not indent the patterns between "if" and "endif".
203    if /^[&gt; ]*Received:/
204    /^[&gt; ]*Received: +from +(porcupine\.org) /
205        reject forged client name in Received: header: $1
206    /^[&gt; ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
207        reject forged client name in Received: header: $2
208    /^[&gt; ]*Received:.* +by +(porcupine\.org)\b/
209        reject forged mail server name in Received: header: $1
210    endif
211    /^[&gt; ]*Message-ID:.* &lt;!&amp;!/ DUNNO
212    /^[&gt; ]*Message-ID:.*@(porcupine\.org)/
213	reject forged domain name in Message-ID: header: $1
214</pre>
215</blockquote>
216
217<p> Notes: </p>
218
219<ul>
220
221<li> <p> The example uses pcre: tables mainly for speed; with minor
222modifications, you can use regexp: tables as explained below. </p>
223
224<li> <p> The example is simplified for educational purposes.  In
225reality my patterns list multiple domain names, as
226"<tt>(domain|domain|...)</tt>".  </p>
227
228<li> <p> The "<tt>\.</tt>" matches "<tt>.</tt>" literally. Without
229the "<tt>\</tt>", the "<tt>.</tt>" would match any character. </p>
230
231<li> <p> The "<tt>\(</tt>" and "<tt>\)</tt>" match "<tt>(</tt>"
232and "<tt>)</tt>" literally. Without the "<tt>\</tt>", the "<tt>(</tt>"
233and "<tt>)</tt>" would be grouping operators.  </p>
234
235<li> <p> The "<tt>\b</tt>" is used here to match the end of a word.
236If you use regexp: tables, specify "<tt>[[:&gt;:]]</tt>" (on some
237systems you should specify "<tt>\&gt;</tt>" instead; for details
238see your system documentation).
239
240<li> <p> The "if /pattern/" and "endif" eliminate unnecessary
241matching attempts. DO NOT indent lines starting with /pattern/
242between the "if" and "endif"! </p>
243
244<li> <p> The two "<tt>Message-ID:.* &lt;!&amp;!</tt>" rules are
245workarounds for some versions of Outlook express, as described in
246the <a href="#caveats"> caveats </a> section below.
247
248</ul>
249
250<p><a name="caveats"><strong>Caveats</strong></a></p>
251
252<ul>
253
254<li>
255
256<p> Netscape Messenger (and reportedly, Mozilla) sends a HELO name
257that is identical to the sender address domain part. If you have
258such clients then the above patterns would block legitimate email.
259</p>
260
261<p> My network has only one such machine, and to prevent its mail
262from being blocked I have configured it to send mail as
263user@hostname.porcupine.org. On the Postfix server, a canonical
264mapping translates this temporary address into user@porcupine.org.
265</p>
266
267<blockquote>
268<pre>
269/etc/postfix/main.cf:
270    canonical_maps = hash:/etc/postfix/canonical
271
272/etc/postfix/canonical:
273    @hostname.porcupine.org @porcupine.org
274</pre>
275</blockquote>
276
277<p> This is of course practical only when you have very few systems
278that send HELO commands like this, and when you never have to send
279mail to a user on such a host. </p>
280
281<p> An alternative would be to remove the hostname from
282"hostname.porcupine.org" with address
283masquerading, as described in the ADDRESS_REWRITING_README document.
284</p>
285
286<li> <p> Reportedly, Outlook 2003 (perhaps Outlook Express, and
287other versions as well) present substantially different Message-ID
288headers depending upon whether or not a DSN is requested (via Options
289"Request a delivery receipt for this message"). </p>
290
291<p> When a DSN is requested, Outlook 2003 uses a Message-ID string
292that ends in the sender's domain name: </p>
293
294<blockquote>
295<pre>
296Message-ID: &lt;!&amp;! ...very long string... ==@example.com&gt;
297</pre>
298</blockquote>
299
300<p> where <i>example.com</i> is the domain name part of the email
301address specified in Outlook's account settings for the user.  Since
302many users configure their email addresses as <i>username@example.com</i>,
303messages with DSN turned on will trigger the REJECT action in the
304previous section. </p>
305
306<p> If you have such clients then you can exclude their Message-ID
307strings with the two "<tt>Message-ID:.* &lt;!&amp;!</tt>" patterns
308that are shown in the previous section.  Otherwise you will not be
309able to use the two backscatter rules to stop forged Message ID
310strings.  Of course this workaround may break the next time Outlook
311is changed.  </p>
312
313</ul>
314
315<h3><a name="forged_sender">Blocking backscatter mail with forged
316sender information</a></h3>
317
318Like many people I still have a few email addresses in domains that
319I used in the past. Mail for those addresses is forwarded to my
320current address.  Most of the backscatter mail that I get claims
321to be sent from these addresses.  Such mail is obviously forged
322and is very easy to stop.
323
324<blockquote>
325<pre>
326/etc/postfix/main.cf:
327    header_checks = pcre:/etc/postfix/header_checks
328    body_checks = pcre:/etc/postfix/body_checks
329
330/etc/postfix/header_checks:
331    /^(From|Return-Path):.*\b(user@domain\.tld)\b/
332        reject forged sender address in $1: header: $2
333
334/etc/postfix/body_checks:
335    /^[&gt; ]*(From|Return-Path):.*\b(user@domain\.tld)\b/
336        reject forged sender address in $1: header: $2
337</pre>
338</blockquote>
339
340<p> Notes: </p>
341
342<ul>
343
344<li> <p> The example uses pcre: tables mainly for speed; with minor
345modifications, you can use regexp: tables as explained below. </p>
346
347<li> <p> The example is simplified for educational purposes.  In
348reality, my patterns list multiple email addresses as
349"<tt>(user1@domain1\.tld|user2@domain2\.tld)</tt>".  </p>
350
351<li> <p> The two "<tt>\b</tt>" as used in "<tt>\b(user@domain\.tld)\b</tt>"
352match the beginning and end of a word, respectively.  If you use
353regexp: tables, specify "<tt>[[:&lt;:]]</tt> and <tt>[[:&gt;:]]</tt>"
354(on some systems you should specify "<tt>\&lt;</tt> and <tt>\&gt;</tt>"
355instead; for details see your system documentation).  </p>
356
357<li> <p> The "<tt>\.</tt>" matches "<tt>.</tt>" literally. Without
358the "<tt>\</tt>", the "<tt>.</tt>" would match any character. </p>
359
360</ul>
361
362<h3><a name="forged_other">Blocking backscatter mail with other
363forged information</a></h3>
364
365<p> Another sign of forgery can be found in the IP address that is
366recorded in Received: headers next to your HELO host or domain name.
367This information must be used with care, though. Some mail servers
368are behind a network address translator and never see the true
369client IP address.  </p>
370
371<h3><a name="scanner">Blocking backscatter mail from virus
372scanners</a></h3>
373
374<p> With all the easily recognizable forgeries eliminated, there
375is one category of backscatter mail that remains, and that is
376notifications from virus scanner software. Unfortunately, some
377virus scanning software doesn't know that viruses forge sender
378addresses. To make matters worse, the software also doesn't know
379how to report a mail delivery problem, so that we cannot use the
380above techniques to recognize forgeries.  </p>
381
382<p> Recognizing virus scanner mail is an error prone process,
383because there is a lot of variation in report formats.  The following
384is only a small example of message header patterns.  For a large
385collection of header and body patterns that recognize virus
386notification email, see
387https://web.archive.org/web/20100317123907/http://std.dkuug.dk/keld/virus/
388or http://www.t29.dk/antiantivirus.txt.  </p>
389
390<blockquote>
391<pre>
392/etc/postfix/header_checks:
393    /^Subject: *Your email contains VIRUSES/ DISCARD virus notification
394    /^Content-Disposition:.*VIRUS1_DETECTED_AND_REMOVED/
395        DISCARD virus notification
396    /^Content-Disposition:.*VirusWarning.txt/ DISCARD virus notification
397</pre>
398</blockquote>
399
400<p> Note: these documents haven't been updated since 2004, so they
401are useful only as a starting point. </p>
402
403<p> A plea to virus or spam scanner operators: please do not make
404the problem worse by sending return mail to forged sender addresses.
405You're only harassing innocent people. If you must return mail to
406the purported sender, please return the full message headers, so
407that the sender can filter out the obvious forgeries. </p>
408
409</body>
410
411</html>
412