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