1 <!doctype html public
"-//W3C//DTD HTML 4.01 Transitional//EN"
2 "http://www.w3.org/TR/html4/loose.dtd">
8 <title>Postfix Backscatter Howto
</title>
10 <meta http-equiv=
"Content-Type" content=
"text/html; charset=us-ascii">
16 <h1><img src=
"postfix-logo.jpg" width=
"203" height=
"98" ALT=
"">Postfix
17 Backscatter Howto
</h1>
23 <p> This document describes features that require Postfix version
26 <p> Topics covered in this document:
</p>
30 <li><a href=
"#wtf">What is backscatter mail?
</a>
32 <li><a href=
"#random">How do I block backscatter mail to random
33 recipient addresses?
</a>
35 <li><a href=
"#real">How do I block backscatter mail to real
36 recipient addresses?
</a>
40 <li><a href=
"#forged_helo">Blocking backscatter mail with forged
41 mail server information
</a>
43 <li><a href=
"#forged_sender">Blocking backscatter mail with forged
44 sender information
</a>
46 <li><a href=
"#forged_other">Blocking backscatter mail with other
47 forged information
</a>
49 <li><a href=
"#scanner">Blocking backscatter mail from virus
56 <p> The examples use Perl Compatible Regular Expressions (Postfix
57 <a href=
"pcre_table.5.html">pcre
</a>: tables), but also provide a translation to POSIX regular
58 expressions (Postfix
<a href=
"regexp_table.5.html">regexp
</a>: tables). PCRE is preferred primarily
59 because the implementation is often faster.
</p>
61 <h2><a name=
"wtf">What is backscatter mail?
</a></h2>
63 <p> When a spammer or worm sends mail with forged sender addresses,
64 innocent sites are flooded with undeliverable mail notifications.
65 This is called backscatter mail. With Postfix, you know that you're
66 a backscatter victim when your logfile goes on and on like this:
71 Dec
4 04:
30:
09 hostname postfix/smtpd[
58549]: NOQUEUE: reject:
72 RCPT from xxxxxxx[x.x.x.x]:
550 5.1.1 <yyyyyy@your.domain.here
>:
73 Recipient address rejected: User unknown; from=
<>
74 to=
<yyyyyy@your.domain.here
> proto=ESMTP helo=
<zzzzzz
>
78 <p> What you see are lots of
"user unknown" errors with
"from=<>".
79 These are error reports from MAILER-DAEMONs elsewhere on the Internet.
82 <h2><a name=
"random">How do I block backscatter mail to random
83 recipient addresses?
</a></h2>
85 <p> If your machine receives backscatter mail to random addresses,
86 configure Postfix to reject all mail for non-existent recipients
87 as described in the
<a href=
"LOCAL_RECIPIENT_README.html">LOCAL_RECIPIENT_README
</a> and
88 <a href=
"STANDARD_CONFIGURATION_README.html">STANDARD_CONFIGURATION_README
</a> documentation.
</p>
90 <p> If your machine runs Postfix
2.0 and earlier, disable the
"pause
91 before reject" feature in the SMTP server. If your system is under
92 stress then it should not waste time.
</p>
96 /etc/postfix/
<a href=
"postconf.5.html">main.cf
</a>:
97 # Not needed with Postfix
2.1 and later.
98 <a href=
"postconf.5.html#smtpd_error_sleep_time">smtpd_error_sleep_time
</a> =
0
100 # Not needed with Postfix
2.4 and later.
101 <a href=
"postconf.5.html#unknown_local_recipient_reject_code">unknown_local_recipient_reject_code
</a> =
550
105 <h2><a name=
"real">How do I block backscatter mail to real
106 recipient addresses?
</a></h2>
108 <p> When backscatter mail passes the
"unknown recipient" barrier,
109 there still is no need to despair. Many mail systems are kind
110 enough to attach the message headers of the undeliverable mail in
111 the non-delivery notification. These message headers contain
112 information that you can use to recognize and block forged mail.
115 <h3><a name=
"forged_helo">Blocking backscatter mail with forged
116 mail server information
</a></h3>
118 <p> Although my email address is
"wietse@porcupine.org", all my
119 mail systems announce themselves with the SMTP HELO command as
120 "hostname.porcupine.org". Thus, if returned mail has a Received:
121 message header like this:
</p>
125 Received: from porcupine.org ...
129 <p> Then I know that this is almost certainly forged mail (almost;
130 see
<a href=
"#caveats">next section
</a> for the fly in the ointment).
132 sent by my systems looks like this:
</p>
136 Received: from hostname.porcupine.org ...
140 <p> For the same reason the following message headers are very likely
141 to be the result of forgery:
</p>
145 Received: from host.example.com ([
1.2.3.4] helo=porcupine.org) ...
146 Received: from [
1.2.3.4] (port=
12345 helo=porcupine.org) ...
147 Received: from host.example.com (HELO porcupine.org) ...
148 Received: from host.example.com (EHLO porcupine.org) ...
152 <p> Some forgeries show up in the way that a mail server reports
153 itself in Received: message headers. Keeping in mind that all my
154 systems have a mail server name of
<i>hostname
</i>.porcupine.org,
155 the following is definitely a forgery:
</p>
159 Received: by porcupine.org ...
160 Received: from host.example.com ( ... ) by porcupine.org ...
164 <p> Another frequent sign of forgery is the Message-ID: header. My
165 systems produce a Message-ID: of
166 <<i>stuff
</i>@
<i>hostname
</i>.porcupine.org
>. The following
167 are forgeries, especially the first one:
171 Message-ID:
<1cb479435d8eb9.2beb1.qmail@porcupine.org
>
172 Message-ID:
<yulszqocfzsficvzzju@porcupine.org
>
176 <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>
177 patterns like this:
</p>
181 /etc/postfix/
<a href=
"postconf.5.html">main.cf
</a>:
182 <a href=
"postconf.5.html#header_checks">header_checks
</a> =
<a href=
"pcre_table.5.html">pcre
</a>:/etc/postfix/header_checks
183 <a href=
"postconf.5.html#body_checks">body_checks
</a> =
<a href=
"pcre_table.5.html">pcre
</a>:/etc/postfix/body_checks
185 /etc/postfix/header_checks:
187 /^Received: +from +(porcupine\.org) +/
188 reject forged client name in Received: header: $
1
189 /^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
190 reject forged client name in Received: header: $
2
191 /^Received:.* +by +(porcupine\.org)\b/
192 reject forged mail server name in Received: header: $
1
194 /^Message-ID:.*
<!
&!/ DUNNO
195 /^Message-ID:.*@(porcupine\.org)/
196 reject forged domain name in Message-ID: header: $
1
198 /etc/postfix/body_checks:
199 if /^[
> ]*Received:/
200 /^[
> ]*Received: +from +(porcupine\.org) /
201 reject forged client name in Received: header: $
1
202 /^[
> ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
203 reject forged client name in Received: header: $
2
204 /^[
> ]*Received:.* +by +(porcupine\.org)\b/
205 reject forged mail server name in Received: header: $
1
207 /^[
> ]*Message-ID:.*
<!
&!/ DUNNO
208 /^[
> ]*Message-ID:.*@(porcupine\.org)/
209 reject forged domain name in Message-ID: header: $
1
217 <li> <p> The example uses
<a href=
"pcre_table.5.html">pcre
</a>: tables mainly for speed; with minor
218 modifications, you can use
<a href=
"regexp_table.5.html">regexp
</a>: tables as explained below.
</p>
220 <li> <p> The example is simplified for educational purposes. In
221 reality my patterns list multiple domain names, as
222 "<tt>(domain|domain|...)</tt>".
</p>
224 <li> <p> The
"<tt>\.</tt>" matches
"<tt>.</tt>" literally. Without
225 the
"<tt>\</tt>", the
"<tt>.</tt>" would match any character.
</p>
227 <li> <p> The
"<tt>\(</tt>" and
"<tt>\)</tt>" match
"<tt>(</tt>"
228 and
"<tt>)</tt>" literally. Without the
"<tt>\</tt>", the
"<tt>(</tt>"
229 and
"<tt>)</tt>" would be grouping operators.
</p>
231 <li> <p> The
"<tt>\b</tt>" is used here to match the end of a word.
232 If you use
<a href=
"regexp_table.5.html">regexp
</a>: tables, specify
"<tt>[[:>:]]</tt>" (on some
233 systems you should specify
"<tt>\></tt>" instead; for details
234 see your system documentation).
236 <li> <p> The
"if /pattern/" and
"endif" eliminate unnecessary
237 matching attempts. DO NOT indent lines starting with /pattern/
238 between the
"if" and
"endif"!
</p>
240 <li> <p> The two
"<tt>Message-ID:.* <!&!</tt>" rules are
241 workarounds for some versions of Outlook express, as described in
242 the
<a href=
"#caveats"> caveats
</a> section below.
246 <p><a name=
"caveats"><strong>Caveats
</strong></a></p>
252 <p> Netscape Messenger (and reportedly, Mozilla) sends a HELO name
253 that is identical to the sender address domain part. If you have
254 such clients then the above patterns would block legitimate email.
257 <p> My network has only one such machine, and to prevent its mail
258 from being blocked I have configured it to send mail as
259 user@hostname.porcupine.org. On the Postfix server, a canonical
260 mapping translates this temporary address into user@porcupine.org.
265 /etc/postfix/
<a href=
"postconf.5.html">main.cf
</a>:
266 <a href=
"postconf.5.html#canonical_maps">canonical_maps
</a> = hash:/etc/postfix/canonical
268 /etc/postfix/canonical:
269 @hostname.porcupine.org @porcupine.org
273 <p> This is of course practical only when you have very few systems
274 that send HELO commands like this, and when you never have to send
275 mail to a user on such a host.
</p>
277 <p> An alternative would be to remove the hostname from
278 "hostname.porcupine.org" with address
279 masquerading, as described in the
<a href=
"ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README
</a> document.
282 <li> <p> Reportedly, Outlook
2003 (perhaps Outlook Express, and
283 other versions as well) present substantially different Message-ID
284 headers depending upon whether or not a DSN is requested (via Options
285 "Request a delivery receipt for this message").
</p>
287 <p> When a DSN is requested, Outlook
2003 uses a Message-ID string
288 that ends in the sender's domain name:
</p>
292 Message-ID:
<!
&! ...very long string... ==@example.com
>
296 <p> where
<i>example.com
</i> is the domain name part of the email
297 address specified in Outlook's account settings for the user. Since
298 many users configure their email addresses as
<i>username@example.com
</i>,
299 messages with DSN turned on will trigger the REJECT action in the
300 previous section.
</p>
302 <p> If you have such clients then you can to exclude their Message-ID
303 strings with the two
"<tt>Message-ID:.* <!&!</tt>" patterns
304 that are shown in the previous section. Otherwise you will not be
305 able to use the two backscatter rules to stop forged Message ID
306 strings. Of course this workaround may break the next time Outlook
311 <h3><a name=
"forged_sender">Blocking backscatter mail with forged
312 sender information
</a></h3>
314 Like many people I still have a few email addresses in domains that
315 I used in the past. Mail for those addresses is forwarded to my
316 current address. Most of the backscatter mail that I get claims
317 to be sent from these addresses. Such mail is obviously forged
318 and is very easy to stop.
322 /etc/postfix/
<a href=
"postconf.5.html">main.cf
</a>:
323 <a href=
"postconf.5.html#header_checks">header_checks
</a> =
<a href=
"pcre_table.5.html">pcre
</a>:/etc/postfix/header_checks
324 <a href=
"postconf.5.html#body_checks">body_checks
</a> =
<a href=
"pcre_table.5.html">pcre
</a>:/etc/postfix/body_checks
326 /etc/postfix/header_checks:
327 /^(From|Return-Path):.*\b(user@domain\.tld)\b/
328 reject forged sender address in $
1: header: $
2
330 /etc/postfix/body_checks:
331 /^[
> ]*(From|Return-Path):.*\b(user@domain\.tld)\b/
332 reject forged sender address in $
1: header: $
2
340 <li> <p> The example uses
<a href=
"pcre_table.5.html">pcre
</a>: tables mainly for speed; with minor
341 modifications, you can use
<a href=
"regexp_table.5.html">regexp
</a>: tables as explained below.
</p>
343 <li> <p> The example is simplified for educational purposes. In
344 reality, my patterns list multiple email addresses as
345 "<tt>(user1@domain1\.tld|user2@domain2\.tld)</tt>".
</p>
347 <li> <p> The two
"<tt>\b</tt>" as used in
"<tt>\b(user@domain\.tld)\b</tt>"
348 match the beginning and end of a word, respectively. If you use
349 <a href=
"regexp_table.5.html">regexp
</a>: tables, specify
"<tt>[[:<:]]</tt> and <tt>[[:>:]]</tt>"
350 (on some systems you should specify
"<tt>\<</tt> and <tt>\></tt>"
351 instead; for details see your system documentation).
</p>
353 <li> <p> The
"<tt>\.</tt>" matches
"<tt>.</tt>" literally. Without
354 the
"<tt>\</tt>", the
"<tt>.</tt>" would match any character.
</p>
358 <h3><a name=
"forged_other">Blocking backscatter mail with other
359 forged information
</a></h3>
361 <p> Another sign of forgery can be found in the IP address that is
362 recorded in Received: headers next to your HELO host or domain name.
363 This information must be used with care, though. Some mail servers
364 are behind a network address translator and never see the true
365 client IP address.
</p>
367 <h3><a name=
"scanner">Blocking backscatter mail from virus
370 <p> With all the easily recognizable forgeries eliminated, there
371 is one category of backscatter mail that remains, and that is
372 notifications from virus scanner software. Unfortunately, some
373 virus scanning software doesn't know that viruses forge sender
374 addresses. To make matters worse, the software also doesn't know
375 how to report a mail delivery problem, so that we cannot use the
376 above techniques to recognize forgeries.
</p>
378 <p> Recognizing virus scanner mail is an error prone process,
379 because there is a lot of variation in report formats. The following
380 is only a small example of message header patterns. For a large
381 collection of header and body patterns that recognize virus
382 notification email, see
<a href=
"http://www.dkuug.dk/keld/virus/">http://www.dkuug.dk/keld/virus/
</a>
383 or
<a href=
"http://www.t29.dk/antiantivirus.txt">http://www.t29.dk/antiantivirus.txt
</a>.
</p>
387 /etc/postfix/header_checks:
388 /^Subject: *Your email contains VIRUSES/ DISCARD virus notification
389 /^Content-Disposition:.*VIRUS1_DETECTED_AND_REMOVED/
390 DISCARD virus notification
391 /^Content-Disposition:.*VirusWarning.txt/ DISCARD virus notification
395 <p> Note: these documents haven't been updated since
2004, so they
396 are useful only as a starting point.
</p>
398 <p> A plea to virus or spam scanner operators: please do not make
399 the problem worse by sending return mail to forged sender addresses.
400 You're only harassing innocent people. If you must return mail to
401 the purported sender, please return the full message headers, so
402 that the sender can filter out the obvious forgeries.
</p>