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,
80 about email that was sent with a false sender address in your domain.
83 <h2><a name=
"random">How do I block backscatter mail to random
84 recipient addresses?
</a></h2>
86 <p> If your machine receives backscatter mail to random addresses,
87 configure Postfix to reject all mail for non-existent recipients
88 as described in the
<a href=
"LOCAL_RECIPIENT_README.html">LOCAL_RECIPIENT_README
</a> and
89 <a href=
"STANDARD_CONFIGURATION_README.html">STANDARD_CONFIGURATION_README
</a> documentation.
</p>
91 <p> If your machine runs Postfix
2.0 and earlier, disable the
"pause
92 before reject" feature in the SMTP server. If your system is under
93 stress then it should not waste time.
</p>
97 /etc/postfix/
<a href=
"postconf.5.html">main.cf
</a>:
98 # Not needed with Postfix
2.1 and later.
99 <a href=
"postconf.5.html#smtpd_error_sleep_time">smtpd_error_sleep_time
</a> =
0
101 # Not needed with Postfix
2.4 and later.
102 <a href=
"postconf.5.html#unknown_local_recipient_reject_code">unknown_local_recipient_reject_code
</a> =
550
106 <h2><a name=
"real">How do I block backscatter mail to real
107 recipient addresses?
</a></h2>
109 <p> When backscatter mail passes the
"unknown recipient" barrier,
110 there still is no need to despair. Many mail systems are kind
111 enough to attach the message headers of the undeliverable mail in
112 the non-delivery notification. These message headers contain
113 information that you can use to recognize and block forged mail.
116 <h3><a name=
"forged_helo">Blocking backscatter mail with forged
117 mail server information
</a></h3>
119 <p> Although my email address is
"wietse@porcupine.org", all my
120 mail systems announce themselves with the SMTP HELO command as
121 "hostname.porcupine.org". Thus, if returned mail has a Received:
122 message header like this:
</p>
126 Received: from porcupine.org ...
130 <p> Then I know that this is almost certainly forged mail (almost;
131 see
<a href=
"#caveats">next section
</a> for the fly in the ointment).
133 sent by my systems looks like this:
</p>
137 Received: from hostname.porcupine.org ...
141 <p> For the same reason the following message headers are very likely
142 to be the result of forgery:
</p>
146 Received: from host.example.com ([
1.2.3.4] helo=porcupine.org) ...
147 Received: from [
1.2.3.4] (port=
12345 helo=porcupine.org) ...
148 Received: from host.example.com (HELO porcupine.org) ...
149 Received: from host.example.com (EHLO porcupine.org) ...
153 <p> Some forgeries show up in the way that a mail server reports
154 itself in Received: message headers. Keeping in mind that all my
155 systems have a mail server name of
<i>hostname
</i>.porcupine.org,
156 the following is definitely a forgery:
</p>
160 Received: by porcupine.org ...
161 Received: from host.example.com ( ... ) by porcupine.org ...
165 <p> Another frequent sign of forgery is the Message-ID: header. My
166 systems produce a Message-ID: of
167 <<i>stuff
</i>@
<i>hostname
</i>.porcupine.org
>. The following
168 are forgeries, especially the first one:
172 Message-ID:
<1cb479435d8eb9.2beb1.qmail@porcupine.org
>
173 Message-ID:
<yulszqocfzsficvzzju@porcupine.org
>
177 <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>
178 patterns like this:
</p>
182 /etc/postfix/
<a href=
"postconf.5.html">main.cf
</a>:
183 <a href=
"postconf.5.html#header_checks">header_checks
</a> =
<a href=
"pcre_table.5.html">pcre
</a>:/etc/postfix/header_checks
184 <a href=
"postconf.5.html#body_checks">body_checks
</a> =
<a href=
"pcre_table.5.html">pcre
</a>:/etc/postfix/body_checks
186 /etc/postfix/header_checks:
187 # Do not indent the patterns between
"if" and
"endif".
189 /^Received: +from +(porcupine\.org) +/
190 reject forged client name in Received: header: $
1
191 /^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
192 reject forged client name in Received: header: $
2
193 /^Received:.* +by +(porcupine\.org)\b/
194 reject forged mail server name in Received: header: $
1
196 /^Message-ID:.*
<!
&!/ DUNNO
197 /^Message-ID:.*@(porcupine\.org)/
198 reject forged domain name in Message-ID: header: $
1
200 /etc/postfix/body_checks:
201 # Do not indent the patterns between
"if" and
"endif".
202 if /^[
> ]*Received:/
203 /^[
> ]*Received: +from +(porcupine\.org) /
204 reject forged client name in Received: header: $
1
205 /^[
> ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
206 reject forged client name in Received: header: $
2
207 /^[
> ]*Received:.* +by +(porcupine\.org)\b/
208 reject forged mail server name in Received: header: $
1
210 /^[
> ]*Message-ID:.*
<!
&!/ DUNNO
211 /^[
> ]*Message-ID:.*@(porcupine\.org)/
212 reject forged domain name in Message-ID: header: $
1
220 <li> <p> The example uses
<a href=
"pcre_table.5.html">pcre
</a>: tables mainly for speed; with minor
221 modifications, you can use
<a href=
"regexp_table.5.html">regexp
</a>: tables as explained below.
</p>
223 <li> <p> The example is simplified for educational purposes. In
224 reality my patterns list multiple domain names, as
225 "<tt>(domain|domain|...)</tt>".
</p>
227 <li> <p> The
"<tt>\.</tt>" matches
"<tt>.</tt>" literally. Without
228 the
"<tt>\</tt>", the
"<tt>.</tt>" would match any character.
</p>
230 <li> <p> The
"<tt>\(</tt>" and
"<tt>\)</tt>" match
"<tt>(</tt>"
231 and
"<tt>)</tt>" literally. Without the
"<tt>\</tt>", the
"<tt>(</tt>"
232 and
"<tt>)</tt>" would be grouping operators.
</p>
234 <li> <p> The
"<tt>\b</tt>" is used here to match the end of a word.
235 If you use
<a href=
"regexp_table.5.html">regexp
</a>: tables, specify
"<tt>[[:>:]]</tt>" (on some
236 systems you should specify
"<tt>\></tt>" instead; for details
237 see your system documentation).
239 <li> <p> The
"if /pattern/" and
"endif" eliminate unnecessary
240 matching attempts. DO NOT indent lines starting with /pattern/
241 between the
"if" and
"endif"!
</p>
243 <li> <p> The two
"<tt>Message-ID:.* <!&!</tt>" rules are
244 workarounds for some versions of Outlook express, as described in
245 the
<a href=
"#caveats"> caveats
</a> section below.
249 <p><a name=
"caveats"><strong>Caveats
</strong></a></p>
255 <p> Netscape Messenger (and reportedly, Mozilla) sends a HELO name
256 that is identical to the sender address domain part. If you have
257 such clients then the above patterns would block legitimate email.
260 <p> My network has only one such machine, and to prevent its mail
261 from being blocked I have configured it to send mail as
262 user@hostname.porcupine.org. On the Postfix server, a canonical
263 mapping translates this temporary address into user@porcupine.org.
268 /etc/postfix/
<a href=
"postconf.5.html">main.cf
</a>:
269 <a href=
"postconf.5.html#canonical_maps">canonical_maps
</a> = hash:/etc/postfix/canonical
271 /etc/postfix/canonical:
272 @hostname.porcupine.org @porcupine.org
276 <p> This is of course practical only when you have very few systems
277 that send HELO commands like this, and when you never have to send
278 mail to a user on such a host.
</p>
280 <p> An alternative would be to remove the hostname from
281 "hostname.porcupine.org" with address
282 masquerading, as described in the
<a href=
"ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README
</a> document.
285 <li> <p> Reportedly, Outlook
2003 (perhaps Outlook Express, and
286 other versions as well) present substantially different Message-ID
287 headers depending upon whether or not a DSN is requested (via Options
288 "Request a delivery receipt for this message").
</p>
290 <p> When a DSN is requested, Outlook
2003 uses a Message-ID string
291 that ends in the sender's domain name:
</p>
295 Message-ID:
<!
&! ...very long string... ==@example.com
>
299 <p> where
<i>example.com
</i> is the domain name part of the email
300 address specified in Outlook's account settings for the user. Since
301 many users configure their email addresses as
<i>username@example.com
</i>,
302 messages with DSN turned on will trigger the REJECT action in the
303 previous section.
</p>
305 <p> If you have such clients then you can to exclude their Message-ID
306 strings with the two
"<tt>Message-ID:.* <!&!</tt>" patterns
307 that are shown in the previous section. Otherwise you will not be
308 able to use the two backscatter rules to stop forged Message ID
309 strings. Of course this workaround may break the next time Outlook
314 <h3><a name=
"forged_sender">Blocking backscatter mail with forged
315 sender information
</a></h3>
317 Like many people I still have a few email addresses in domains that
318 I used in the past. Mail for those addresses is forwarded to my
319 current address. Most of the backscatter mail that I get claims
320 to be sent from these addresses. Such mail is obviously forged
321 and is very easy to stop.
325 /etc/postfix/
<a href=
"postconf.5.html">main.cf
</a>:
326 <a href=
"postconf.5.html#header_checks">header_checks
</a> =
<a href=
"pcre_table.5.html">pcre
</a>:/etc/postfix/header_checks
327 <a href=
"postconf.5.html#body_checks">body_checks
</a> =
<a href=
"pcre_table.5.html">pcre
</a>:/etc/postfix/body_checks
329 /etc/postfix/header_checks:
330 /^(From|Return-Path):.*\b(user@domain\.tld)\b/
331 reject forged sender address in $
1: header: $
2
333 /etc/postfix/body_checks:
334 /^[
> ]*(From|Return-Path):.*\b(user@domain\.tld)\b/
335 reject forged sender address in $
1: header: $
2
343 <li> <p> The example uses
<a href=
"pcre_table.5.html">pcre
</a>: tables mainly for speed; with minor
344 modifications, you can use
<a href=
"regexp_table.5.html">regexp
</a>: tables as explained below.
</p>
346 <li> <p> The example is simplified for educational purposes. In
347 reality, my patterns list multiple email addresses as
348 "<tt>(user1@domain1\.tld|user2@domain2\.tld)</tt>".
</p>
350 <li> <p> The two
"<tt>\b</tt>" as used in
"<tt>\b(user@domain\.tld)\b</tt>"
351 match the beginning and end of a word, respectively. If you use
352 <a href=
"regexp_table.5.html">regexp
</a>: tables, specify
"<tt>[[:<:]]</tt> and <tt>[[:>:]]</tt>"
353 (on some systems you should specify
"<tt>\<</tt> and <tt>\></tt>"
354 instead; for details see your system documentation).
</p>
356 <li> <p> The
"<tt>\.</tt>" matches
"<tt>.</tt>" literally. Without
357 the
"<tt>\</tt>", the
"<tt>.</tt>" would match any character.
</p>
361 <h3><a name=
"forged_other">Blocking backscatter mail with other
362 forged information
</a></h3>
364 <p> Another sign of forgery can be found in the IP address that is
365 recorded in Received: headers next to your HELO host or domain name.
366 This information must be used with care, though. Some mail servers
367 are behind a network address translator and never see the true
368 client IP address.
</p>
370 <h3><a name=
"scanner">Blocking backscatter mail from virus
373 <p> With all the easily recognizable forgeries eliminated, there
374 is one category of backscatter mail that remains, and that is
375 notifications from virus scanner software. Unfortunately, some
376 virus scanning software doesn't know that viruses forge sender
377 addresses. To make matters worse, the software also doesn't know
378 how to report a mail delivery problem, so that we cannot use the
379 above techniques to recognize forgeries.
</p>
381 <p> Recognizing virus scanner mail is an error prone process,
382 because there is a lot of variation in report formats. The following
383 is only a small example of message header patterns. For a large
384 collection of header and body patterns that recognize virus
385 notification email, see
<a href=
"http://www.dkuug.dk/keld/virus/">http://www.dkuug.dk/keld/virus/
</a>
386 or
<a href=
"http://www.t29.dk/antiantivirus.txt">http://www.t29.dk/antiantivirus.txt
</a>.
</p>
390 /etc/postfix/header_checks:
391 /^Subject: *Your email contains VIRUSES/ DISCARD virus notification
392 /^Content-Disposition:.*VIRUS1_DETECTED_AND_REMOVED/
393 DISCARD virus notification
394 /^Content-Disposition:.*VirusWarning.txt/ DISCARD virus notification
398 <p> Note: these documents haven't been updated since
2004, so they
399 are useful only as a starting point.
</p>
401 <p> A plea to virus or spam scanner operators: please do not make
402 the problem worse by sending return mail to forged sender addresses.
403 You're only harassing innocent people. If you must return mail to
404 the purported sender, please return the full message headers, so
405 that the sender can filter out the obvious forgeries.
</p>