old-www/HOWTO/html_single/Spam-Filtering-for-MX/index.html

14018 lines
300 KiB
HTML
Raw Permalink Blame History

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML
><HEAD
><TITLE
>Spam Filtering for Mail Exchangers</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><META
NAME="KEYWORD"
CONTENT="anti-spam"><META
NAME="KEYWORD"
CONTENT="anti-virus"><META
NAME="KEYWORD"
CONTENT="bogus virus warnings"><META
NAME="KEYWORD"
CONTENT="collateral spam"><META
NAME="KEYWORD"
CONTENT="delivery status notification"><META
NAME="KEYWORD"
CONTENT="dsn"><META
NAME="KEYWORD"
CONTENT="exim"><META
NAME="KEYWORD"
CONTENT="exim4"><META
NAME="KEYWORD"
CONTENT="exiscan"><META
NAME="KEYWORD"
CONTENT="exiscan-acl"><META
NAME="KEYWORD"
CONTENT="greylisting"><META
NAME="KEYWORD"
CONTENT="junk mail"><META
NAME="KEYWORD"
CONTENT="sa-exim"><META
NAME="KEYWORD"
CONTENT="smtp"><META
NAME="KEYWORD"
CONTENT="spam"><META
NAME="KEYWORD"
CONTENT="spamassassin"><META
NAME="KEYWORD"
CONTENT="teergrubing"><META
NAME="KEYWORD"
CONTENT="transaction delay"></HEAD
><BODY
CLASS="book"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="BOOK"
><A
NAME="AEN1"
></A
><DIV
CLASS="TITLEPAGE"
><H1
CLASS="title"
><A
NAME="AEN2"
></A
>Spam Filtering for Mail Exchangers</H1
><H2
CLASS="subtitle"
>How to reject junk mail in incoming SMTP transactions.</H2
><H3
CLASS="author"
><A
NAME="AEN6"
></A
>Tor Slettnes</H3
><DIV
CLASS="affiliation"
><DIV
CLASS="address"
><P
CLASS="address"
><TT
CLASS="email"
>&#60;<A
HREF="mailto:tor@slett.net"
>tor@slett.net</A
>&#62;</TT
></P
></DIV
></DIV
><H4
CLASS="EDITEDBY"
>Edited by</H4
><H3
CLASS="editor"
>Joost De Cock</H3
><H3
CLASS="editor"
>Devdas Bhagat</H3
><H3
CLASS="editor"
>Tom Wright</H3
><P
CLASS="edition"
>Version 1.0 -- Release&nbsp;Edition </P
><HR></DIV
><DIV
CLASS="TOC"
><DL
><DT
><B
>Table of Contents</B
></DT
><DT
><A
HREF="#AEN53"
>Introduction</A
></DT
><DD
><DL
><DT
>1. <A
HREF="#purpose"
>Purpose of this Document</A
></DT
><DT
>2. <A
HREF="#audience"
>Audience</A
></DT
><DT
>3. <A
HREF="#updates"
>New versions of this document</A
></DT
><DT
>4. <A
HREF="#history"
>Revision History</A
></DT
><DT
>5. <A
HREF="#credits"
>Credits</A
></DT
><DT
>6. <A
HREF="#feedback"
>Feedback</A
></DT
><DT
>7. <A
HREF="#translations"
>Translations</A
></DT
><DT
>8. <A
HREF="#copyright"
>Copyright information</A
></DT
><DT
>9. <A
HREF="#prerequisites"
>What do you need?</A
></DT
><DT
>10. <A
HREF="#conventions"
>Conventions used in this document</A
></DT
><DT
>11. <A
HREF="#organization"
>Organization of this document</A
></DT
></DL
></DD
><DT
>1. <A
HREF="#background"
>Background</A
></DT
><DD
><DL
><DT
>1.1. <A
HREF="#whysmtptime"
>Why Filter Mail During the SMTP Transaction?</A
></DT
><DT
>1.2. <A
HREF="#goodbadugly"
>The Good, The Bad, The Ugly</A
></DT
><DT
>1.3. <A
HREF="#smtpintro"
>The SMTP Transaction</A
></DT
></DL
></DD
><DT
>2. <A
HREF="#techniques"
>Techniques</A
></DT
><DD
><DL
><DT
>2.1. <A
HREF="#smtpdelays"
>SMTP Transaction Delays</A
></DT
><DT
>2.2. <A
HREF="#dnschecks"
>DNS Checks</A
></DT
><DT
>2.3. <A
HREF="#smtpchecks"
>SMTP checks</A
></DT
><DT
>2.4. <A
HREF="#greylisting"
>Greylisting</A
></DT
><DT
>2.5. <A
HREF="#senderauth"
>Sender Authorization Schemes</A
></DT
><DT
>2.6. <A
HREF="#datachecks"
>Message data checks</A
></DT
><DT
>2.7. <A
HREF="#collateral"
>Blocking Collateral Spam</A
></DT
></DL
></DD
><DT
>3. <A
HREF="#considerations"
>Considerations</A
></DT
><DD
><DL
><DT
>3.1. <A
HREF="#multimx"
>Multiple Incoming Mail Exchangers</A
></DT
><DT
>3.2. <A
HREF="#otherservers"
>Blocking Access to Other SMTP Servers</A
></DT
><DT
>3.3. <A
HREF="#forwardedmail"
>Forwarded Mail</A
></DT
><DT
>3.4. <A
HREF="#usersettings"
>User Settings and Data</A
></DT
></DL
></DD
><DT
>4. <A
HREF="#qanda"
>Questions &#38; Answers</A
></DT
><DT
>A. <A
HREF="#exim"
>Exim Implementation</A
></DT
><DD
><DL
><DT
>A.1. <A
HREF="#exim-prereq"
>Prerequisites</A
></DT
><DT
>A.2. <A
HREF="#exim-configfile"
>The Exim Configuration File</A
></DT
><DT
>A.3. <A
HREF="#exim-options"
>Options and Settings</A
></DT
><DT
>A.4. <A
HREF="#exim-firstpass"
>Building the ACLs - First Pass</A
></DT
><DT
>A.5. <A
HREF="#exim-smtpdelays"
>Adding SMTP transaction delays</A
></DT
><DT
>A.6. <A
HREF="#exim-greylisting"
>Adding Greylisting Support</A
></DT
><DT
>A.7. <A
HREF="#exim-spf"
>Adding SPF Checks</A
></DT
><DT
>A.8. <A
HREF="#exim-mime"
>Adding MIME and Filetype Checks</A
></DT
><DT
>A.9. <A
HREF="#exim-av"
>Adding Anti-Virus Software</A
></DT
><DT
>A.10. <A
HREF="#exim-sa"
>Adding SpamAssassin</A
></DT
><DT
>A.11. <A
HREF="#exim-sign"
>Adding Envelope Sender Signatures</A
></DT
><DT
>A.12. <A
HREF="#exim-bounces"
>Accept Bounces Only for Real Users</A
></DT
><DT
>A.13. <A
HREF="#exim-forward"
>Exempting Forwarded Mail</A
></DT
><DT
>A.14. <A
HREF="#exim-final"
>Final ACLs</A
></DT
></DL
></DD
><DT
><A
HREF="#glossary"
>Glossary</A
></DT
><DT
>B. <A
HREF="#gpl"
>GNU General Public License</A
></DT
><DD
><DL
><DT
>B.1. <A
HREF="#gpl-1"
>Preamble</A
></DT
><DT
>B.2. <A
HREF="#gpl-2"
>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</A
></DT
><DT
>B.3. <A
HREF="#gpl-3"
>How to Apply These Terms to Your New Programs</A
></DT
></DL
></DD
></DL
></DIV
><DIV
CLASS="LOT"
><DL
CLASS="LOT"
><DT
><B
>List of Tables</B
></DT
><DT
>1. <A
HREF="#conventiontable"
>Typographic and usage conventions</A
></DT
><DT
>1-1. <A
HREF="#smtpdialogue"
>Simple SMTP dialogue</A
></DT
><DT
>A-1. <A
HREF="#aclvarusage"
>Use of ACL connection/message variables</A
></DT
></DL
></DIV
><DIV
CLASS="preface"
><HR><H1
><A
NAME="AEN53"
></A
>Introduction</H1
><DIV
CLASS="section"
><H1
CLASS="section"
><A
NAME="purpose"
></A
>1. Purpose of this Document</H1
><P
>&#13; This document discusses various highly effective and low
impact ways to weed out spam and malware during incoming SMTP
transactions in a mail exchanger (MX host), with an added
emphasis on eliminating so-called <A
HREF="#colspam"
><I
CLASS="glossterm"
>Collateral Spam</I
></A
>.
</P
><P
>&#13; The discussions are conceptual in nature, but a sample
implementation is provided using the Exim MTA and other
specific software tools. Miscellaneous other bigotry is
expressed throughout.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="audience"
></A
>2. Audience</H1
><P
>&#13; The intended audience is mail system administrators, who are
already familiar with such acronyms as SMTP, MTA/MDA/MUA,
DNS/rDNS, and MX records. If you are an end user who is
looking for a spam filtering solution for your mail reader
(such as Evolution, Thunderbird, Mail.app or Outlook Express),
this document is <EM
>not</EM
> for you; but you may
wish to point the mail system administrator for your domain
(company, school, ISP...) to its existence.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="updates"
></A
>3. New versions of this document</H1
><P
>&#13; The newest version of this document can be found at
<A
HREF="http://slett.net/spam-filtering-for-mx/"
TARGET="_top"
>http://slett.net/spam-filtering-for-mx/</A
>.
Please check back periodically for corrections and additions.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="history"
></A
>4. Revision History</H1
><P
>&#13; <DIV
CLASS="revhistory"
><TABLE
WIDTH="100%"
BORDER="0"
><TR
><TH
ALIGN="LEFT"
VALIGN="TOP"
COLSPAN="3"
><B
>Revision History</B
></TH
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 1.0</TD
><TD
ALIGN="LEFT"
>2004-09-08</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>First public release.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.18</TD
><TD
ALIGN="LEFT"
>2004-09-07</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Incorporated second language review from Tom Wright.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.17</TD
><TD
ALIGN="LEFT"
>2004-09-06</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Incorporated language review from Tom Wright.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.16</TD
><TD
ALIGN="LEFT"
>2004-08-13</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Incorporated third round of changes from Devdas Bhagat.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.15</TD
><TD
ALIGN="LEFT"
>2004-08-04</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Incorporated second round of changes from technical
review by Devdas Bhagat.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.14</TD
><TD
ALIGN="LEFT"
>2004-08-01</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Incorporated technical review comments/corrections from
Devdas Bhagat.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.13</TD
><TD
ALIGN="LEFT"
>2004-08-01</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Incorporated technical review from Joost De Cock.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.12</TD
><TD
ALIGN="LEFT"
>2004-07-27</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Replaced "A Note on Controversies" with a more
opinionated "The Good, The Bad, the Ugly" section. Also
rewrote text on DNS blocklists. Some corrections from
Seymour J. Metz.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.11</TD
><TD
ALIGN="LEFT"
>2004-07-19</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Incorporated comments from Rick Stewart on RMX++.
Swapped order of "Techniques" and "Considerations".
Minor typographic fixes in Exim implementation.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.10</TD
><TD
ALIGN="LEFT"
>2004-07-16</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Added &#60;?dbhtml..?&#62; tags to control generated HTML
filenames - should prevent broken links from google etc.
Swapped order of "Forwarded Mail" and "User Settings".
Correction from Tony Finch on Bayesian filters;
commented out check for Subject:, Date:, and Message-ID:
headers per Johannes Berg; processing time subtracted
from SMTP delays per suggestion from Alan Flavell.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.09</TD
><TD
ALIGN="LEFT"
>2004-07-13</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Elaborated on problems with envelope sender signatures
and mailing list servers, and a scheme to make such
signatures optional per host/domain for each user.
Moved "Considerations" section out as a separate
chapter; added subsections "Blocking Access to other
SMTP Server", "User Settings" and "Forwarded Mail".
Incorporated Matthew Byng-Maddick's comments on the
mechanism used to generate these signatures, Chris
Edwards' comments on sender callout verification, and
Hadmut Danisch's comments on RMX++ and other topics.
Changed license terms (GPL instead of GFDL).</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.08</TD
><TD
ALIGN="LEFT"
>2004-07-09</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Additional work on Exim implementation: Added section on
per-user settings and data for SpamAssassin per
suggestion from Tollef Fog Heen. Added SPF checks via
Exiscan-ACL. Corrections from Sam Michaels.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.07</TD
><TD
ALIGN="LEFT"
>2004-07-08</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Made corrections to the Exim Envelope Sender Signatures
examples, and added support for users to "opt in" to
this feature, per suggestion from Christian Balzer.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.06</TD
><TD
ALIGN="LEFT"
>2004-07-08</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Incorporated Exim/MySQL greylisting implementation and
various corrections from Johannes Berg. Moved "Sender
Authorization Schemes" up two levels to become a
top-level section in the Techniques chapter. Added
greylisting for NULL empty envelope senders after DATA.
Added SpamAssassin configuration to match Exim examples.
Incorporated corrections from Dominik Ruff, Mark
Valites, "Andrew" at Supernews.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.05</TD
><TD
ALIGN="LEFT"
>2004-07-07</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Eliminated the (empty) Sendmail implementation for now,
to move ahead with the final review process.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.04</TD
><TD
ALIGN="LEFT"
>2004-07-06</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Reorganized layout a little: Combined "SMTP-Time
Filtering", "Introduction to SMTP", and "Considerations"
into a single "Background" chapter. Split the previous
"Building ACLs" section in the Exim implementation into
top-level sections. Added alternate sender
authorization schemes to SPF: Microsoft Caller-ID for
E-Mail and RMX++. Incorporated comments from Ken
Raeburn.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.03</TD
><TD
ALIGN="LEFT"
>2004-07-02</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Added discussion on Multiple Incoming Mail Exchangers;
minor corrections related to Sender Callout Verification.</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.02</TD
><TD
ALIGN="LEFT"
>2004-06-30</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Added Exim implementation as an appendix</TD
></TR
><TR
><TD
ALIGN="LEFT"
>Revision 0.01</TD
><TD
ALIGN="LEFT"
>2004-06-16</TD
><TD
ALIGN="LEFT"
>Revised by: TS</TD
></TR
><TR
><TD
ALIGN="LEFT"
COLSPAN="3"
>Initial draft.</TD
></TR
></TABLE
></DIV
>
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="credits"
></A
>5. Credits</H1
><P
>&#13; A number of people have provided feedback, corrections, and
contributions, as indicated in the <A
HREF="#history"
>Revision History</A
>.
Thank you!
</P
><P
>&#13; The following are <EM
>some</EM
> of the people and
groups that have provided tools and ideas to this document, in
no particular order:
</P
><P
></P
><UL
><LI
><P
>&#13; Evan Harris <TT
CLASS="email"
>&#60;<A
HREF="mailto:eharris (at) puremagic.com"
>eharris (at) puremagic.com</A
>&#62;</TT
>, who
conceived and wrote a white paper on <A
HREF="#greylisting"
>greylisting</A
>.
</P
></LI
><LI
><P
>&#13; Axel Zinser <TT
CLASS="email"
>&#60;<A
HREF="mailto:fifi (at) hiss.org"
>fifi (at) hiss.org</A
>&#62;</TT
>, who
apparently conceived of
<A
HREF="#smtpdelays"
>teergrubing</A
>.
</P
></LI
><LI
><P
>&#13; The developers of
<A
HREF="http://spf.pobox.com/"
TARGET="_top"
>SPF</A
>,
<A
HREF="http://www.danisch.de/work/security/antispam.html"
TARGET="_top"
>RMX++</A
>,
and other
<A
HREF="#senderauth"
>Sender Authorization Schemes</A
>.
</P
></LI
><LI
><P
>&#13; The creators and maintainers of distributed, collaborative
junk mail signature repositories, such as
<A
HREF="http://rhyolite.com/anti-spam/dcc/"
TARGET="_top"
>DCC</A
>,
<A
HREF="http://razor.sf.net/"
TARGET="_top"
>Razor</A
>, and
<A
HREF="http://pyzor.sf.net/"
TARGET="_top"
>Pyzor</A
>.
</P
></LI
><LI
><P
>&#13; The creators and maintainers of various DNS blocklists and
whitelists, such as
<A
HREF="http://www.spamcop.net/"
TARGET="_top"
>SpamCop</A
>,
<A
HREF="http://www.spamhaus.org/"
TARGET="_top"
>SpamHaus</A
>,
<A
HREF="http://www.sorbs.net/"
TARGET="_top"
>SORBS</A
>,
<A
HREF="http://cbl.abuseat.org/"
TARGET="_top"
>CBL</A
>, and
<A
HREF="http://moensted.dk/spam/"
TARGET="_top"
>many others</A
>.
</P
></LI
><LI
><P
>&#13; The
<A
HREF="http://www.spamassassin.org/full/3.0.x/dist/CREDITS"
TARGET="_top"
>developers</A
>
of
<A
HREF="http://www.spamassassin.org/"
TARGET="_top"
>SpamAssassin</A
>,
who have taken giant leaps forward in developing and
integrating various spam filtering techniques into a
sophisticated heuristics-based tool.
</P
></LI
><LI
><P
>&#13; Tim Jackson <TT
CLASS="email"
>&#60;<A
HREF="mailto:tim (at) timj.co.uk"
>tim (at) timj.co.uk</A
>&#62;</TT
> collated
and maintains a list of
<A
HREF="#bogusviruswarning"
>bogus virus warnings</A
>
for use with SpamAssassin.
</P
></LI
><LI
><P
>&#13; A lot of smart people who developed the excellent <A
HREF="#exim"
>Exim</A
> MTA, including: Philip
Hazel <TT
CLASS="email"
>&#60;<A
HREF="mailto:ph10 (at) cus.cam.ac.uk"
>ph10 (at) cus.cam.ac.uk</A
>&#62;</TT
>, the
maintainer; Tom Kistner <TT
CLASS="email"
>&#60;<A
HREF="mailto:tom (at)
duncanthrax.net"
>tom (at)
duncanthrax.net</A
>&#62;</TT
>, who wrote the Exiscan-ACL patch
for SMTP-time content checks; Andreas Metzler
<TT
CLASS="email"
>&#60;<A
HREF="mailto:ametzler (at) debian.org"
>ametzler (at) debian.org</A
>&#62;</TT
>, who did a really
good job of building the Exim 4 Debian packages.
</P
></LI
><LI
><P
>&#13; Many, many others who contributed ideas, software, and
other techniques to counter the spam epidemic.
</P
></LI
><LI
><P
>&#13; You, for reading this document and your interest in
reclaiming e-mail as a useful communication tool
</P
></LI
></UL
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="feedback"
></A
>6. Feedback</H1
><P
>&#13; I would love to hear of your experiences with the techniques
outlined in this document, and of any other comments,
questions, suggestions, and/or contributions you may have.
Please send me an e-mail at: <TT
CLASS="email"
>&#60;<A
HREF="mailto:tor@slett.net"
>tor@slett.net</A
>&#62;</TT
>.
</P
><P
>&#13; If you are able to provide implementations for other <A
HREF="#mta"
><I
CLASS="glossterm"
>Mail Transport Agent</I
></A
>s, such as Sendmail or Postfix, please let me
know.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="translations"
></A
>7. Translations</H1
><P
>&#13; No translations exist yet. If you would like to create one,
please let me know.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="copyright"
></A
>8. Copyright information</H1
><P
>&#13; Copyright <20> 2004 Tor Slettnes.
</P
><P
>&#13; This document is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
</P
><P
>&#13; This document is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more details.
A copy of the license is included in <A
HREF="#gpl"
>Appendix B</A
>.
</P
><P
>&#13; Read <A
HREF="http://www.fsf.org/gnu/manifesto.html"
TARGET="_top"
>The
GNU Manifesto </A
> if you want to know why this license
was chosen for this book.
</P
><P
>&#13; The logos, trademarks and symbols used in this book are the
properties of their respective owners.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="prerequisites"
></A
>9. What do you need?</H1
><P
>&#13; The techniques described in this document predicate system
access to the inbound <A
HREF="#mx"
><I
CLASS="glossterm"
>Mail Exchanger</I
></A
>(s) for the internet
domain where you receive e-mail. Essentially, you need to be
able to install software and/or modify the configuration files
for the <A
HREF="#mta"
><I
CLASS="glossterm"
>Mail Transport Agent</I
></A
> on that system.
</P
><P
>&#13; Although the discussions in this document are conceptual in
nature and can be incorporated into a number of different
MTAs, a sample Exim 4 implementation is provided. This
implementation, in turn, incorporates other software tools,
such as <A
HREF="http://www.spamassassin.org/"
TARGET="_top"
>SpamAssassin</A
>.
See <A
HREF="#exim"
>Appendix A</A
> for details.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="conventions"
></A
>10. Conventions used in this document</H1
><P
>&#13; The following typographic and usage conventions occur in this text:
</P
><DIV
CLASS="table"
><A
NAME="conventiontable"
></A
><P
><B
>Table 1. Typographic and usage conventions</B
></P
><TABLE
BORDER="1"
CLASS="CALSTABLE"
><THEAD
><TR
><TH
ALIGN="LEFT"
VALIGN="MIDDLE"
>Text type</TH
><TH
ALIGN="LEFT"
VALIGN="MIDDLE"
>Meaning</TH
></TR
></THEAD
><TBODY
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
><SPAN
CLASS="QUOTE"
>"Quoted text"</SPAN
></TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>Quotes from people, quoted computer output.</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>terminal view</PRE
></FONT
></TD
></TR
></TABLE
></TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Literal computer input and output captured from
the terminal, usually rendered with a light grey
background.
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
><B
CLASS="command"
>command</B
></TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Name of a command that can be entered on the command
line.
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
><TT
CLASS="varname"
>VARIABLE</TT
></TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Name of a variable or pointer to content of a
variable, as in <TT
CLASS="varname"
>$VARNAME</TT
>.
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
><TT
CLASS="option"
>option</TT
></TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Option to a command, as in <SPAN
CLASS="QUOTE"
>"the
<TT
CLASS="option"
>-a</TT
> option to the
<B
CLASS="command"
>ls</B
> command"</SPAN
>.
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
><TT
CLASS="parameter"
><I
>argument</I
></TT
></TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Argument to a command, as in
<SPAN
CLASS="QUOTE"
>"read <B
CLASS="command"
>man
<TT
CLASS="parameter"
><I
>ls</I
></TT
></B
>
"</SPAN
>.
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
><B
CLASS="command"
>command
<TT
CLASS="option"
>options</TT
>
<TT
CLASS="parameter"
><I
>arguments</I
></TT
>
</B
> </P
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Command synopsis or general usage, on a separated
line.
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
><TT
CLASS="filename"
>filename</TT
></TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Name of a file or directory, for example <SPAN
CLASS="QUOTE"
>"Change
to the <TT
CLASS="filename"
>/usr/bin</TT
>
directory."</SPAN
>
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
><B
CLASS="keycap"
>Key</B
></TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Keys to hit on the keyboard, such as <SPAN
CLASS="QUOTE"
>"type
<B
CLASS="keycap"
>Q</B
> to quit"</SPAN
>.
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
><SPAN
CLASS="guibutton"
>Button</SPAN
></TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Graphical button to click, like the
<SPAN
CLASS="guibutton"
>OK</SPAN
> button.
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <SPAN
CLASS="guimenu"
>Menu</SPAN
>-&gt;<SPAN
CLASS="guimenuitem"
>Choice</SPAN
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Choice to select from a graphical menu, for instance:
<SPAN
CLASS="QUOTE"
>"Select
<SPAN
CLASS="guimenu"
>Help</SPAN
>-&gt;<SPAN
CLASS="guimenuitem"
>About
Mozilla</SPAN
> in your
browser."</SPAN
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <EM
>Terminology</EM
></TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; Important term or concept:
<SPAN
CLASS="QUOTE"
>"The Linux <EM
>kernel</EM
>
is the heart of the system."</SPAN
>
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; See <A
HREF="#glossary"
>Glossary</A
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; link to related subject within this guide.
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <A
HREF="http://slett.net/gallery/2003-05/IMG_1655"
TARGET="_top"
>The author</A
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>Clickable link to an external web resource.</TD
></TR
></TBODY
></TABLE
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="organization"
></A
>11. Organization of this document</H1
><P
>&#13; This document is organized into the following chapters:
</P
><P
></P
><DIV
CLASS="variablelist"
><DL
><DT
><A
HREF="#background"
>Background</A
></DT
><DD
><P
>&#13; General introduction to SMTP time filtering, and to SMTP.
</P
></DD
><DT
><A
HREF="#techniques"
>Techniques</A
></DT
><DD
><P
>&#13; Various ways to block junk mail in an SMTP transaction.
</P
></DD
><DT
><A
HREF="#considerations"
>Considerations</A
></DT
><DD
><P
>&#13; Issues that pertain to transaction time filtering.
</P
></DD
><DT
><A
HREF="#qanda"
>Questions &#38; Answers</A
></DT
><DD
><P
>&#13; My attempt at anticipating your questions, and then
answering them.
</P
></DD
></DL
></DIV
><P
>&#13; A sample Exim implementation is provided in <A
HREF="#exim"
>Appendix A</A
>.
</P
></DIV
></DIV
><DIV
CLASS="chapter"
><HR><H1
><A
NAME="background"
></A
>Chapter 1. Background</H1
><BLOCKQUOTE
CLASS="ABSTRACT"
><DIV
CLASS="abstract"
><A
NAME="AEN362"
></A
><P
></P
><P
>&#13; Here we cover the advantages of filtering mail during an
incoming SMTP transaction, rather than following the more
conventional approach of offloading this task to the mail
routing and delivery stage. We also provide a brief
introduction to the SMTP transaction.
</P
><P
></P
></DIV
></BLOCKQUOTE
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="whysmtptime"
></A
>1.1. Why Filter Mail During the SMTP Transaction?</H1
><DIV
CLASS="section"
><H2
CLASS="section"
><A
NAME="statusquo"
></A
>1.1.1. Status Quo</H2
><P
>&#13; If you receive spam, raise your hands. Keep them up.
</P
><P
>&#13; If you receive computer virii or other malware, raise your
hands too.
</P
><P
>&#13; If you receive bogus <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
>s (DSNs), such as
<SPAN
CLASS="QUOTE"
>"Message Undeliverable"</SPAN
>, <SPAN
CLASS="QUOTE"
>"Virus
found"</SPAN
>, <SPAN
CLASS="QUOTE"
>"Please confirm delivery"</SPAN
>, etc,
related to messages you never sent, raise your hands as well.
This is known as <A
HREF="#colspam"
><I
CLASS="glossterm"
>Collateral Spam</I
></A
>.
</P
><P
>&#13; This last form is particularly troublesome, because it is
harder to weed out than <SPAN
CLASS="QUOTE"
>"standard"</SPAN
> spam or
malware, and because such messages can be quite confusing to
recipients who do not possess godly skills in parsing message
headers. In the case of virus warnings, this often causes
unnecessary concern on the recipient's end; more generally, a
common tendency will be to ignore all such messages, thereby
missing out on legitimate DSNs.
</P
><P
>&#13; Finally, I want those of you who have lost legitimate mail into
a big black hole - due to misclassification by spam or virus
scanners - to lift your feet.
</P
><P
>&#13; If you were standing before and are still standing, I suggest
that you may not be fully aware of what is happening to your
mail. If you have been doing any type of spam filtering, even
by manually moving mails to the trash can in your mail reader,
let alone by experimenting with primitive filtering techniques
such as DNS blacklists (SpamHaus, SPEWS, SORBS...), chances
are that you have lost some valid mail.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="cause"
></A
>1.1.2. The Cause</H2
><P
>&#13; Spam, just like many other artifacts of greed, is a social
disease. Call it affluenza, or whatever you like; lower life
forms seek to destroy a larger ecosystem, and if successful,
will actually end up ruining their own habitat in the end.
</P
><P
>&#13; Larger social issues and philosophy aside: You - the mail system
administrator - face the very concrete and real life dilemma of
finding a way to deal with all this junk.
</P
><P
>&#13; As it turns out, there are some limitations with the
conventional way that mail is being processed and delegated by
the various components of mail transport and delivery
software. In a traditional setup, one or more <A
HREF="#mx"
><I
CLASS="glossterm"
>Mail Exchanger</I
></A
>(s) accept most or all incoming mail deliveries
to addresses within a domain. Often, they then forward the
mail to one or more internal machines for further processing,
and/or delivery to the user's mailboxes. If any of these
servers discovers that it is unable to perform the requested
delivery or function, it generates and returns a DSN back to
the sender address in the original mail.
</P
><P
>&#13; As organizations started deploying spam and virus scanners,
they often found that the path of least resistance was to work
these into the message delivery path, as mail is transferred
from the incoming <A
HREF="#mx"
><I
CLASS="glossterm"
>Mail Exchanger</I
></A
>(s) to internal delivery
hosts and/or software. For instance, a common way filter out
spam is by <EM
>routing</EM
> the mail through
SpamAssassin or other software before it is delivered to a
user's mailbox, and/or rely on spam filtering capabilities in
the user's <A
HREF="#mua"
><I
CLASS="glossterm"
>Mail User Agent</I
></A
>.
</P
><P
>&#13; Options for dealing with mail that is classified as spam or
virus at this point are limited:
</P
><P
></P
><UL
><LI
><P
>&#13; You can return a <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
> back to the sender.
The problem is that nearly all spam and e-mail borne
virii are delivered with faked sender addresses. If you
return this mail, it will invariably go to innocent third
parties -- perhaps warning a grandmother in Sweden, who
uses Mac OS X and does not know much about computers, that
she is infected by the Blaster worm. In other words, you
will be generating <A
HREF="#colspam"
><I
CLASS="glossterm"
>Collateral Spam</I
></A
>.
</P
></LI
><LI
><P
>&#13; You can drop the message into the bit bucket, without
sending any notification back to the sender. This is an
even bigger problem in the case of <A
HREF="#falsepos"
><I
CLASS="glossterm"
>False Positive</I
></A
>s, because neither the sender nor
the receiver will ever know what happened to the message
(or in the receiver's case, that it ever existed).
</P
></LI
><LI
><P
>&#13; Depending on how your users access their mail (for
instance, if they access it via the IMAP protocol or use a
web-based mail reader, but not if they retreive it over
POP-3), you may be able to file it into a separate junk
folder for them -- perhaps as an option in their account
settings.
</P
><P
>&#13; This may be the best of these three options. Even so, the
messages may remain unseen for some time, or simply
overlooked as the receiver more-or-less periodically scans
through and deletes mail in their <SPAN
CLASS="QUOTE"
>"Junk"</SPAN
>
folder.
</P
></LI
></UL
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="solution"
></A
>1.1.3. The Solution</H2
><P
>&#13; As you would have guessed by now, the <EM
>One
True</EM
> solution to this problem is to do spam and
virus filtering during the SMTP dialogue from the remote host,
as the mail is being received by the inbound mail exchanger
for your domain. This way, if the mail turns out to be
undesirable, you can issue a SMTP <EM
>reject</EM
>
response rather than face the dilemma described above. As a
result:
</P
><P
></P
><UL
><LI
><P
>&#13; You will be able to stop the delivery of most junk mail
early in the SMTP transaction, before the actual message
data has been received, thus saving you both network
bandwidth and CPU processing.
</P
></LI
><LI
><P
>&#13; You will be able to deploy some spam filtering techniques
that are not possible later, such as
<A
HREF="#smtpdelays"
>SMTP transaction delays</A
> and
<A
HREF="#greylisting"
>Greylisting</A
>.
</P
></LI
><LI
><P
>&#13; You will be able to notify the sender in case of a
delivery failure (e.g. due to an invalid recipient
address) without directly generating <A
HREF="#colspam"
><I
CLASS="glossterm"
>Collateral Spam</I
></A
>
</P
><P
>&#13; We will discuss how you can avoid causing collateral spam
indirectly as a result of rejecting mail forwarded from
trusted sources, such as mailing list servers or mail
accounts on other sites
<A
NAME="AEN419"
HREF="#FTN.AEN419"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
>.
</P
></LI
><LI
><P
>&#13; You will be able to protect yourself against collateral
spam from others (such as bogus <SPAN
CLASS="QUOTE"
>"You have a
virus"</SPAN
> messages from anti-virus software).
</P
></LI
></UL
><P
>&#13; OK, you can lower your hands now. If you were standing, and
your feet disappeared from under you, you can now also stand up
again.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="goodbadugly"
></A
>1.2. The Good, The Bad, The Ugly</H1
><P
>&#13; Some filtering techniques are more suitable for use during the
SMTP transaction than others. Some are simply better than
others. Nearly all have their proponents and opponents.
</P
><P
>&#13; Needless to say, these controversies extend to the methods
described here as well. For instance:
</P
><P
></P
><UL
><LI
><P
>&#13; Some argue that <A
HREF="#dnschecks"
>DNS checks</A
> penalize
individual mail senders purely based on their Internet
Service Provider (ISP), not on the merits of their
particular message.
</P
></LI
><LI
><P
>&#13; Some point out that ratware traps like <A
HREF="#smtpdelays"
>SMTP transaction delays</A
> and <A
HREF="#greylisting"
>Greylisting</A
> are
easily overcome and will be less effective over time, while
continuing to degrade the Quality of Service for legitimate
mail.
</P
></LI
><LI
><P
>&#13; Some find that <A
HREF="#senderauth"
>Sender Authorization Schemes</A
> like the <A
HREF="#spf"
>Sender Policy Framework</A
> give ISPs a way to lock their customers in,
and do not adequately address users who roam between
different networks or who forward their e-mail from one host
to another.
</P
></LI
></UL
><P
>&#13; I will steer away from most of these controversies. Instead, I
will try to provide a functional description of the various
techniques available, including their possible side effects, and
then talk a little about my own experiences using some of them.
</P
><P
>&#13; That said, there are some filtering methods in use today that I
deliberately omit from this document:
</P
><P
></P
><UL
><LI
><P
>&#13; Challenge/response systems (like <A
HREF="http://tmda.net/"
TARGET="_top"
>TMDA</A
>). These are not
suitable for SMTP time filtering, as they rely on first
accepting the mail, then returning a confirmation request to
the <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
>. This technique is therefore
outside the scope of this document.
<A
NAME="AEN452"
HREF="#FTN.AEN452"
><SPAN
CLASS="footnote"
>[2]</SPAN
></A
>
</P
></LI
><LI
><P
>&#13; <A
HREF="#bayesian"
><I
CLASS="glossterm"
>Bayesian Filters</I
></A
>. These require training specific
to a particular user, and/or a particular language. As
such, these too are not normally suitable for use during the
SMTP transaction (But see <A
HREF="#usersettings"
>User Settings and Data</A
>).
</P
></LI
><LI
><P
>&#13; <A
HREF="#micropay"
><I
CLASS="glossterm"
>Micropayment Schemes</I
></A
> are not really suitable for
weeding out junk mail until all the world's legitimate mail
is sent with a virtual <EM
>postage stamp</EM
>.
(Though in the mean time, they can be used for the opposite
purpose - that is, to accept mail carrying the stamp that
would otherwise be rejected).
</P
></LI
></UL
><P
>&#13; Generally, I have attempted to offer techniques that are as
precise as possible, and to go to great lengths to avoid <A
HREF="#falsepos"
><I
CLASS="glossterm"
>False Positive</I
></A
>s. People's e-mail is important to them,
and they spend time and effort writing it. In my view,
willfully using techniques or tools that reject large amounts of
legitimate mail is a show of disrespect, both to the people that
are directly affected and to the Internet as a whole.
<A
NAME="AEN465"
HREF="#FTN.AEN465"
><SPAN
CLASS="footnote"
>[3]</SPAN
></A
>
This is especially true for SMTP-time system wide filtering,
because end recipients usually have little or no control over
the criteria being used to filter their mail.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="smtpintro"
></A
>1.3. The SMTP Transaction</H1
><P
>&#13; SMTP is the protocol that is used for mail delivery on the
Internet. For a detailed description of the protocol, please
refer to <A
HREF="http://www.ietf.org/rfc/rfc2821.txt"
TARGET="_top"
>RFC
2821</A
>, as well as Dave Crocker's introduction to
<A
HREF="http://www.brandenburg.com/specifications/draft-crocker-mail-arch-00.htm"
TARGET="_top"
>Internet Mail Architecture</A
>.
</P
><P
>&#13; Mail deliveries involve an SMTP transaction between the
connecting host (client) and the receiving host (server). For
this discussion, the connecting host is the peer, and the
receiving host is your server.
</P
><P
>&#13; In a typical SMTP transaction, the client issues SMTP commands
such as <B
CLASS="command"
>EHLO</B
>, <B
CLASS="command"
>MAIL FROM:</B
>,
<B
CLASS="command"
>RCPT TO:</B
>, and <B
CLASS="command"
>DATA</B
>. Your
server responds to each command with a 3-digit numeric code
indicating whether the command was accepted
(<B
CLASS="command"
>2<TT
CLASS="parameter"
><I
>xx</I
></TT
></B
>), was subject to
a temporary failure or restriction
(<B
CLASS="command"
>4<TT
CLASS="parameter"
><I
>xx</I
></TT
></B
>), or failed
definitively/permanently
(<B
CLASS="command"
>5<TT
CLASS="parameter"
><I
>xx</I
></TT
></B
>), followed by
some human readable explanation. A full description of these
codes is included in
<A
HREF="http://www.ietf.org/rfc/rfc2821.txt"
TARGET="_top"
>RFC 2821</A
>.
</P
><P
>&#13; A best case scenario SMTP transaction typically consists of the
following relevant steps:
</P
><DIV
CLASS="table"
><A
NAME="smtpdialogue"
></A
><P
><B
>Table 1-1. Simple SMTP dialogue</B
></P
><TABLE
BORDER="1"
CLASS="CALSTABLE"
><THEAD
><TR
><TH
ALIGN="LEFT"
VALIGN="MIDDLE"
>Client</TH
><TH
ALIGN="LEFT"
VALIGN="MIDDLE"
>Server</TH
></TR
></THEAD
><TBODY
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Initiates a TCP connection to server.
</P
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Presents an SMTP banner - that is, a greeting that
starts with the code <B
CLASS="command"
>220</B
> to indicate
that it is ready to speak SMTP (or usually ESMTP, a
superset of SMTP):
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>220 <TT
CLASS="parameter"
><I
>your.f.q.d.n</I
></TT
> ESTMP...</PRE
></FONT
></TD
></TR
></TABLE
>
</P
>
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Introduces itself by way of an Hello command, either
<B
CLASS="command"
>HELO</B
> (now obsolete) or
<B
CLASS="command"
>EHLO</B
>, followed by its own <A
HREF="#fqdn"
><I
CLASS="glossterm"
>Fully Qualified Domain Name</I
></A
>:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>EHLO <TT
CLASS="parameter"
><I
>peers.f.q.d.n</I
></TT
></PRE
></FONT
></TD
></TR
></TABLE
>
</P
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Accepts this greeting with a <B
CLASS="command"
>250</B
>
response. If the client used the
<EM
>extended</EM
> version of the Hello
command (<B
CLASS="command"
>EHLO</B
>), your server knows
that it is capable of handling multi-line responses,
and so will normally send back several lines
indicating the capabilities offered by your server:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;250-<TT
CLASS="parameter"
><I
>your.f.q.d.n</I
></TT
> Hello ...
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-STARTTLS
250-AUTH
250 HELP
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
>
<P
>&#13; If the <B
CLASS="command"
>PIPELINING</B
> capability is
included in this response, the client can from this point
forward issue several commands at once, without waiting
for the response to each one.
</P
>
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Starts a new mail transaction by specifying the
<A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
>:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>MAIL FROM:&#60;<TT
CLASS="parameter"
><I
>sender</I
></TT
>@<TT
CLASS="parameter"
><I
>address</I
></TT
>&#62;
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Issues a <B
CLASS="command"
>250</B
> response to indicate
that the sender is accepted.
</P
>
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Lists the <A
HREF="#envto"
><I
CLASS="glossterm"
>Envelope Recipient</I
></A
>s of the message, one
at a time, using the command:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>RCPT TO:&#60;<TT
CLASS="parameter"
><I
>receiver</I
></TT
>@<TT
CLASS="parameter"
><I
>address</I
></TT
>&#62;</PRE
></FONT
></TD
></TR
></TABLE
>
</P
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Issues a response to each command
(<B
CLASS="command"
>2<TT
CLASS="parameter"
><I
>xx</I
></TT
></B
>,
<B
CLASS="command"
>4<TT
CLASS="parameter"
><I
>xx</I
></TT
></B
>, or
<B
CLASS="command"
>5<TT
CLASS="parameter"
><I
>xx</I
></TT
></B
>,
depending on whether delivery to this recipient was
accepted, subject to a temporary failure, or
rejected).
</P
>
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Issues a <B
CLASS="command"
>DATA</B
> command to indicate
that it is ready to send the message.
</P
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Responds <B
CLASS="command"
>354</B
> to indicate that the
command has been provisionally accepted.
</P
>
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Transmits the message, starting with RFC 2822
compliant header lines (such as:
<TT
CLASS="option"
>From:</TT
>, <TT
CLASS="option"
>To:</TT
>,
<TT
CLASS="option"
>Subject:</TT
>, <TT
CLASS="option"
>Date:</TT
>,
<TT
CLASS="option"
>Message-ID:</TT
>). The header and the
body are separated by an empty line. To indicate the
end of the message, the client sends a single period
(".") on a separate line.
</P
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Replies <B
CLASS="command"
>250</B
> to indicate that the
message has been accepted.
</P
>
</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; If there are more messages to be delivered, issues the
next <B
CLASS="command"
>MAIL FROM:</B
> command.
Otherwise, it says <B
CLASS="command"
>QUIT</B
>, or in rare
cases, simply disconnects.
</P
>
</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>&#13; <P
>&#13; Disconnects.
</P
>
</TD
></TR
></TBODY
></TABLE
></DIV
></DIV
></DIV
><DIV
CLASS="chapter"
><HR><H1
><A
NAME="techniques"
></A
>Chapter 2. Techniques</H1
><BLOCKQUOTE
CLASS="ABSTRACT"
><DIV
CLASS="abstract"
><A
NAME="AEN579"
></A
><P
></P
><P
>&#13; In this chapter, we look at various ways to weed out junk mail
during the SMTP transaction from remote hosts. We will also try
to anticipate some of the side effects from deploying these
techniques.
</P
><P
></P
></DIV
></BLOCKQUOTE
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="smtpdelays"
></A
>2.1. SMTP Transaction Delays</H1
><P
>&#13; As it turns out, one of the more effective ways of stopping spam
is by imposing transaction delays during an inbound SMTP
dialogue. This is a primitive form of
<EM
>teergrubing</EM
>, see: <A
HREF="http://www.iks-jena.de/mitarb/lutz/usenet/teergrube.en.html"
TARGET="_top"
>http://www.iks-jena.de/mitarb/lutz/usenet/teergrube.en.html</A
>
</P
><P
>&#13; Most spam and nearly all e-mail borne virii are delivered
directly to your server by way of specialized SMTP client
software, optimized for sending out large amounts of mail in a
very short time. Such clients are commonly known as
<A
HREF="#ratware"
><I
CLASS="glossterm"
>Ratware</I
></A
>.
</P
><P
>&#13; In order to accomplish this task, ratware authors commonly take
a few shortcuts that, ahem, <SPAN
CLASS="QUOTE"
>"diverge"</SPAN
> a bit
from the RFC 2821 specification. One of the intrinsic traits of
ratware is that it is notoriously impatient, especially with
slow-responding mail servers. They may issue the
<B
CLASS="command"
>HELO</B
> or <B
CLASS="command"
>EHLO</B
> command
before the server has presented the initial SMTP banner, and/or
try to pipeline several SMTP commands before the server has
advertised the <B
CLASS="command"
>PIPELINING</B
> capability.
</P
><P
>&#13; Certain <A
HREF="#mta"
><I
CLASS="glossterm"
>Mail Transport Agent</I
></A
>s (such as Exim) automatically
treat such SMTP protocol violations as
<EM
>synchronization errors</EM
>, and immediately
drop the incoming connection. If you happen to be using such an
MTA, you may already see a lot of entries to this effect in your
log files. In fact, chances are that if you perform any
time-consuming checks (such as
<A
HREF="#dnschecks"
>DNS checks</A
>) prior to presenting the initial
SMTP banner, such errors will occur frequently, as ratware
clients simply do not take the time to wait for your server to
come alive (Things to do, people to spam).
</P
><P
>&#13; We can help along by imposing additional delays. For instance,
you may decide to wait:
</P
><P
></P
><UL
><LI
><P
>&#13; 20 seconds before presenting the initial SMTP banner,
</P
></LI
><LI
><P
>&#13; 20 seconds after the Hello (<B
CLASS="command"
>EHLO</B
> or
<B
CLASS="command"
>HELO</B
>) greeting,
</P
></LI
><LI
><P
>&#13; 20 seconds, after the <B
CLASS="command"
>MAIL FROM:</B
>
command, and
</P
></LI
><LI
><P
>&#13; 20 seconds after each <B
CLASS="command"
>RCPT TO:</B
> command.
</P
></LI
></UL
><P
>&#13; Where did 20 seconds come from, you ask. Why not a minute? Or
several minutes? After all, RFC 2821 mandates that the sending
host (client) should wait up to several minutes for every SMTP
response. The issue is that some receiving hosts, particularly
those that use Exim, may perform <A
HREF="#callback"
>Sender Callout Verification</A
> in
response to incoming mail delivery attempts. If you or one of
your users send mail to such a host, it will contact the <A
HREF="#mx"
><I
CLASS="glossterm"
>Mail Exchanger</I
></A
> (MX host) for your domain and start an SMTP
dialogue in order to validate the sender address. The default
timeout of such <A
HREF="#callback"
>Sender Callout Verification</A
>s is 30 seconds - if
you impose delays this long, the peer's sender callout
verification would fail, and in turn the original mail delivery
from you/your user might be rejected (usually with a temporary
failure, which means the message delivery will be retried for 5
days or so before the mail is finally returned to the sender).
</P
><P
>&#13; In other words, 20 seconds is about as long as you can stall
before you start interfering with legitimate mail deliveries.
</P
><P
>&#13; If you do not like imposing such delays on every SMTP
transaction (say, you have a very busy site and are low on
machine resources), you may choose to use
<SPAN
CLASS="QUOTE"
>"selective"</SPAN
> transaction delays. In this case, you
could impose the delay:
</P
><P
></P
><UL
><LI
><P
>&#13; If there is a problem with the peer's DNS information (see
<A
HREF="#dnschecks"
>DNS checks</A
>).
</P
></LI
><LI
><P
>&#13; After detecting some sign of trouble during the SMTP
transaction (see <A
HREF="#smtpchecks"
>SMTP checks</A
>).
</P
></LI
><LI
><P
>&#13; Only in the highest-numbered MX host in your DNS zone,
i.e. the mail exchanger with the last priority. Often,
<A
HREF="#ratware"
><I
CLASS="glossterm"
>Ratware</I
></A
> specifically target these hosts,
whereas legitimate MTAs will try the lower-numbered MX hosts
first.
</P
></LI
></UL
><P
>&#13; In fact, selective transaction delays may be a good way to
incorporate some less conclusive checks that we will discuss in
the following sections. You probably do not wish to reject the
mail outright based the results from e.g. the SPEWS <A
HREF="#dnsbl"
>blacklist</A
>, but on the other hand, it may
provide a strong enough indication of trouble that you can at
least impose transaction delays. After all, legitimate mail
deliveries are not affected, other than being subjected to a
slight delay.
</P
><P
>&#13; Conversely, if you find conclusive evidence of spamming (e.g. by
way of certain <A
HREF="#smtpchecks"
>SMTP checks</A
>), and your server
can afford it, you may choose to impose an extended delay,
e.g. 15 minutes or so, before finally rejecting the delivery
<A
NAME="AEN632"
HREF="#FTN.AEN632"
><SPAN
CLASS="footnote"
>[4]</SPAN
></A
>.
This is for little or no benefit other than slowing down the
spammer a little bit in their quest to reach as many people as
possible before DNS blacklists and other collaborative network
checks catch up. In other words, pure altruism on your
side. :-)
</P
><P
>&#13; In my own case, selective transaction delays and the resulting
SMTP synchronization errors account for nearly 50% of rejected
incoming delivery attempts. This roughly translates into saying
that nearly 50% of incoming junk mail is stopped by SMTP
transaction delays alone.
</P
><P
>&#13; See also <A
HREF="#qanda-adapt"
><EM
>What happens when
spammers adapt...</EM
></A
>.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="dnschecks"
></A
>2.2. DNS Checks</H1
><P
>&#13; Some indication of the integrity of a particular peer can be
gleaned directly from the <A
HREF="#dns"
><I
CLASS="glossterm"
>Domain Name System</I
></A
> (DNS), even
before SMTP commands are issued. In particular, various DNS
blacklists can be consulted to find out if a particular IP
address is known to violate or fulfill certain criteria, and a
simple pair of forward/reverse (DNS/rDNS) lookups can be used as
a vague indicator of the host's general integrity.
</P
><P
>&#13; Moreover, various data items presented during the SMTP dialogue
(such as the name presented in the Hello greeting) can be
subjected to DNS validation, once it becomes available. For a
discussion on these items, see the section on <A
HREF="#smtpchecks"
>SMTP checks</A
>, below.
</P
><P
>&#13; A word of caution, though. DNS checks are not always conclusive
(e.g. a required DNS server may not be responding), and not
always indicative of spam. Moreover, if you have a very busy
site, they can be expensive in terms of processing time per
message. That said, they can provide useful information for
logging purposes, and/or as part of a more holistic integrity
check.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="dnsbl"
></A
>2.2.1. DNS Blacklists</H2
><P
>&#13; DNS blacklists (DNSbl's, formerly called "Real-time Black-hole
Lists" after the original blacklist, "mail-abuse.org") make up
perhaps the most common tool to perform transaction-time spam
blocking. The receiving server performs one or more rDNS
lookups of the peer's IP address within various DNSbl zones,
such as "dnsbl.sorbs.net", "opm.blitzed.org",
"lists.dsbl.org", and so forth. If a matching DNS record is
found, a typical action is to reject the mail delivery.
<A
NAME="AEN649"
HREF="#FTN.AEN649"
><SPAN
CLASS="footnote"
>[5]</SPAN
></A
>
</P
><P
>&#13; If in addition to the DNS address ("A" record) you look up the
"TXT" record of an entry, you will typically receive a
one-line description of the listing, suitable for inclusion in
a SMTP reject response. To try this out, you can use the
"host" command provided on most Linux and UNIX systems:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>host -t txt 2.0.0.127.dnsbl.sorbs.net</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; There are currently hundreds of these lists available, each
with different listing criteria, and with different
listing/unlisting policies. Some lists even combine several
listing criteria into the same DNSbl, and issue different data
in response to the rDNS lookup, depending on which criterion
affects the address provided. For instance, a rDNS lookup
against <TT
CLASS="option"
>sbl-xbl.spamhaus.org</TT
> returns
127.0.0.2 for IP addresses that are believed by the SpamHaus
staff to directly belong to spammers and their providers,
127.0.0.4 response for <A
HREF="#zombie"
><I
CLASS="glossterm"
>Zombie Host</I
></A
>s, or a
127.0.0.6 response for <A
HREF="#openproxy"
><I
CLASS="glossterm"
>Open Proxy</I
></A
> servers.
</P
><P
>&#13; Unfortunately, many of these lists contain large blocks of IP
addresses that are not directly responsible for the alleged
violations, don't have clear listing / delisting policies,
and/or post misleading information about which addresses are
listed<A
NAME="AEN661"
HREF="#FTN.AEN661"
><SPAN
CLASS="footnote"
>[6]</SPAN
></A
>.
The blind trust in such lists often cause a large amount of
what is referred to as <A
HREF="#coldamage"
><I
CLASS="glossterm"
>Collateral Damage</I
></A
> (not to be
confused with <A
HREF="#colspam"
><I
CLASS="glossterm"
>Collateral Spam</I
></A
>).
</P
><P
>&#13; For that reason, rather than rejecting mail deliveries
outright based on a single positive response from DNS
blacklists, many administrators prefer to use these lists in a
more nuanced fashion. They may consult several lists, and
assign a "score" to each positive response. If the total
score for a given IP address reaches a given threshold,
deliveries from that address are rejected. This is how DNS
blacklists are used by filtering software such as
SpamAssassin (<A
HREF="#spamscanners"
>Spam Scanners</A
>).
</P
><P
>&#13; One could also use such lists as one of several triggers for
SMTP transaction delays on incoming connections
(a.k.a. "teergrubing"). If a host is listed in a DNSbl, your
server would delay its response to every SMTP command issued
by the peer for, say, 20 seconds. Several other criteria can
be used as triggers for such delays; see the section on
<A
HREF="#smtpdelays"
>SMTP transaction delays</A
>.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="rdns"
></A
>2.2.2. DNS Integrity Check</H2
><P
>&#13; Another way to use DNS is to perform a reverse lookup of the
peer's IP address, then a forward lookup of the resulting
name. If the original IP address is included in the result,
its DNS integrity has been validated. Otherwise, the DNS
information for the connecting host is not valid.
</P
><P
>&#13; Rejecting mails based on this criterion may be an option if
you are a militant member of the DNS police, setting up an
incoming MX for your own personal domain, and don't mind
rejecting legitimate mail as a way to impress upon the sender
that they need to ask their own system administrator to clean
up their DNS records. For everyone else, the result of a DNS
integrity check should probably only be used as one data point
in a larger set of heuristics. Alternatively, as above, using
SMTP transaction delays for misconfigured hosts may not be a
bad idea.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="smtpchecks"
></A
>2.3. SMTP checks</H1
><P
>&#13; Once the SMTP dialogue is underway, you can perform various
checks on the commands and arguments presented by the remote
host. For instance, you will want to ensure that the name
presented in the Hello greeting is valid.
</P
><P
>&#13; However, even if you decide to reject the delivery attempt early
in the SMTP transaction, you may not want to perform the actual
rejection right away. Instead, you may stall the sender with
SMTP transaction delays until after the <B
CLASS="command"
>RCPT
TO:</B
>, then reject the mail at that point.
</P
><P
>&#13; The reason is that some ratware does not understand rejections
early in the SMTP transaction; they keep trying. On the other
hand, most of them give up if the <B
CLASS="command"
>RCPT TO:</B
>
fails.
</P
><P
>&#13; Besides, this gives a nice opportunity to do a little
<EM
>teergrubing</EM
>.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="helocheck"
></A
>2.3.1. Hello (HELO/EHLO) checks</H2
><P
>&#13; Per RFC 2821, the first SMTP command issued by the client
should be EHLO (or if unsupported, HELO), followed by its
primary, <A
HREF="#fqdn"
><I
CLASS="glossterm"
>Fully Qualified Domain Name</I
></A
>. This is known as the Hello
greeting. If no meaningful FQDN is available, the client can
supply its IP address enclosed in square brackets:
"[1.2.3.4]". This last form is known as an IPv4 address
"literal" notation.
</P
><P
>&#13; Quite understandably, <A
HREF="#ratware"
><I
CLASS="glossterm"
>Ratware</I
></A
> rarely present
their own FQDN in the Hello greeting. Rather, greetings from
ratware usually attempt to conceal the sending host's
identity, and/or to generate confusing and/or misleading
"Received:" trails in the message header. Some examples of
such greetings are:
</P
><P
></P
><UL
><LI
><P
>&#13; Unqualified names (i.e. names without a period), such as
the <SPAN
CLASS="QUOTE"
>"local part"</SPAN
> (username) of the
recipient address.
</P
></LI
><LI
><P
>&#13; A plain IP address (i.e. not an IP literal); usually
yours, but can be a random one.
</P
></LI
><LI
><P
>&#13; Your domain name, or the FQDN of your server.
</P
></LI
><LI
><P
>&#13; Third party domain names, such as
<TT
CLASS="option"
>yahoo.com</TT
> and
<TT
CLASS="option"
>hotmail.com</TT
>.
</P
></LI
><LI
><P
>&#13; Non-existing domain names, or domain names with
non-existing name servers.
</P
></LI
><LI
><P
>&#13; No greeting at all.
</P
></LI
></UL
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="helosyntax"
></A
>2.3.1.1. Simple HELO/EHLO syntax checks</H3
><P
>&#13; Some of these RFC 2821 violations are both easy to check
against, and clear indications that the sending host is
running some form of <A
HREF="#ratware"
><I
CLASS="glossterm"
>Ratware</I
></A
>. You can
reject such greetings -- either right away, or e.g. after
the <B
CLASS="command"
>RCPT TO:</B
> command.
</P
><P
>&#13; First, feel free to reject plain IP addresses in the Hello
greeting. Even if you wish to generously allow everything
RFC 2821 mandates, recommends, and suggests, you will note
that IP addresses should always be enclosed in square
brackets when presented in lieu of a name.
<A
NAME="AEN718"
HREF="#FTN.AEN718"
><SPAN
CLASS="footnote"
>[7]</SPAN
></A
>
</P
><P
>&#13; In particular, you may wish to issue a strongly worded
rejection message to hosts that introduce themselves using
<EM
>your</EM
> IP address - or for that matter,
your host name. They are plainly lying. Perhaps you want
to stall the sender with an exceedingly long SMTP
transaction delay in response to such a greeting; say,
hours.
</P
><P
>&#13; For that matter, my own experience indicates that
<EM
>no</EM
> legitimate sites on the internet
present themselves to other internet sites using an IP
address literal (the [x.y.z.w] notation) either. Nor should
they; all hosts sending mail directly on the internet should
use their valid <A
HREF="#fqdn"
><I
CLASS="glossterm"
>Fully Qualified Domain Name</I
></A
>. The only use of use
of IP literals I have come across is from mail user agents
on my local area network, such as Ximian Evolution,
configured to use my server as outgoing SMTP server
(smarthost). Indeed, I only accept literals from my own
LAN.
</P
><P
>&#13; You may or may not also wish to reject unqualified host
names (host names without a period). I find that these are
rarely (but not never - how's that for double negative
negations) legitimate.
</P
><P
>&#13; Similarly, you can reject host names that contain invalid
characters. For internet domains, only alphanumeric letters
and hyphen are valid characters; a hyphen is not allowed as
the first character. (You may also want to consider the
underscore a valid character, because it is quite common to
see this from misconfigured, but ultimately well-meaning,
Windows clients).
</P
><P
>&#13; Finally, if you receive a <B
CLASS="command"
>MAIL FROM:</B
>
command without first having received a Hello greeting,
well, polite people greet first.
</P
><P
>&#13; On my servers, I reject greetings that fail any of these
syntax checks. However, the rejection does not actually
take place until after the <B
CLASS="command"
>RCPT TO:</B
>
command. In the mean time, I impose a 20 second transaction
delay after each SMTP command (<B
CLASS="command"
>HELO/EHLO</B
>,
<B
CLASS="command"
>MAIL FROM:</B
>, <B
CLASS="command"
>RCPT TO:</B
>).
</P
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="heloverify"
></A
>2.3.1.2. Verifying the Hello greeting via DNS</H3
><P
>&#13; Hosts that make it this far have presented at least a
superficially credible greeting. Now it is time to verify
the provided name via DNS. You can:
</P
><P
></P
><UL
><LI
><P
>&#13; Perform a forward lookup of the provided name, and
match the result against the peer's IP address
</P
></LI
><LI
><P
>&#13; Perform a reverse lookup of the peer's IP address, and
match it against name provided in the greeting.
</P
></LI
></UL
><P
>&#13; If either of these two checks succeeds, the name has been
verified.
</P
><P
>&#13; Your MTA may have a built-in option to perform this check.
For instance, in Exim (see <A
HREF="#exim"
>Appendix A</A
>),
you want to set "helo_try_verify_hosts = *", and create ACLs
that take action based on the "verify = helo" condition.
</P
><P
>&#13; This check is a little more expensive in terms of processing
time and network resources than the simple syntax checks.
Moreover, unlike the syntax checks, a mismatch does not
always indicate ratware; several large internet sites, such
as hotmail.com, yahoo.com, and amazon.com, frequently
present unverifiable Hello greetings.
</P
><P
>&#13; On my servers, I do a DNS validation of the Hello greeting
if I am not already stalling the sender with transaction
delays based on prior checks. Then, if this check fails, I
impose a 20 second delay on every SMTP command from this
point forward. I also prepare a
<SPAN
CLASS="QUOTE"
>"X-HELO-Warning:"</SPAN
> header that I will later add
to the message(s), and use to increase the <A
HREF="#spamassassin"
>SpamAssassin</A
> score for
possible rejection after the message data has been received.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="senderchecks"
></A
>2.3.2. Sender Address Checks</H2
><P
>&#13; After the client has presented the
<B
CLASS="command"
>MAIL FROM:</B
> &#60;<TT
CLASS="parameter"
><I
>address</I
></TT
>&#62;
command, you can validate the supplied
<A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
> address as follows.
<A
NAME="AEN756"
HREF="#FTN.AEN756"
><SPAN
CLASS="footnote"
>[8]</SPAN
></A
>
</P
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="sendersyntax"
></A
>2.3.2.1. Sender Address Syntax Check</H3
><P
>&#13; Does the supplied address conform to the format
&#60;<TT
CLASS="parameter"
><I
>localpart</I
></TT
>@<TT
CLASS="parameter"
><I
>domain</I
></TT
>&#62;?
Is the <TT
CLASS="parameter"
><I
>domain</I
></TT
> part a syntactically
valid <A
HREF="#fqdn"
><I
CLASS="glossterm"
>Fully Qualified Domain Name</I
></A
>?
</P
><P
>&#13; Often, your MTA performs these checks by default.
</P
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="impostor"
></A
>2.3.2.2. Impostor Check</H3
><P
>&#13; In the case where you and your users send all your outgoing
mail only through a select few servers, you can reject
messages from other hosts in which the <SPAN
CLASS="QUOTE"
>"domain"</SPAN
>
of the sender address is your own.
</P
><P
>&#13; A more general alternative to this check is
<A
HREF="#spf"
>Sender Policy Framework</A
>.
</P
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="sendervalid"
></A
>2.3.2.3. Simple Sender Address Validation</H3
><P
>&#13; If the address is local, is the <SPAN
CLASS="QUOTE"
>"local part"</SPAN
>
(the part before the @ sign) a valid mailbox on your
system?
</P
><P
>&#13; If the address is remote, does the <SPAN
CLASS="QUOTE"
>"domain"</SPAN
>
(the part after the @ sign) exist?
</P
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="callback"
></A
>2.3.2.4. Sender Callout Verification</H3
><P
>&#13; This is a mechanism that is offered by some MTAs, such as
Exim and Postfix, to validate the <SPAN
CLASS="QUOTE"
>"local part"</SPAN
>
of a remote sender address. In Postfix terminology, it is
called <SPAN
CLASS="QUOTE"
>"Sender Address Verification"</SPAN
>.
</P
><P
>&#13; Your server contacts the MX for the
<TT
CLASS="parameter"
><I
>domain</I
></TT
> provided in the sender
address, attempting to initiate a secondary SMTP transaction
as if delivering mail to this address. It does not actually
send any mail; rather, once the <B
CLASS="command"
>RCPT TO:</B
>
command has been either accepted or rejected by the remote
host, your server sends <B
CLASS="command"
>QUIT</B
>.
</P
><P
>&#13; By default, Exim uses an empty envelope sender address for
such callout verifications. The goal is to determine if a
<A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
> would be accepted if returned to the
sender.
</P
><P
>&#13; Postfix, on the other hand, defaults to the sender address
&#60;<TT
CLASS="option"
>postmaster@</TT
><TT
CLASS="parameter"
><I
>domain</I
></TT
>&#62;
for address verification purposes
(<TT
CLASS="parameter"
><I
>domain</I
></TT
> is taken from the
<TT
CLASS="option"
>$myorigin</TT
> variable). For this reason, you
may wish to treat this sender address the same way that you
treat the NULL envelope sender (for instance, avoid <A
HREF="#smtpdelays"
>SMTP transaction delays</A
> or <A
HREF="#greylisting"
>Greylisting</A
>, but
require <A
HREF="#signedsender"
>Envelope Sender Signature</A
>s in recipient
addresses). More on this in the implementation appendices.
</P
><P
>&#13; You may find that this check alone may not be suitable as a
trigger to reject incoming mail. Occasionally, legitimate
mail, such as a recurring billing statement, is sent out
from automated services with an invalid return address.
Also, an unfortunate side effect of spam is that some users
tend to mangle the return address in their outgoing mails
(though this may affect the <SPAN
CLASS="QUOTE"
>"From:"</SPAN
> header in
the message itself more often than the <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
>).
</P
><P
>&#13; Moreover, this check only verifies that an address is valid,
not that it was authentic as the sender of this particular
message (but see also <A
HREF="#signedsender"
>Envelope Sender Signature</A
>).
</P
><P
>&#13; Finally, there are reports of sites, such as
<SPAN
CLASS="QUOTE"
>"aol.com"</SPAN
>, that will unconditionally blacklist
any system from which they discover sender callout requests.
These sites may be frequent victims of <A
HREF="#joejob"
><I
CLASS="glossterm"
>Joe Job</I
></A
>s, and as a result, receive storms of
sender callout requests. By taking part in these DDoS
(Distributed Denial-of-Servcie) attacks, you are effectively
turning yourself into a pawn in the hands of the spammer.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="rcptchecks"
></A
>2.3.3. Recipient Address Checks</H2
><P
>&#13; This should be simple, you say. A recipient address is either
valid, in which case the mail is delivered, or invalid, in
which case your MTA takes care of the rejection by default.
</P
><P
>&#13; Let us have a look, shall we?
</P
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="relayprevent"
></A
>2.3.3.1. Open Relay Prevention</H3
><P
>&#13; <EM
>Do not relay mail from remote hosts to remote
addresses!</EM
> (Unless the sender is authenticated).
</P
><P
>&#13; This may seem obvious to most of us, but apparently this is
a frequently overlooked consideration. Also, not everyone
may have a full grasp of the various internet standards
related to e-mail addresses and delivery paths (consider
<SPAN
CLASS="QUOTE"
>"percent hack domains"</SPAN
>, <SPAN
CLASS="QUOTE"
>"bang (!)
paths"</SPAN
>, etc).
</P
><P
>&#13; If you are unsure whether your MTA acts as an an <A
HREF="#openrelay"
><I
CLASS="glossterm"
>Open Relay</I
></A
>, you can test it via
<SPAN
CLASS="QUOTE"
>"relay-test.mail-abuse.org"</SPAN
>.
At a shell prompt on your server, type:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>telnet relay-test.mail-abuse.org</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; This is a service that will use various tests to see whether
your SMTP server appears to forward mail to remote e-mail
addresses, and/or any number of address <SPAN
CLASS="QUOTE"
>"hacks"</SPAN
>
such as the ones mentioned above.
</P
><P
>&#13; Preventing your servers from acting as open relays is
extremely important. If your server is an open relay, and
spammers find you, you will be listed in numerous DNS
blacklists instantly. If the maintainers of certain other
DNS blacklists find you (by probing, and/or by acting on
complaints), you will be listed in those for an extended
period of time.
</P
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="rcptvalid"
></A
>2.3.3.2. Recipient Address Lookups</H3
><P
>&#13; This, too may seem banal to most of us. It is not always so.
</P
><P
>&#13; If your users' mail accounts and mailboxes are stored
directly on your incoming mail exchanger, you can simply
check that the <SPAN
CLASS="QUOTE"
>"local part"</SPAN
> of the recipient
address corresponds to a valid mailbox. No problem here.
</P
><P
>&#13; There are two scenarios where verification of the recipient
address is more cumbersome:
</P
><P
></P
><UL
><LI
><P
>&#13; If your machine is a backup MX for the recipient
domain.
</P
></LI
><LI
><P
>&#13; If your machine forwards all mail for your domain to
another (presumably internal) server.
</P
></LI
></UL
><P
>&#13; The alternative to recipient address verification is to
accept all recipient addresses within these respective
domains, which in turn means that you or the destination
server might have to generate a <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
> for
recipient addresses that later turn out to be invalid.
Ultimately, this means that you would be generating
collateral spam.
</P
><P
>&#13; With that in mind, let us see how we can verify the
recipient in the scenarios listed above.
</P
><DIV
CLASS="section"
><HR><H4
CLASS="section"
><A
NAME="callforward"
></A
>2.3.3.2.1. Recipient Callout Verification</H4
><P
>&#13; This is a mechanism that is offered by some MTAs, such as
Exim and Postfix, to verify the <SPAN
CLASS="QUOTE"
>"local part"</SPAN
>
of a remote recipient address (see <EM
><A
HREF="#callback"
>Sender Callout Verification</A
></EM
> for a description of how
this works). In Postfix terminology, this is called
<SPAN
CLASS="QUOTE"
>"Recipient Address Verification"</SPAN
>.
</P
><P
>&#13; In this case, server attempts to contact the final
destination host to validate each recipient address before
you, in turn, accept the <B
CLASS="command"
>RCPT TO:</B
>
command from your peer.
</P
><P
>&#13; This solution is simple and elegant. It works with any
MTA that might be running on the final destination host,
and without access to any particular directory service.
Moreover, if that MTA happens to perform a fuzzy match on
the recipient address (this is the case with Lotus Domino
servers), this check will accurately reflect whether the
recipient address is eventually going to be accepted or
not - something which may not be true for the mechanisms
described below.
</P
><P
>&#13; Be sure to keep the original <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
>
intact for the recipient callout, or the response from the
destination host may not be accurate. For instance, it
may reject bounces (i.e. mail with no envelope sender) for
system users and aliases, as described in <A
HREF="#dsnrealuser"
>Accept Bounces Only for Real Users</A
>.
</P
><P
>&#13; Among major MTAs, Exim and Postfix support this mechanism.
</P
></DIV
><DIV
CLASS="section"
><HR><H4
CLASS="section"
><A
NAME="ldap"
></A
>2.3.3.2.2. Directory Services</H4
><P
>&#13; Another good solution would be a directory service
(e.g. one or more LDAP servers) that can be queried by
your MTA. The most common MTAs all support LDAP, NIS,
and/or various other backends that are commonly used to
provide user account information.
</P
><P
>&#13; The main sticking point is that unless the final
destination host of the e-mail already uses such a
directory service to map user names to mailboxes, there
may be some work involved in setting this up.
</P
></DIV
><DIV
CLASS="section"
><HR><H4
CLASS="section"
><A
NAME="replicdir"
></A
>2.3.3.2.3. Replicated Mailbox Lists</H4
><P
>&#13; If none of the options above are viable, you could fall
back to a <SPAN
CLASS="QUOTE"
>"poor man's directory service"</SPAN
>,
where you would periodically copy a current list of
mailboxes from the machine where they are located, to your
MX host(s). Your MTA would then consult this list to
validate <B
CLASS="command"
>RCPT TO:</B
> commands in incoming
mail.
</P
><P
>&#13; If the machine(s) that host(s) your mailboxes is/are
running on some flavor of UNIX or Linux, you could write a
script to first generate such a list, perhaps from the
local <SPAN
CLASS="QUOTE"
>"/etc/passwd"</SPAN
> file, and then copy it to
your MX host(s) using the <SPAN
CLASS="QUOTE"
>"scp"</SPAN
> command from
the <A
HREF="http://www.openssh.org/"
TARGET="_top"
>OpenSSH</A
>
suite. You could then set up a <SPAN
CLASS="QUOTE"
>"cron"</SPAN
> job
(type <B
CLASS="command"
>man cron</B
> for details) to
periodically run this script.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="rcptmisses"
></A
>2.3.3.3. Dictionary Attack Prevention</H3
><P
>&#13; <EM
>Dictionary Attack</EM
> is a term used to
describe SMTP transactions where the sending host keeps
issuing <B
CLASS="command"
>RCPT TO:</B
> commands to probe for
possible recipient addresses based on common names (often
alphabetically starting with <SPAN
CLASS="QUOTE"
>"aaron"</SPAN
>, but
sometimes starting later in the alphabet, and/or at random).
If a particular address is accepted by your server, that
address is added into the spammer's arsenal.
</P
><P
>&#13; Some sites, particularly larger ones, find that they are
frequent targets of such attacks. From the spammer's
perspective, chances of finding a given username on a
large site is better than on sites with only a few users.
</P
><P
>&#13; One effective way to combat dictionary attacks is to issue
increasing transaction delays for each failed address. For
instance, the first non-existing recipient address can be
rejected with a 20-second delay, the second address with a
30-second delay, and so on.
</P
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="dsnonercpt"
></A
>2.3.3.4. Accept only one recipient for DSNs</H3
><P
>&#13; Legitimate <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
>s should be sent to only one
recipient address - the originator of the original message
that triggered the notification. You can drop the
connection if the <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
> address is
empty, but there are more than one recipients.
</P
></DIV
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="greylisting"
></A
>2.4. Greylisting</H1
><P
>&#13; The <EM
>greylisting</EM
> concept is presented by
Evan Harris in a whitepaper at:
<A
HREF="http://projects.puremagic.com/greylisting/"
TARGET="_top"
>http://projects.puremagic.com/greylisting/</A
>.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="greylisting-theory"
></A
>2.4.1. How it works</H2
><P
>&#13; Like <A
HREF="#smtpdelays"
>SMTP transaction delays</A
>, greylisting is a simple but
highly effective mechanism to weed out messages that are being
delivered via <A
HREF="#ratware"
><I
CLASS="glossterm"
>Ratware</I
></A
>. The idea is to
establish whether a prior relationship exists between the
sender and the receiver of a message. For most legitimate
mail it does, and the delivery proceeds normally.
</P
><P
>&#13; On the other hand, if no prior relationship exists, the
delivery is temporariliy rejected (with a
<B
CLASS="command"
>451</B
> SMTP response). Legitimate MTAs will
treat this response accordingly, and retry the delivery in a
little while<A
NAME="noretrysenders"
HREF="#FTN.noretrysenders"
><SPAN
CLASS="footnote"
>[9]</SPAN
></A
>. In contrast, ratware will either make repeated
delivery attempts right away, and/or simply give up and move
on to the next target in its address list.
</P
><P
>&#13; Three pieces of information from a delivery attempt, referred
to a as a <EM
>triplet</EM
> are used to uniquely
identify the relationship between a sender and a receiver:
</P
><P
></P
><UL
><LI
><P
>&#13; The <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
>.
</P
></LI
><LI
><P
>&#13; The sending host's IP address.
</P
></LI
><LI
><P
>&#13; The <A
HREF="#envto"
><I
CLASS="glossterm"
>Envelope Recipient</I
></A
>.
</P
></LI
></UL
><P
>&#13; If a delivery attempt was temporarily rejected, this triplet
is cached. It remains greylisted for a given amount of time
(nominally 1 hour), after which it is whitelisted, and new
delivery attempts would succeed. If no new delivery attempts
occur prior to a given timeout (nominally 4 hours), then the
triplet expires from the cache.
</P
><P
>&#13; If a whitelisted triplet has not been seen for an extended
duration (at minimum one month, to account for monthly billing
statements and the like), it is expired. This prevents
unlimited growth of the list.
</P
><P
>&#13; These timeouts are taken from Evan Harris' original
greylisting whitepaper (or should we say, ahem,
<SPAN
CLASS="QUOTE"
>"greypaper"</SPAN
>?) Some people have found that a
larger timeout may be needed before greylisted triplets
expire, because certain ISPs (such as
<EM
>earthlink.net</EM
>) retry deliveries only
every 6 hours or similar.
<A
NAME="AEN914"
HREF="#FTN.AEN914"
><SPAN
CLASS="footnote"
>[10]</SPAN
></A
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="greylisting-multimx"
></A
>2.4.2. Greylisting in Multiple Mail Exchangers</H2
><P
>&#13; If you operate more than one incoming mail exchangers, and
each exchanger maintains its own greylisting cache, then:
</P
><P
></P
><UL
><LI
><P
>&#13; First-time deliveries from a given sender to one of your
users may theoretically be delayed up to
<TT
CLASS="parameter"
><I
>N</I
></TT
> times the initial 1-hour delay,
where <TT
CLASS="parameter"
><I
>N</I
></TT
> is the number of mail
exchangers. This is because the message would likely be
retried at a different server than the one that issued the
<B
CLASS="command"
>451</B
> response to the initial delivery.
In the worst case, the sender host may not get around to
retrying the delivery to the first exchanger for 4 hours,
or until after the greylist triplet has expired, thereby
causing the delivery attempt to be rejected over and over
again, until the sender gives up (usually after 4 days or
so).
</P
><P
>&#13; In practice, this is unlikely. If a delivery attempt
temporarily fails, the sender host normally retries the
delivery immediately, using a different MX. Thus, after
one hour, any of these MX hosts would accept the message.
</P
></LI
><LI
><P
>&#13; Even after a triplet has been whitelisted in one of your
MXs, the next message with the same triplet will be
greylisted if it is delivered to a different MX.
</P
></LI
></UL
><P
>&#13; For these reasons, you may want to implement a solution where
the database of greylist triplets is shared between your
incoming mail exchangers. However, since the machine that
hosts this database would become a single point of failure,
you would have to take a sensible action if that machine is
down (e.g. accept all deliveries). Or you could use database
replication techniques and have the SMTP server fall back to
one of the replicating servers for lookups.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="greylisting-results"
></A
>2.4.3. Results</H2
><P
>&#13; In my own experience, <EM
>greylisting</EM
> gets
rid of about 90% of unique junk mail deliveries,
<EM
>after</EM
> most of the <A
HREF="#smtpchecks"
>SMTP checks</A
> previously described are applied! If
you used greylisting as a first defense, it would likely catch
an even higher percentage of incoming junk mail.
</P
><P
>&#13; Conversely, there are virtually zero <A
HREF="#falsepos"
><I
CLASS="glossterm"
>False Positive</I
></A
>s
resulting from this technique. All major <A
HREF="#mta"
><I
CLASS="glossterm"
>Mail Transport Agent</I
></A
>s
perform delivery retries after a temporary failure, in a manner
that will eventually result in a successful delivery.
</P
><P
>&#13; The downside to greylisting is a legitimate mail from people
who have not e-mailed a particular recipient in the past is
subject to a one-hour delay (or maybe several hours, if you
operate several MX hosts).
</P
><P
>&#13; See also <A
HREF="#qanda-adapt"
><EM
>What happens when
spammers adapt...</EM
></A
>.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="senderauth"
></A
>2.5. Sender Authorization Schemes</H1
><P
>&#13; Various schemes have been developed for sender verification
where not only the validity, but also the authenticity, of
the sender address is checked. The owner of a internet
domain specifies certain criteria that must be fulfilled in
authentic deliveries from senders within that domain.
</P
><P
>&#13; Two early proposed schemes of this kind were:
</P
><P
></P
><UL
><LI
><P
>&#13; <TT
CLASS="option"
>MAIL-FROM</TT
> MX records, conceived by Paul
Vixie <TT
CLASS="email"
>&#60;<A
HREF="mailto:paul (at) vix.com"
>paul (at) vix.com</A
>&#62;</TT
>
</P
></LI
><LI
><P
>&#13; Reverse Mail Exchanger (RMX) records as an addition to DNS
itself, conceived and published by Hadmut Danisch
<TT
CLASS="email"
>&#60;<A
HREF="mailto:hadmut (at) danisch.de"
>hadmut (at) danisch.de</A
>&#62;</TT
>.
</P
></LI
></UL
><P
>&#13; Under both of these schemes, all mails from
<TT
CLASS="email"
>&#60;<A
HREF="mailto:user@domain.com"
>user@domain.com</A
>&#62;</TT
> had to come from the hosts
specified in <TT
CLASS="email"
>&#60;<A
HREF="mailto:domain.com"
>domain.com</A
>&#62;</TT
>'s DNS zone.
</P
><P
>&#13; These schemes have evolved. Alas, they have also forked.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="spf"
></A
>2.5.1. Sender Policy Framework (SPF)</H2
><P
>&#13; <SPAN
CLASS="QUOTE"
>"Server Policy Framework"</SPAN
> (previously
<SPAN
CLASS="QUOTE"
>"Sender Permitted From"</SPAN
>) is perhaps the most
well-known scheme for sender authorization. It is loosely
based on the original schemes described above, but allows
for a bit more flexibility in the criteria that can be
posted by the domain holder.
</P
><P
>&#13; SPF information is published as a <TT
CLASS="option"
>TXT</TT
>
record in a domain's top-level DNS zone. This record can
specify:
</P
><P
></P
><UL
><LI
><P
>&#13; which hosts are allowed to send mail from that domain
</P
></LI
><LI
><P
>&#13; the mandatory presence of a GPG (GNU Privacy Guard)
signature in outgoing mail from the domain
</P
></LI
><LI
><P
>&#13; other criteria; see
<A
HREF="http://spf.pobox.com/"
TARGET="_top"
>http://spf.pobox.com/</A
> for details.
</P
></LI
></UL
><P
>&#13; The structure of the <B
CLASS="command"
>TXT</B
> record is still
undergoing development, however basic features to accomplish
the above are in place. It starts with the string
<TT
CLASS="option"
>v=spf1</TT
>, followed by such modifiers as:
</P
><P
></P
><UL
><LI
><P
>&#13; <TT
CLASS="option"
>a</TT
> - the IP address of
the domain itself is a valid sender host
</P
></LI
><LI
><P
>&#13; <TT
CLASS="option"
>mx</TT
> - the incoming mail exchanger for
that domain is also a valid sender
</P
></LI
><LI
><P
>&#13; <TT
CLASS="option"
>ptr</TT
> - if a rDNS lookup of the
sending host's IP address yields a name within the
domain portion of the sender address, it is a valid
sender.
</P
></LI
></UL
><P
>&#13; Each of these modifiers may be prefixed with a plus sign (+),
minus sign (-), question mark (?), or tilde (~) to indicate
whether it specifies an authorative source, an non-authorative
source, a neutral stance, or a likely non-authorative source,
respectively.
</P
><P
>&#13; Each modifier may also be extended with a colon, followed by
an alternate domain name. For instance, if you are a Comcast
subscriber, your own DNS zone may include the string
<SPAN
CLASS="QUOTE"
>"<TT
CLASS="option"
>-ptr:client.comcast.net
ptr:comcast.net</TT
>"</SPAN
> to indicate that your
outgoing e-mail never comes from a host that resolves to
<TT
CLASS="parameter"
><I
>anything</I
></TT
>.client.comcast.net, but could
come from other hosts that resolve to
<TT
CLASS="parameter"
><I
>anything</I
></TT
><TT
CLASS="option"
>.comcast.net</TT
>.
</P
><P
>&#13; SPF information is currently published for a number of
high-profile internet domains, such as aol.com,
altavista.com, dyndns.org, earthlink.net, and google.com.
</P
><P
>&#13; Sender authorization schemes in general and SPF in particular
are not universally accepted. In particular, one objection is
that domain holders may effectively establish a monopoly on
relaying outgoing mail from their users/customers.
</P
><P
>&#13; Another objection is that SPF breaks traditional e-mail
forwarding - the forwarding host may not have the authority to
do so per the SPF information in the envelope sender domain.
This is partly addressed via <A
HREF="http://spf.pobox.com/srs.html"
TARGET="_top"
>SRS</A
>, or
<EM
>Sender Rewriting Scheme</EM
>, wherein the
forwarder of the mail will modify the <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
> address to the format:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
><TT
CLASS="parameter"
><I
>user</I
></TT
>=<TT
CLASS="parameter"
><I
>source.domain</I
></TT
>@<TT
CLASS="parameter"
><I
>forwarder.domain</I
></TT
></PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="ms-cide"
></A
>2.5.2. Microsoft Caller-ID for E-Mail</H2
><P
>&#13; Similar to SPF, in that acceptance criteria are posted
via a TXT record in the sending domain's DNS zone.
However, rather than relying on simple keywords, MS CIDE
information consists of fairly large structures encoded in
XML. The XML schema is published under a license by
Microsoft.
</P
><P
>&#13; While SPF would nominally be used to check the <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
> address of an e-mail, MS CIDE is
mainly a tool to validate the RFC 2822 header of the
message itself. Thus, the earliest point at which such a
check could be applied would be after the message data has
been delivered, before issuing the final
<B
CLASS="command"
>250</B
> response.
</P
><P
>&#13; Quite frankly, dead on arrival. Encumbered by patent issues
and sheer complexity.
</P
><P
>&#13; That said, Recent SPF tools posted on <A
HREF="http://spf.pobox.com/"
TARGET="_top"
>http://spf.pobox.com/</A
> are capable of checking MS
Caller-ID information in addition to SPF.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="rmxplus"
></A
>2.5.3. RMX++</H2
><P
>&#13; (part of <EM
>Simple Caller Authorization Framework -
SCAF</EM
>). This scheme is developed by Hadmut Danisch,
who also conceived of the original RMX.
</P
><P
>&#13; RMX++ allows for dynamic authorization by way of HTTP servers.
The domain owner publishes a server location via DNS, and the
receiving host contacts that server in order to obtain an
<EM
>authorization record</EM
> to verify the
authenticity of the caller.
</P
><P
>&#13; This scheme allows the domain owner more fine-grained control
of criteria used to authenticate the sender address, without
having to publicly reveal the structure of their network (as
with SPF information in static TXT records). For instance, an
example from Hadmut is an authorization server that allows no
more than five messages from a given address per day after
business hours, then issues an alert once the limit has been
reached.
</P
><P
>&#13; Moreover, SCAF is not limited to e-mail, but can also be used
to provide caller authentication for other services such as
Voice over IP (VoIP).
</P
><P
>&#13; One possible downside with RMX++, as noted by Rick Stewart
<TT
CLASS="email"
>&#60;<A
HREF="mailto:rick.stewart (at) theinternetco.net"
>rick.stewart (at) theinternetco.net</A
>&#62;</TT
>, is its
impact on machine and network resources: Replies from HTTP
servers are not as widely cached as information obtained
directly via DNS, and it is signifcantly more expensive to
make an HTTP request than a DNS request.
</P
><P
>&#13; Further, Rick notes that the dynamic nature of RMX++ makes
faults harder to track. If there is a five-message-per-day
limit, as in the example above, and one message gets checked
five times, then the limit is hit with a single message. It
makes re-checking a message impossible.
</P
><P
>&#13; For more information on RMX, RMX++, and SCAF, refer to: <A
HREF="http://www.danisch.de/work/security/antispam.html"
TARGET="_top"
>http://www.danisch.de/work/security/antispam.html</A
>.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="datachecks"
></A
>2.6. Message data checks</H1
><P
>&#13; Time has come to look at the content of the message itself.
This is what conventional spam and virus scanners do, as they
normally operate on the message after it has been accepted.
However, in our case, we perform these checks
<EM
>before</EM
> issuing the final
<B
CLASS="command"
>250</B
> response, so that we have a chance to
reject the mail on the spot rather than later generating <A
HREF="#colspam"
><I
CLASS="glossterm"
>Collateral Spam</I
></A
>.
</P
><P
>&#13; If your incoming mail exchangers are very busy (i.e. large site,
few machines), you may find that performing some or all of these
checks directly in the mail exchanger is too costly. In
particular, running <A
HREF="#virusscanners"
>Virus Scanners</A
> and <A
HREF="#spamscanners"
>Spam Scanners</A
> do take up a fair amount of CPU
bandwidth and time.
</P
><P
>&#13; If so, you will want to set up dedicated machines for these
scanning operations. Most server-side anti-spam and anti-virus
software can be invoked over the network, i.e. from your mail
exchanger. More on this in the following chapters, where we
discuss implementation for the various MTAs.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="headerchecks"
></A
>2.6.1. Header checks</H2
><DIV
CLASS="section"
><H3
CLASS="section"
><A
NAME="headersmissing"
></A
>2.6.1.1. Missing Header Lines</H3
><P
>&#13; <A
HREF="http://www.ietf.org/rfc/rfc2822.txt"
TARGET="_top"
>RFC
2822</A
> mandates that a message
<EM
>should</EM
> contain at least the following
header lines:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;From: ...
To: ...
Subject: ...
Message-ID: ...
Date: ...
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; The absence of any of these lines means that the message
is not generated by a mainstream <A
HREF="#mua"
><I
CLASS="glossterm"
>Mail User Agent</I
></A
>, and
that it is probably junk
<A
NAME="AEN1045"
HREF="#FTN.AEN1045"
><SPAN
CLASS="footnote"
>[11]</SPAN
></A
>.
</P
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="headersyntax"
></A
>2.6.1.2. Header Address Syntax Check</H3
><P
>&#13; Addresses presented in the message header (i.e. the
<B
CLASS="command"
>To:</B
>, <B
CLASS="command"
>Cc:</B
>,
<B
CLASS="command"
>From:</B
> ... fields) should be syntactically
valid. Enough said.
</P
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="headeraddress"
></A
>2.6.1.3. Simple Header Address Validation</H3
><P
>&#13; For each address in the message header:
</P
><P
></P
><UL
><LI
><P
>&#13; If the address is local, is the <EM
>local
part</EM
> (before the @ sign) a valid mailbox?
</P
></LI
><LI
><P
>&#13; If the address is remote, does the <EM
>domain
part</EM
> (after the @ sign) exist?
</P
></LI
></UL
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="headercallout"
></A
>2.6.1.4. Header Address Callout Verification</H3
><P
>&#13; This works similar to <A
HREF="#callback"
>Sender Callout Verification</A
> and <A
HREF="#callforward"
>Recipient Callout Verification</A
>. Each remote header address is
verified by calling the primary MX for the corresponding
domain to determine if a <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
> would be
accepted.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="jmsr"
></A
>2.6.2. Junk Mail Signature Repositories</H2
><P
>&#13; One trait of junk mail is that it is sent to a large number of
addresses. If 50 other recipients have already flagged a
particular message as spam, why couldn't you use this fact to
decide whether or not to accept the message when it is
delivered to you? Better yet, why not set up <A
HREF="#spamtrap"
><I
CLASS="glossterm"
>Spam Trap</I
></A
>s that feed a public pool of known spam?
</P
><P
>&#13; I am glad you asked. As it turns out, such pools do exist:
</P
><P
></P
><UL
><LI
><P
>&#13; <A
HREF="http://razor.sf.net/"
TARGET="_top"
>Razor</A
>
</P
></LI
><LI
><P
>&#13; <A
HREF="http://pyzor.sf.net/"
TARGET="_top"
>Pyzor</A
>
</P
></LI
><LI
><P
>&#13; <A
HREF="http://rhyolite.com/anti-spam/dcc/"
TARGET="_top"
>Distributed
Checksum Clearinghouse (DCC)</A
>
</P
></LI
></UL
><P
>&#13; These tools have progressed beyond simple signature checks
that only trigger if you receive an identical copy of a
message that is known to be junk mail. Rather, they evaluate
common patterns, to account for slight variations in the
message header and body.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="garbagechars"
></A
>2.6.3. Binary garbage checks</H2
><P
>&#13; Messages containing non-printable characters are rare. When
they do show up, the message is nearly always a virus, or in
some cases spam written in a non-western language, without the
appropriate MIME encoding.
</P
><P
>&#13; One particular case is where the message contains NUL
characters (ordinal zero). Even if you decide that figuring
out what a <EM
>non-printable</EM
> character means
is more complex than beneficial, you might consider checking
for this character. That is because some <A
HREF="#mda"
><I
CLASS="glossterm"
>Mail Delivery Agent</I
></A
>s, such as the <A
HREF="http://asg.web.cmu.edu/cyrus/"
TARGET="_top"
>Cyrus Mail Suite</A
>,
will ultimately reject mails that contain it.
<A
NAME="AEN1096"
HREF="#FTN.AEN1096"
><SPAN
CLASS="footnote"
>[12]</SPAN
></A
>.
If you use such software, you should definitely consider
getting rid of NUL characters.
</P
><P
>&#13; On the other hand, the (now obsolete) RFC 822 specification
did not explicitly prohibit NUL characters in the message.
For this reason, as an alternative to rejecting mails
containing it, you may choose to strip these characters from
the message before delivering it to Cyrus.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="mimeerrors"
></A
>2.6.4. MIME checks</H2
><P
>&#13; Similarly, it might be worthwhile to validate the MIME
structure of incoming message. MIME decoding errors or
inconsistencies do not happen very often; but when they do,
the message is definitely junk. Moreover, such errors may
indicate potential problems in subsequent checks, such as
<A
HREF="#fileext"
>File Attachment Check</A
>s, <A
HREF="#virusscanners"
>Virus Scanners</A
>,
or <A
HREF="#spamscanners"
>Spam Scanners</A
>.
</P
><P
>&#13; In other words, if the MIME encoding is illegal, reject the
message.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="fileext"
></A
>2.6.5. File Attachment Check</H2
><P
>&#13; When was the last time someone sent you a Windows screensaver
(<SPAN
CLASS="QUOTE"
>".scr"</SPAN
> file) or Windows Program Information File
(<SPAN
CLASS="QUOTE"
>".pif"</SPAN
>) that you actually wanted?
</P
><P
>&#13; Consider blocking messages with <SPAN
CLASS="QUOTE"
>"Windows
executable"</SPAN
> file attachment(s) - i.e. file names that
end with a period followed by any of a number of three-letter
combinations such as the above. This check consumes
significantly less resources on your server than <A
HREF="#virusscanners"
>Virus Scanners</A
>, and may also catch new virii for
which a signature does not yet exist in your anti-virus
scanner.
</P
><P
>&#13; For a more-or-less comprehensive list of such <SPAN
CLASS="QUOTE"
>"file name
extensions"</SPAN
>, please visit: <A
HREF="http://support.microsoft.com/default.aspx?scid=kb;EN-US;290497"
TARGET="_top"
>http://support.microsoft.com/default.aspx?scid=kb;EN-US;290497</A
>.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="virusscanners"
></A
>2.6.6. Virus Scanners</H2
><P
>&#13; A number of different server-side virus scanners are
available. To name a few:
</P
><P
></P
><UL
><LI
><P
>&#13; <A
HREF="http://www.vanja.com/tools/sophie/"
TARGET="_top"
>Sophie</A
>
</P
></LI
><LI
><P
>&#13; <A
HREF="http://www.kapersky.com/"
TARGET="_top"
>KAVDaemon</A
>
</P
></LI
><LI
><P
>&#13; <A
HREF="http://clamav.elektrapro.com/"
TARGET="_top"
>ClamAV</A
>
</P
></LI
><LI
><P
>&#13; <A
HREF="http://www.sald.com/"
TARGET="_top"
>DrWeb</A
>
</P
></LI
></UL
><P
>&#13; In situations where you are not willing to block all
potentially dangerous files based on their file names alone
(consider <SPAN
CLASS="QUOTE"
>".zip"</SPAN
> files), such scanners are
helpful. Also, they will be able to catch virii that are
not transmitted as file attachments, such as the
<SPAN
CLASS="QUOTE"
>"Bagle.R"</SPAN
> virus that arrived in March, 2004.
</P
><P
>&#13; In most cases, the machine performing the virus scan does not
need to be your mail exchanger. Most of these anti-virus
scanners can be invoked on a different host over a network
connection.
</P
><P
>&#13; Anti-virus software mainly detect virii based on a set of
signatures for known virii, or <EM
>virus
definitions</EM
>. These need to be updated regularly,
as new virii are developed. Also, the software itself
should at any time be up to date for maximum accuracy.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="spamscanners"
></A
>2.6.7. Spam Scanners</H2
><P
>&#13; Similarly, anti-spam software can be used to classify messages
based on a large set of heuristics, including their content,
standards compliance, and various network checks such as <A
HREF="#dnsbl"
>DNS Blacklists</A
> and <A
HREF="#jmsr"
>Junk Mail Signature Repository</A
>. In the end,
such software typically assigns a composite
<SPAN
CLASS="QUOTE"
>"score"</SPAN
> to each message, indicating the
likelihood that the message is spam, and if the score is above
a certain threshold, would classify it as such.
</P
><P
>&#13; Two of the most popular server-side heuristic anti-spam
filters are:
<P
></P
><UL
><LI
><A
NAME="spamassassin"
></A
><P
>&#13; <A
HREF="http://www.spamassassin.org/"
TARGET="_top"
>SpamAssassin</A
>
</P
></LI
><LI
><A
NAME="brightmail"
></A
><P
>&#13; <A
HREF="http://www.brightmail.com/"
TARGET="_top"
>BrightMail</A
>
</P
></LI
></UL
>
</P
><P
>&#13; These tools undergo a constant evolution as spammers find ways
to circumvent their various checks. For instance, consider
<SPAN
CLASS="QUOTE"
>"creative"</SPAN
> spelling, such as <SPAN
CLASS="QUOTE"
>"GR0W lO
1NCH35"</SPAN
>. So, just like anti-virus software, if you use
anti-spam software, you should update it frequently for the
highest level of accuracy.
</P
><P
>&#13; I use SpamAssassin, although to minimize impact on machine
resources, it is no longer my first line of defense. Out of
approximately 500 junk mail delivery attempts to my personal
address per day, about 50 reach the point where they are being
checked by SpamAssassin (mainly because they are forwarded
from one of my other accounts, so the checks described above
are not effective). Out of these 50 messages, one message
ends up in my inbox approximately every 2 or 3 days.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="collateral"
></A
>2.7. Blocking Collateral Spam</H1
><P
>&#13; <A
HREF="#colspam"
><I
CLASS="glossterm"
>Collateral Spam</I
></A
> is more difficult to block with the
techniques described so far, because it normally arrives from
legitimate sites using standard mail transport software (such as
Sendmail, Postfix, or Exim). The challenge is to distinguish
these messages from valid <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
>s returned in
response to mail sent from your own users. Here are some
ways that people do this:
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="bogusviruswarning"
></A
>2.7.1. Bogus Virus Warning Filter</H2
><P
>&#13; Most of the time, collateral spam is virus warnings generated
by anti-virus scanners<A
NAME="AEN1165"
HREF="#FTN.AEN1165"
><SPAN
CLASS="footnote"
>[13]</SPAN
></A
>. In turn,
the wording in the <TT
CLASS="option"
>Subject:</TT
> line of these
virus warnings, and/or other characteristics, is usually
provided by the anti-virus software itself. As such, you
could create a list of the more common characteristics, and
filter out such bogus virus warnings.
</P
><P
>&#13; Well, aren't you in luck - someone already did this for
you. :-)
</P
><P
>&#13; Tim Jackson <TT
CLASS="email"
>&#60;<A
HREF="mailto:tim (at) timj.co.uk"
>tim (at) timj.co.uk</A
>&#62;</TT
> maintains a
list of bogus virus warnings for use with <A
HREF="#spamassassin"
>SpamAssassin</A
>. This list is
available at:
<A
HREF="http://www.timj.co.uk/linux/bogus-virus-warnings.cf"
TARGET="_top"
>http://www.timj.co.uk/linux/bogus-virus-warnings.cf</A
>.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="addspf"
></A
>2.7.2. Publish SPF info for your domain</H2
><P
>&#13; The purpose of the <A
HREF="#spf"
>Sender Policy Framework</A
> is precisely to
protect against <A
HREF="#joejob"
><I
CLASS="glossterm"
>Joe Job</I
></A
>s; i.e. to prevent
forgeries of valid e-mail addresses.
</P
><P
>&#13; If you publish SPF records in the DNS zone for your domain,
then recipient hosts that incorporate SPF checks would not
have accepted the forged message in the first place. As such,
they would not be sending a <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
> to your
site.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="signedsender"
></A
>2.7.3. Enveloper Sender Signature</H2
><P
>&#13; A different approach that I am currently experimenting with
myself is to add a signature in the local part of the <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
> address in outgoing mail, then check for
this signature in the <A
HREF="#envto"
><I
CLASS="glossterm"
>Envelope Recipient</I
></A
> address before
accepting incoming <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
>s. For instance, the
generated sender address might be of the following format:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
><TT
CLASS="parameter"
><I
>localpart</I
></TT
>=<TT
CLASS="parameter"
><I
>signature</I
></TT
>@<TT
CLASS="parameter"
><I
>domain</I
></TT
></PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Normal message replies are unaffected. These replies go to
the address in the <TT
CLASS="option"
>From:</TT
> or
<TT
CLASS="option"
>Reply-To:</TT
> field of the message, which are
left intact.
</P
><P
>&#13; Sounds easy, doesn't it? Unfortunately, generating a
signature that is suitable for this purpose is a bit more
complex than it sounds. There are a couple of conflicting
considerations to take into account:
</P
><P
></P
><UL
><LI
><P
>&#13; To gain any benefit from this method, the signed envelope
sender address that you generate should be useless in the
hands of spammers. Typically, this would imply that the
signature incorporates a time stamp that would eventually
expire:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
><TT
CLASS="parameter"
><I
>sender</I
></TT
>=<TT
CLASS="parameter"
><I
>timestamp</I
></TT
>=<TT
CLASS="parameter"
><I
>hash</I
></TT
>@<TT
CLASS="parameter"
><I
>domain</I
></TT
></PRE
></FONT
></TD
></TR
></TABLE
>
</P
></LI
><LI
><P
>&#13; If you send mail to a site that incorporates <A
HREF="#greylisting"
>Greylisting</A
>, your envelope sender address
should remain constant for that particular recipient.
Otherwise, your mail will continuously be greylisted.
</P
><P
>&#13; With this in mind, you could generate a <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
> based on the <A
HREF="#envto"
><I
CLASS="glossterm"
>Envelope Recipient</I
></A
>
address:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
><TT
CLASS="parameter"
><I
>sender</I
></TT
>=<TT
CLASS="parameter"
><I
>recipient</I
></TT
>=<TT
CLASS="parameter"
><I
>recipient.domain</I
></TT
>=<TT
CLASS="parameter"
><I
>hash</I
></TT
>@<TT
CLASS="parameter"
><I
>domain</I
></TT
></PRE
></FONT
></TD
></TR
></TABLE
>
Although this address does not expire, if you start seeing
junk mail to it, you will at least know the source of the
leak - it is incorported in the recipient address.
Moreover, you can easily block specific recipient address
signatures, without affecting normal mail delivery to that
same recipient.
</P
></LI
><LI
><P
>&#13; Two more issues occur with mailing list servers. Usually,
replies to request mails (such as
<SPAN
CLASS="QUOTE"
>"subscribe"</SPAN
>/<SPAN
CLASS="QUOTE"
>"unsubscribe"</SPAN
>) are
sent with no envelope sender.
</P
><P
></P
><UL
><LI
><P
>&#13; The first issue pertains to servers that send
responses back to the <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
>
address of the request mail (as in the case of
<TT
CLASS="email"
>&#60;<A
HREF="mailto:discuss@en.tldp.org"
>discuss@en.tldp.org</A
>&#62;</TT
>). The problem is
that commands for the mailing list server (such as
<B
CLASS="command"
>subscribe</B
> or
<B
CLASS="command"
>unsubscribe</B
>) are typically sent to
one or more different addresses
(e.g. <TT
CLASS="email"
>&#60;<A
HREF="mailto:discuss-subscribe@en.tldp.org"
>discuss-subscribe@en.tldp.org</A
>&#62;</TT
> and
<TT
CLASS="email"
>&#60;<A
HREF="mailto:discuss-unsubscribe@en.tldp.org"
>discuss-unsubscribe@en.tldp.org</A
>&#62;</TT
>,
respectively) than the address used for list mail.
Hence, the subscriber address will be different from
the sender address in messages sent to the list itself
-- and in this example, also different from the
address that will be generated for unsubscription
requests. As a result, you may not be able to post to
the list, or unsubscribe.
</P
><P
>&#13; The compromise would be to incorporate only the
recipient <EM
>domain</EM
> in the sender
signature. The sender address might then look like:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
><TT
CLASS="parameter"
><I
>subscribername</I
></TT
>=en.tldp.org=<TT
CLASS="parameter"
><I
>hash</I
></TT
>@<TT
CLASS="parameter"
><I
>subscriber.domain</I
></TT
></PRE
></FONT
></TD
></TR
></TABLE
>
</P
></LI
><LI
><P
>&#13; The second issue pertains to those that send responses
back to the reply address in the message header of the
request mail (such as
<TT
CLASS="email"
>&#60;<A
HREF="mailto:spam-l-request@peach.ease.lsoft.com"
>spam-l-request@peach.ease.lsoft.com</A
>&#62;</TT
>).
Since this address is not signed, the response from
the list server would be blocked by your server.
</P
><P
>&#13; There is not much you can do about this, other than to
<SPAN
CLASS="QUOTE"
>"whitelist"</SPAN
> these particular servers in
such a way that they are allowed to return mail to
unsigned recipient addresses.
</P
></LI
></UL
></LI
></UL
><P
>&#13; At this point, this approach starts losing some of its edge.
Moreover, even legitimate DSNs are rejected unless the
original mail has been sent via your server. Thus, you should
only consider doing this if for those of your users that do
not roam, or otherwise send their outgoing mail via servers
outside your control.
</P
><P
>&#13; That said, in situations where none of the above concerns
apply to you, this method gives you a good way to not only
eliminate collateral spam, but also a way to educate the
owners of the sites that (presumably unwittingly) generate it.
Moreover, as a side benefit, sites that perform <A
HREF="#callback"
>Sender Callout Verification</A
> will only get a positive response from
you if the original mail was, indeed, sent from your site. In
essence, you are reducing your exposure to sender address
forgeries by spammers.
</P
><P
>&#13; You could perhaps allow your users to specify whether to sign
outgoing mails, and if so, specify which hosts should be
allowed to return mails to the unsigned version of their
address. For instance, if they have system accounts on your
mail server, you could check for the existence and content,
respectively, of a given file in their home directory.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="dsnrealuser"
></A
>2.7.4. Accept Bounces Only for Real Users</H2
><P
>&#13; Even if you check for envelope sender signatures, there may be
a loophole that allows bogus bounces to be accepted.
Specifically, if your users have to opt in to the scheme, you
are probably not checking for this signature in mails sent to
system aliases, such as <TT
CLASS="option"
>postmaster</TT
> or
<TT
CLASS="option"
>mailer-daemon</TT
>. Moreover, since these users
do not generate outgoing mail, they should not receive any
bounces.
</P
><P
>&#13; You can reject mail if it is sent to such system aliases, or
alternatively, if there is no mailbox for the provided
recipient address.
</P
></DIV
></DIV
></DIV
><DIV
CLASS="chapter"
><HR><H1
><A
NAME="considerations"
></A
>Chapter 3. Considerations</H1
><BLOCKQUOTE
CLASS="ABSTRACT"
><DIV
CLASS="abstract"
><A
NAME="AEN1250"
></A
><P
></P
><P
>&#13; Some specific considerations come into play as a result of
system-wide SMTP time filtering. Here we cover some of those.
</P
><P
></P
></DIV
></BLOCKQUOTE
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="multimx"
></A
>3.1. Multiple Incoming Mail Exchangers</H1
><P
>&#13; Most domains list more than one incoming <A
HREF="#mx"
><I
CLASS="glossterm"
>Mail Exchanger</I
></A
>s
(a.k.a. <SPAN
CLASS="QUOTE"
>"MX hosts"</SPAN
>). If you do so, then bear in
mind that in order to have any effect, any SMTP time filtering
you incorporate on the primary MX has to be incorporated on all
the others as well. Otherwise, the sending host would simply
sidestep filtering by retrying the mail delivery through your
backup server(s).
</P
><P
>&#13; If the backup server(s) are not under your control, ask
yourself whether you need multiple MXs in the first place. In
this situation, chances are that they serve only as
<EM
>redundant</EM
> mail servers, and that they in
turn forward the mail to your primary MX. If so, you probably
don't need them. If your host happens to be down for a little
while, that's OK -- well-behaved sender hosts will retry
deliveries for several days before giving up
<A
HREF="#FTN.noretrysenders"
><SPAN
CLASS="footnote"
>[9]</SPAN
></A
>.
</P
><P
>&#13; A situation where you <EM
>may</EM
> need multiple
MXs is to perform load balancing between several servers -
i.e. if you receive so much mail that one machine alone could
not handle it. In this case, see if you could offload some
tasks (such as <A
HREF="#virusscanners"
>virus</A
> and
<A
HREF="#spamscanners"
>spam</A
> scanners) to other
machines, in order to reduce or eliminate this need.
</P
><P
>&#13; Again, if you do decide to keep using several MXs, your backup
servers need to be (at least) as restrictive as the primary
server, lest filtering in the primary MX is useless.
</P
><P
>&#13; See also the section on <A
HREF="#greylisting"
>Greylisting</A
> for
additional concerns related to multiple MX hosts.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="otherservers"
></A
>3.2. Blocking Access to Other SMTP Servers</H1
><P
>&#13; Any SMTP server that is not listed as a public <A
HREF="#mx"
><I
CLASS="glossterm"
>Mail Exchanger</I
></A
> in the DNS zone of your domain(s) should not
accept incoming connections from the internet. All incoming
mail traffic should go through your incoming mail exchanger(s).
</P
><P
>&#13; This consideration is not unique to SMTP servers. If you have
machines that only serve an internal purpose within your site,
use a firewall to restrict access to these.
</P
><P
>&#13; This is a rule, so therefore there must be exceptions. However,
if you don't know what they are, then the above applies to you.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="forwardedmail"
></A
>3.3. Forwarded Mail</H1
><P
>&#13; You should take care not to reject mail as a result of spam
filtering if it is forwarded from <SPAN
CLASS="QUOTE"
>"friendly"</SPAN
>
sources, such as:
</P
><P
></P
><UL
><LI
><P
>&#13; Your backup MX hosts, if any. Supposedly, these have
already filtered out most of the junk (see <A
HREF="#multimx"
>Multiple Incoming Mail Exchangers</A
>).
</P
></LI
><LI
><P
>&#13; Mailing lists, to which you or your users subscribe. You may
still filter such mail (it may not be as criticial if it
ends up in a black hole). However, if you reject the mail,
you may end up causing the list server to automatically
unsubscribe the recipient.
</P
></LI
><LI
><P
>&#13; Other accounts belonging to the recipient. Again,
rejections will generate collateral spam, and/or create
problems for the host that forwards the mail.
</P
></LI
></UL
><P
>&#13; You may see a logistical issue with the last two of these
sources: They are specific to each recipient. How to you allow
each user to specify which hosts they want to whitelist, and
then use such individual whitelists in a system-wide SMTP-time
filtering setup? If the message is forwarded to several
recipients at your site (as may often be true in the case of
a mailing list), how do you decide whose whitelist to use?
</P
><P
>&#13; There is no magic bullet here. This is one of those situations
where we just have to do a bit of work. You can decide to
accept all mails, regardless of spam classification, so long as
it is sent from a host in the whitelist of any one of the
recipients. For instance, in response to each <B
CLASS="command"
>RCPT
TO:</B
> command, we can match the sending host against the
corresponding user's whitelist. If found, set a flag that will
prevent a subsequent rejection. Effectively, you are using an
<EM
>aggregate</EM
> of each recipient's whitelist.
</P
><P
>&#13; The implementation appendices cover this in more detail.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="usersettings"
></A
>3.4. User Settings and Data</H1
><P
>&#13; There are other situations where you may want to support
settings and data for each user at site. For instance, if you
scan incoming mail with SpamAssassin (see <A
HREF="#spamscanners"
>Spam Scanners</A
>), you may want to allow for individual
spam thresholds, acceptable languages and character sets, and
Bayesian training/data.
</P
><P
>&#13; A sticking point is that SMTP-time filtering of incoming mail is
done at the system level, before mail is being delivered to a
particular user, and as such, does not lend itself too well to
individual preferences. A single message may have several
recipients; and unlike the case with <A
HREF="#forwardedmail"
>Forwarded Mail</A
>, using an aggregate of each
recipient's preferences is not a good option. Consider a
scenario where you have users from different linguistic
backgrounds.
</P
><P
>&#13; As it turns out, though, there is a modification to this truth.
The trick is to limit the number of recipients in incoming
messages to one, so that the message can be analyzed in
accordance with the settings and data that belongs to the
corresponding user.
</P
><P
>&#13; To do this, you would accept the first <B
CLASS="command"
>RCPT
TO:</B
>, then issue a SMTP <B
CLASS="command"
>451</B
> (defer)
response to subsequent commands. If the caller is a
well-behaved MTA, it will know how to interpret this response,
and try later. (If it is confused, then, well, it is probably a
sender from which you don't want to receive mail in the first
place).
</P
><P
>&#13; Obviously, this is a hack. Every mail sent to several users at
your site will be slowed down by 30 minutes or more per
recipient. Especially in corporate environments, where it is
common to see e-mail discussions involving several people on the
inside and several others on the outside, and where timelines of
mail deliveries are essential, this is probably not a good
solution at all.
</P
><P
>&#13; Another issue that mainly pertains to corporate enterprises and
other large sites is that incoming mail is often forwarded to
internal machines for delivery, and that recipients don't
normally have accounts on the mail exchanger. It may still be
possible to support user-specific settings and data in these
situations (e.g. via database lookups or LDAP queries), but you
may also want to consider whether it's worth the effort.
</P
><P
>&#13; That said, if you are on a small site, and where you are not
afraid of delayed deliveries, this may be an acceptable way
to allow each user to fine tune their filtering criteria.
</P
></DIV
></DIV
><DIV
CLASS="chapter"
><HR><H1
><A
NAME="qanda"
></A
>Chapter 4. Questions &#38; Answers</H1
><BLOCKQUOTE
CLASS="ABSTRACT"
><DIV
CLASS="abstract"
><A
NAME="AEN1305"
></A
><P
></P
><P
>&#13; In this section I try to anticipate some of the questions that
may come up, and to answer them. If you have questions that are
not listed, and/or would like to provide extra input in this
section, please provide <A
HREF="#feedback"
>feedback</A
>.
</P
><P
></P
></DIV
></BLOCKQUOTE
><DIV
CLASS="qandaset"
><H2
CLASS="title"
>When Spammers Adapt</H2
><DL
><DT
>Q: <A
HREF="#AEN1311"
>&#13; What happens when spammers adapt and try to get around the
techniques described in this document?
</A
></DT
></DL
><DIV
CLASS="qandaentry"
><DIV
CLASS="question"
><P
><A
NAME="AEN1311"
></A
><B
>Q: </B
>
What happens when spammers adapt and try to get around the
techniques described in this document?
</P
></DIV
><DIV
CLASS="answer"
><P
><B
>A: </B
>
Well, that depends. :-)
</P
><P
>&#13; Some of the checks described (such as <A
HREF="#smtpchecks"
>SMTP checks</A
> and <A
HREF="#greylisting"
>Greylisting</A
>)
specifically target <EM
>ratware</EM
> behavior.
It is certainly possible to imagine that this behavior will
change if enough sites incorporate these checks. Hatmut
Danisch notes:
<EM
>&#13; Ratware contains buggy SMTP protocols because they didn't
need to do any better. It worked this way, so why should
they have spent more time? Meanwhile
<SPAN
CLASS="QUOTE"
>"ratware"</SPAN
> has a higher quality, and even the
quality of spam messages has significantly improved. Once
enough people reject spam by detecting bad SMTP protocols,
spam software authors will simply improve their
software.
</EM
>
</P
><P
>&#13; That said, there are challenges remaining for such ratware:
</P
><P
></P
><UL
><LI
><P
>&#13; To get around <A
HREF="#smtpdelays"
>SMTP transaction delays</A
>, they need to
wait for each response from the receiving SMTP server.
At that point, we have collectively accomplished a
significant reduction in the rate of mail that a given
spamming host is able to deliver per unit of time.
Since spammers are racing against time to deliver as
many mails as possible before DNS blocklists and
collaborative content filters catch up, we are improving
the effectiveness of these tools.
</P
><P
>&#13; The effect is similar to the goal of <A
HREF="#micropay"
><I
CLASS="glossterm"
>Micropayment Schemes</I
></A
>, wherein the sender spends a few
seconds working on a computational challenge for each
recipient of the mail, and adds a resulting signature to
the e-mail header for the recipient to validate. The
main difference, aside from the complexity of these
schemes, is that they require the participation of
virtually everyone in the world before they can
effectively be used to weed out spam, whereas SMTP
transaction delays start being effective with the first
recipient machine that implements it.
</P
></LI
><LI
><P
>&#13; To get around a <A
HREF="#helocheck"
>HELO/EHLO check</A
>, they need
to provide a proper greeting, i.e. identify themselves
with a valid <A
HREF="#fqdn"
><I
CLASS="glossterm"
>Fully Qualified Domain Name</I
></A
>. This provides for
increased traceability, especially with receiving <A
HREF="#mta"
><I
CLASS="glossterm"
>Mail Transport Agent</I
></A
>s that do not automatically insert the
results of a rDNS lookup into the Received: header of
the message.
</P
></LI
><LI
><P
>&#13; To get all of the <A
HREF="#senderchecks"
>Sender Address Checks</A
>, they
need to provide their own valid sender address (or, at
least, <EM
>a</EM
> valid sender address
within their own domain). Nuff said.
</P
></LI
><LI
><P
>&#13; To get around <A
HREF="#greylisting"
>Greylisting</A
>, they need
to retry deliveries to temporarily failed recipients
addresses after one hour (but before four hours). (As
far as implementation goes, in order to minimize machine
resources, rather than keeping a copy of each
temporarily failed mail, ratware may keep only a list of
temporarily failed recipients, and perform a second
sweep through those addresses after an hour or two).
</P
><P
>&#13; Even so, <EM
>greylisting</EM
> will remain
fairly effective in conjunction with <A
HREF="#dnsbl"
>DNS Blacklists</A
> that are fed from <A
HREF="#spamtrap"
><I
CLASS="glossterm"
>Spam Trap</I
></A
>s. That is because the mandatory
one-hour retry delay will give these lists a chance to
list the sending host.
</P
></LI
></UL
><P
>&#13; Software tools, such as <A
HREF="#spamscanners"
>Spam Scanners</A
> and
<A
HREF="#virusscanners"
>Virus Scanners</A
>, are in constant evolution.
As spammers evolve, so do these (and vice versa). As long
as you use recent versions of these tools, they will remain
quite effective.
</P
><P
>&#13; Finally, this document is itself subject to change. As the
nature of junk mail changes, people will come up with new,
creative ways to block it.
</P
></DIV
></DIV
></DIV
></DIV
><DIV
CLASS="appendix"
><HR><H1
><A
NAME="exim"
></A
>Appendix A. Exim Implementation</H1
><BLOCKQUOTE
CLASS="ABSTRACT"
><DIV
CLASS="abstract"
><A
NAME="AEN1350"
></A
><P
></P
><P
>&#13; Here we cover the integration of techniques and tools described
in this document into the Exim <A
HREF="#mta"
><I
CLASS="glossterm"
>Mail Transport Agent</I
></A
>.
</P
><P
></P
></DIV
></BLOCKQUOTE
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-prereq"
></A
>A.1. Prerequisites</H1
><P
>&#13; For these examples, you need the <TT
CLASS="option"
>Exim</TT
> <A
HREF="#mta"
><I
CLASS="glossterm"
>Mail Transport Agent</I
></A
>, preferrably with Tom Kistner's
<TT
CLASS="option"
>Exiscan-ACL</TT
> patch applied. Prebuilt
<TT
CLASS="option"
>Exim+Exiscan-ACL</TT
> packages exist for the most
popular Linux distributions as well as FreeBSD; see the <A
HREF="http://duncanthrax.net/exiscan-acl/"
TARGET="_top"
>Exiscan-ACL</A
>
home page for details<A
NAME="AEN1361"
HREF="#FTN.AEN1361"
><SPAN
CLASS="footnote"
>[14]</SPAN
></A
>.
</P
><P
>&#13; The final implementation example at the end incorporates these
additional tools:
</P
><P
></P
><UL
><LI
><P
>&#13; <A
HREF="http://www.spamassassin.org/"
TARGET="_top"
>SpamAssassin</A
>
- a popular spam filtering tool that analyzes mail content
against a large and highly sophisticated set of
heuristics.
</P
></LI
><LI
><P
>&#13; <A
HREF="http://packages.debian.org/unstable/mail/greylistd"
TARGET="_top"
>greylistd</A
>
- a simple greylisting solution written by yours truly,
specifically with Exim in mind.
</P
></LI
></UL
><P
>&#13; Other optional software is used in examples throughout.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-configfile"
></A
>A.2. The Exim Configuration File</H1
><P
>&#13; The Exim configuration file contains global definitions at the
top (we will call this the <EM
>main section</EM
>),
followed by several other sections<A
NAME="AEN1380"
HREF="#FTN.AEN1380"
><SPAN
CLASS="footnote"
>[15]</SPAN
></A
>. Each of these other sections starts with:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>begin <TT
CLASS="parameter"
><I
>section</I
></TT
></PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; We will spend most of our time in the <TT
CLASS="option"
>acl</TT
>
section (i.e. after <TT
CLASS="option"
>begin acl</TT
>); but we will
also add and/or modify a few items in the
<TT
CLASS="option"
>transports</TT
> and <TT
CLASS="option"
>routers</TT
>
sections, as well as in the main section at the top of the file.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-acl"
></A
>A.2.1. Access Control Lists</H2
><P
>&#13; As of version 4.xx, Exim incorporates perhaps the most
sophisticated and flexible mechanism for SMTP-time filtering
available anywhere, by way of so-called <EM
>Access
Control Lists</EM
> (ACLs).
</P
><P
>&#13; An ACL can be used to evaluate whether to accept or reject an
aspect of an incoming message transaction, such as the initial
connection from a remote host, or the
<B
CLASS="command"
>HELO/EHLO</B
>, <B
CLASS="command"
>MAIL FROM:</B
>,
or <B
CLASS="command"
>RCPT TO:</B
> SMTP commands. So, for
instance, you may have an ACL named
<TT
CLASS="option"
>acl_rcpt_to</TT
> to validate each <B
CLASS="command"
>RCPT
TO:</B
> command received from the peer.
</P
><P
>&#13; An ACL consists of a series of <EM
>statements</EM
>
(or <EM
>rules</EM
>). Each statement starts with
an action verb, such as <TT
CLASS="option"
>accept</TT
>,
<TT
CLASS="option"
>warn</TT
>, <TT
CLASS="option"
>require</TT
>,
<TT
CLASS="option"
>defer</TT
>, or <TT
CLASS="option"
>deny</TT
>, followed by
a list of conditions, options, and other settings pertaining
to that statement. Every <EM
>statement</EM
> is
evaluated in order, until a definitive action (besides
<TT
CLASS="option"
>warn</TT
>) is taken. There is an implicit
<TT
CLASS="option"
>deny</TT
> at the end of the ACL.
</P
><P
>&#13; A sample statement in the <TT
CLASS="option"
>acl_rcpt_to</TT
> ACL
above may look like this:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; deny
message = relay not permitted
!hosts = +relay_from_hosts
!domains = +local_domains : +relay_to_domains
delay = 1m
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; This statement will reject the <B
CLASS="command"
>RCPT TO:</B
>
command if it was not delivered by a host in the
<SPAN
CLASS="QUOTE"
>"+relay_from_hosts"</SPAN
> host list, and the recipient
domain is not in the <SPAN
CLASS="QUOTE"
>"+local_domains"</SPAN
> or
<SPAN
CLASS="QUOTE"
>"+relay_to_domains"</SPAN
> domain lists. However, before
issuing the <SPAN
CLASS="QUOTE"
>"550"</SPAN
> SMTP response to this command,
the server will wait for one minute.
</P
><P
>&#13; To evaluate a particular ACL at a given stage of the message
transaction, you need to point one of Exim's <EM
>policy
controls</EM
> to that ACL. For instance, to use the
<TT
CLASS="option"
>acl_rcpt_to</TT
> ACL mentioned above to evaluate the
<B
CLASS="command"
>RCPT TO:</B
>, the main section of your Exim
configuration file (before any <TT
CLASS="option"
>begin</TT
> keywords)
should include:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>acl_smtp_rcpt = acl_rcpt_to</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; For a full list of such <EM
>policy controls</EM
>,
refer to section 14.11 in the Exim specifications.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-expansions"
></A
>A.2.2. Expansions</H2
><P
>&#13; A large number of <EM
>expansion items</EM
> are
available, including run-time variables, lookup functions,
string/regex manipulations, host/domain lists, etc. etc. An
exhaustive reference for the last x.x0 release (i.e. 4.20,
4.30..) can be found in the file <SPAN
CLASS="QUOTE"
>"spec.txt"</SPAN
>; ACLs
are described in section 38.
</P
><P
>&#13; In particular, Exim provides twenty general purpose expansion
variables to which we can assign values in an ACL statement:
</P
><P
></P
><UL
><LI
><P
>&#13; <TT
CLASS="varname"
>$acl_c0</TT
> - <TT
CLASS="varname"
>$acl_c9</TT
> can
hold values that will persist through the lifetime of an
SMTP connection.
</P
></LI
><LI
><P
>&#13; <TT
CLASS="varname"
>$acl_m0</TT
> - <TT
CLASS="varname"
>$acl_m9</TT
> can
hold values while a message is being received, but are
then reset. They are also reset by the
<B
CLASS="command"
>HELO</B
>, <B
CLASS="command"
>EHLO</B
>,
<B
CLASS="command"
>MAIL</B
>, and <B
CLASS="command"
>RSET</B
>
commands.
</P
></LI
></UL
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-options"
></A
>A.3. Options and Settings</H1
><P
>&#13; The main section of the Exim configuration file (before the
first <TT
CLASS="option"
>begin</TT
> keyword) contains various macros,
policy controls, and other general settings. Let us start by
defining a couple of macros we will use later:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# Define the message size limit; we will use this in the DATA ACL.
MESSAGE_SIZE_LIMIT = 10M
# Maximum message size for which we will run Spam or Virus scanning.
# This is to reduce the load imposed on the server by very large messages.
MESSAGE_SIZE_SPAM_MAX = 1M
# Macro defining a secret that we will use to generate various hashes.
# PLEASE CHANGE THIS!.
SECRET = <TT
CLASS="parameter"
><I
>some-secret</I
></TT
>
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Let us tweak some general Exim settings:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# Treat DNS failures (SERVFAIL) as lookup failures.
# This is so that we can later reject sender addresses
# within non-existing domains, or domains for which no
# nameserver exists.
dns_again_means_nonexist = !+local_domains : !+relay_to_domains
# Enable HELO verification in ACLs for all hosts
helo_try_verify_hosts = *
# Remove any limitation on the maximum number of incoming
# connections we can serve at one time. This is so that while
# we later impose SMTP transaction delays for spammers, we
# will not refuse to serve new connections.
smtp_accept_max = 0
# ..unless the system load is above 10
smtp_load_reserve = 10
# Do not advertise ESMTP "PIPELINING" to any hosts.
# This is to trip up ratware, which often tries to pipeline
# commands anyway.
pipelining_advertise_hosts = :
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Finally, we will point some Exim policy controls to five ACLs
that we will create to evaluate the various stages of an
incoming SMTP transaction:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;acl_smtp_connect = acl_connect
acl_smtp_helo = acl_helo
acl_smtp_mail = acl_mail_from
acl_smtp_rcpt = acl_rcpt_to
acl_smtp_data = acl_data
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-firstpass"
></A
>A.4. Building the ACLs - First Pass</H1
><P
>&#13; In the acl section (following <TT
CLASS="option"
>begin acl</TT
>), we
need to define these ACLs. In doing so, we will incorporate
some of the basic
<EM
><A
HREF="#techniques"
>Techniques</A
></EM
>
described earlier in this document, namely
<EM
><A
HREF="#dnschecks"
>DNS checks</A
></EM
> and
<EM
><A
HREF="#smtpchecks"
>SMTP checks</A
></EM
>.
</P
><P
>&#13; In this pass, we will do most of the checks in <A
HREF="#acl_rcpt_to_1"
>acl_rcpt_to</A
>, and leave the other ACLs largely
empty. That is because most of the commonly used ratware does
not understand rejections early in the SMTP transaction - it
keeps trying. On the other hand, most ratware clients give up
if the <B
CLASS="command"
>RCPT TO:</B
> fails.
</P
><P
>&#13; We create all these ACLs, however, because we will use them
later.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="acl_connect_1"
></A
>A.4.1. acl_connect</H2
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# This access control list is used at the start of an incoming
# connection. The tests are run in order until the connection
# is either accepted or denied.
acl_connect:
# In this pass, we do not perform any checks here.
accept
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="acl_helo_1"
></A
>A.4.2. acl_helo</H2
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# This access control list is used for the HELO or EHLO command in
# an incoming SMTP transaction. The tests are run in order until the
# greeting is either accepted or denied.
acl_helo:
# In this pass, we do not perform any checks here.
accept
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="acl_mail_from_1"
></A
>A.4.3. acl_mail_from</H2
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# This access control list is used for the MAIL FROM: command in an
# incoming SMTP transaction. The tests are run in order until the
# sender address is either accepted or denied.
#
acl_mail_from:
# Accept the command.
accept
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="acl_rcpt_to_1"
></A
>A.4.4. acl_rcpt_to</H2
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# This access control list is used for every RCPT command in an
# incoming SMTP message. The tests are run in order until the
# recipient address is either accepted or denied.
acl_rcpt_to:
# Accept mail received over local SMTP (i.e. not over TCP/IP).
# We do this by testing for an empty sending host field.
# Also accept mails received from hosts for which we relay mail.
#
# Recipient verification is omitted here, because in many
# cases the clients are dumb MUAs that don't cope well with
# SMTP error responses.
#
accept
hosts = : +relay_from_hosts
# Accept if the message arrived over an authenticated connection,
# from any host. Again, these messages are usually from MUAs, so
# recipient verification is omitted.
#
accept
authenticated = *
######################################################################
# DNS checks
######################################################################
#
# The results of these checks are cached, so multiple recipients
# does not translate into multiple DNS lookups.
#
# If the connecting host is in one of a select few DNSbls, then
# reject the message. Be careful when selecting these lists; many
# would cause a large number of false postives, and/or have no
# clear removal policy.
#
deny
dnslists = dnsbl.sorbs.net : \
dnsbl.njabl.org : \
cbl.abuseat.org : \
bl.spamcop.net
message = $sender_host_address is listed in $dnslist_domain\
${if def:dnslist_text { ($dnslist_text)}}
# If reverse DNS lookup of the sender's host fails (i.e. there is
# no rDNS entry, or a forward lookup of the resulting name does not
# match the original IP address), then reject the message.
#
deny
message = Reverse DNS lookup failed for host $sender_host_address.
!verify = reverse_host_lookup
######################################################################
# Hello checks
######################################################################
# If the remote host greets with an IP address, then reject the mail.
#
deny
message = Message was delivered by ratware
log_message = remote host used IP address in HELO/EHLO greeting
condition = ${if isip {$sender_helo_name}{true}{false}}
# Likewise if the peer greets with one of our own names
#
deny
message = Message was delivered by ratware
log_message = remote host used our name in HELO/EHLO greeting.
condition = ${if match_domain{$sender_helo_name}\
{$primary_hostname:+local_domains:+relay_to_domains}\
{true}{false}}
deny
message = Message was delivered by ratware
log_message = remote host did not present HELO/EHLO greeting.
condition = ${if def:sender_helo_name {false}{true}}
# If HELO verification fails, we add a X-HELO-Warning: header in
# the message.
#
warn
message = X-HELO-Warning: Remote host $sender_host_address \
${if def:sender_host_name {($sender_host_name) }}\
incorrectly presented itself as $sender_helo_name
log_message = remote host presented unverifiable HELO/EHLO greeting.
!verify = helo
######################################################################
# Sender Address Checks
######################################################################
# If we cannot verify the sender address, deny the message.
#
# You may choose to remove the "callout" option. In particular,
# if you are sending outgoing mail through a smarthost, it will not
# give any useful information.
#
# Details regarding the failed callout verification attempt are
# included in the 550 response; to omit these, change
# "sender/callout" to "sender/callout,no_details".
#
deny
message = &#60;$sender_address&#62; does not appear to be a \
valid sender address.
!verify = sender/callout
######################################################################
# Recipent Address Checks
######################################################################
# Deny if the local part contains @ or % or / or | or !. These are
# rarely found in genuine local parts, but are often tried by people
# looking to circumvent relaying restrictions.
#
# Also deny if the local part starts with a dot. Empty components
# aren't strictly legal in RFC 2822, but Exim allows them because
# this is common. However, actually starting with a dot may cause
# trouble if the local part is used as a file name (e.g. for a
# mailing list).
#
deny
local_parts = ^.*[@%!/|] : ^\\.
# Drop the connection if the envelope sender is empty, but there is
# more than one recipient address. Legitimate DSNs are never sent
# to more than one address.
#
drop
message = Legitimate bounces are never sent to more than one \
recipient.
senders = : postmaster@*
condition = $recipients_count
# Reject the recipient address if it is not in a domain for
# which we are handling mail.
#
deny
message = relay not permitted
!domains = +local_domains : +relay_to_domains
# Reject the recipient if it is not a valid mailbox.
# If the mailbox is not on our system (e.g. if we are a
# backup MX for the recipient domain), then perform a
# callout verification; but if the destination server is
# not responding, accept the recipient anyway.
#
deny
message = unknown user
!verify = recipient/callout=20s,defer_ok
# Otherwise, the recipient address is OK.
#
accept
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="acl_data_1"
></A
>A.4.5. acl_data</H2
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# This access control list is used for message data received via
# SMTP. The tests are run in order until the recipient address
# is either accepted or denied.
acl_data:
# Add Message-ID if missing in messages received from our own hosts.
warn
condition = ${if !def:h_Message-ID: {1}}
hosts = : +relay_from_hosts
message = Message-ID: &#60;E$message_id@$primary_hostname&#62;
# Accept mail received over local SMTP (i.e. not over TCP/IP).
# We do this by testing for an empty sending host field.
# Also accept mails received from hosts for which we relay mail.
#
accept
hosts = : +relay_from_hosts
# Accept if the message arrived over an authenticated connection, from
# any host.
#
accept
authenticated = *
# Enforce a message-size limit
#
deny
message = Message size $message_size is larger than limit of \
MESSAGE_SIZE_LIMIT
condition = ${if &#62;{$message_size}{MESSAGE_SIZE_LIMIT}{true}{false}}
# Deny unless the address list header is syntactically correct.
#
deny
message = Your message does not conform to RFC2822 standard
log_message = message header fail syntax check
!verify = header_syntax
# Deny non-local messages with no Message-ID, or no Date
#
# Note that some specialized MTAs, such as certain mailing list
# servers, do not automatically generate a Message-ID for bounces.
# Thus, we add the check for a non-empty sender.
#
deny
message = Your message does not conform to RFC2822 standard
log_message = missing header lines
!hosts = +relay_from_hosts
!senders = : postmaster@*
condition = ${if or {{!def:h_Message-ID:}\
{!def:h_Date:}\
{!def:h_Subject:}} {true}{false}}
# Warn unless there is a verifiable sender address in at least
# one of the "Sender:", "Reply-To:", or "From:" header lines.
#
warn
message = X-Sender-Verify-Failed: No valid sender in message header
log_message = No valid sender in message header
!verify = header_sender
# Accept the message.
#
accept
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-smtpdelays"
></A
>A.5. Adding SMTP transaction delays</H1
><DIV
CLASS="section"
><H2
CLASS="section"
><A
NAME="exim-smtpdelays-simple"
></A
>A.5.1. The simple way</H2
><P
>&#13; The simplest way to add SMTP transaction delays is to append a
<TT
CLASS="option"
>delay</TT
> control to the final
<TT
CLASS="option"
>accept</TT
> statement in each of the ACLs we have
declared, as follows:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; accept
delay = 20s
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; In addition, you may want to add progressive delays in the
<TT
CLASS="option"
>deny</TT
> statement pertaining to invalid
recipients (<SPAN
CLASS="QUOTE"
>"unknown user"</SPAN
>) within <A
HREF="#acl_rcpt_to_1"
>acl_rcpt_to</A
>. This is to slow down dictionary
attacks. For instance:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; deny
message = unknown user
!verify = recipient/callout=20s,defer_ok,use_sender
delay = ${eval:$rcpt_fail_count*10 + 20}s
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; It should be noted that there is no point in imposing a delay
in <A
HREF="#acl_data_1"
>acl_data</A
>, after the message data has
been received. Ratware commonly disconnect at this point,
before even receiving a response from your server. In any
case, whether or not the client disconnects at this point has
no bearing on whether Exim will proceed with the delivery of
the message.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-smtpdelays-selective"
></A
>A.5.2. Selective Delays</H2
><P
>&#13; If you are like me, you want to be a little bit more selective
about which hosts you subject to SMTP transaction delays. For
instance, as described earlier in this document, you may
decide that a match from a DNS blacklist or a non-verifiable
EHLO/HELO greeting are not conditions that by themselves
warrant a rejection - but they may well be sufficient triggers
for transaction delays.
</P
><P
>&#13; In order perform selective delays, we want move some of the
checks that we previously did in <A
HREF="#acl_rcpt_to_1"
>acl_rcpt_to</A
> to earlier points in the SMTP
transaction. This is so that we can start imposing the delays
as soon as we see any sign of trouble, and thereby increase
the chance of causing synchronization errors and other trouble
for ratware.
</P
><P
>&#13; Specifically, we want to:
</P
><P
></P
><UL
><LI
><P
>&#13; Move the DNS checks to
<A
HREF="#acl_connect_final"
>acl_connect</A
>.
</P
></LI
><LI
><P
>&#13; Move the Hello checks to <A
HREF="#acl_helo_final"
>acl_helo</A
>.
One exception: We cannot yet check for a missing Hello
greeting at this point, because this ACL is processed
<EM
>in response</EM
> to an EHLO or HELO
command. We will do this check in the <A
HREF="#acl_mail_from_final"
>acl_mail_from</A
> ACL.
</P
></LI
><LI
><P
>&#13; Move the Sender Address Checks checks to <A
HREF="#acl_mail_from_final"
>acl_mail_from</A
>.
</P
></LI
></UL
><P
>&#13; However, for reasons described above, we do not want to
actually reject the mail until after the <B
CLASS="command"
>RCPT
TO:</B
> command. Instead, in the earlier ACLs, we
will convert the various <TT
CLASS="option"
>deny</TT
> statements
into <TT
CLASS="option"
>warn</TT
> statements, and use Exim's
general purpose ACL variables to store any error messages or
warnings until after the <B
CLASS="command"
>RCPT TO:</B
>
command. We do that as follows:
</P
><P
></P
><UL
><LI
><P
>&#13; If we decide to reject the delivery, we store an error
message to be used in the forthcoming
<B
CLASS="command"
>550</B
> response in
<TT
CLASS="varname"
>$acl_c0</TT
> or <TT
CLASS="varname"
>$acl_m0</TT
>:
</P
><P
></P
><UL
><LI
><P
>&#13; If we identify the condition before a mail delivery
has started (i.e. in
<A
HREF="#acl_connect_final"
>acl_connect</A
> or
<A
HREF="#acl_helo_final"
>acl_helo</A
>), we use the
connection-persistent variable
<TT
CLASS="varname"
>$acl_c0</TT
>
</P
></LI
><LI
><P
>&#13; Once a mail transaction has started (i.e. after the
<B
CLASS="command"
>MAIL FROM:</B
> command), we copy any
contents from <TT
CLASS="varname"
>$acl_c0</TT
> into the
message-specific variable <TT
CLASS="varname"
>$acl_m0</TT
>,
and use the latter from this point forward. This
way, any conditions identified in this particular
message will not affect any subsequent messages
received in the same connection.
</P
></LI
></UL
><P
>&#13; Also, we store a corresponding <EM
>log
message</EM
> in <TT
CLASS="varname"
>$acl_c1</TT
> or
<TT
CLASS="varname"
>$acl_m1</TT
>, in a similar manner.
</P
></LI
><LI
><P
>&#13; If we come across a condition that does not warrant an
outright rejection, we only store a warning message in
<TT
CLASS="varname"
>$acl_c1</TT
> or <TT
CLASS="varname"
>$acl_m1</TT
>.
Once a mail transaction has started (i.e. in <A
HREF="#acl_mail_from_final"
>acl_mail_from</A
>), we add any content in
this variable to the message header as well.
</P
></LI
><LI
><P
>&#13; If we decide to <EM
>accept</EM
> a message
without regard to the results of any subsequent checks
(such as a SpamAssassin scan), we set a flag in
<TT
CLASS="varname"
>$acl_c0</TT
> or <TT
CLASS="varname"
>$acl_m0</TT
>, but
<TT
CLASS="varname"
>$acl_c1</TT
> and <TT
CLASS="varname"
>$acl_m1</TT
>
empty.
</P
></LI
><LI
><P
>&#13; At the beginning of every ACL to and including <A
HREF="#acl_mail_from_final"
>acl_mail_from</A
>, we record the current
timestamp in <TT
CLASS="varname"
>$acl_m2</TT
>. At the end of the
ACL, we use the presence of <TT
CLASS="varname"
>$acl_c1</TT
> or
<TT
CLASS="varname"
>$acl_m1</TT
> to trigger a SMTP transaction
delay until a total of 20 seconds has elapsed.
</P
></LI
></UL
><P
>&#13; The following table summarizes our use of these variables:
</P
><DIV
CLASS="table"
><A
NAME="aclvarusage"
></A
><P
><B
>Table A-1. Use of ACL connection/message variables</B
></P
><TABLE
BORDER="1"
CLASS="CALSTABLE"
><THEAD
><TR
><TH
ALIGN="LEFT"
VALIGN="MIDDLE"
>Variables:</TH
><TH
ALIGN="LEFT"
VALIGN="MIDDLE"
>$acl_[cm]0 unset</TH
><TH
ALIGN="LEFT"
VALIGN="MIDDLE"
>$acl_[cm]0 set</TH
></TR
></THEAD
><TBODY
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>$acl_[cm]1 unset</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>(No decision yet)</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>Accept the mail</TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>$acl_[cm]1 set</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>Add warning in header</TD
><TD
ALIGN="LEFT"
VALIGN="MIDDLE"
>Reject the mail</TD
></TR
></TBODY
></TABLE
></DIV
><P
>&#13; As an example of this approach, let us consider two checks
that we do in response to the Hello greeting; one that will
reject mails if the peer greets with an IP address, and one
that will warn about an unverifiable name in the greeting.
Previously, we did both of these checks in <A
HREF="#acl_rcpt_to_1"
>acl_rcpt_to</A
> - now we move them to the <A
HREF="#acl_helo_final"
>acl_helo</A
> ACL.
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;acl_helo:
# Record the current timestamp, in order to calculate elapsed time
# for subsequent delays
warn
set acl_m2 = $tod_epoch
# Accept mail received over local SMTP (i.e. not over TCP/IP).
# We do this by testing for an empty sending host field.
# Also accept mails received from hosts for which we relay mail.
#
accept
hosts = : +relay_from_hosts
# If the remote host greets with an IP address, then prepare a reject
# message in $acl_c0, and a log message in $acl_c1. We will later use
# these in a "deny" statement. In the mean time, their presence indicate
# that we should keep stalling the sender.
#
warn
condition = ${if isip {$sender_helo_name}{true}{false}}
set acl_c0 = Message was delivered by ratware
set acl_c1 = remote host used IP address in HELO/EHLO greeting
# If HELO verification fails, we prepare a warning message in acl_c1.
# We will later add this message to the mail header. In the mean time,
# its presence indicates that we should keep stalling the sender.
#
warn
condition = ${if !def:acl_c1 {true}{false}}
!verify = helo
set acl_c1 = X-HELO-Warning: Remote host $sender_host_address \
${if def:sender_host_name {($sender_host_name) }}\
incorrectly presented itself as $sender_helo_name
log_message = remote host presented unverifiable HELO/EHLO greeting.
#
# ... additional checks omitted for this example ...
#
# Accept the connection, but if we previously generated a message in
# $acl_c1, stall the sender until 20 seconds has elapsed.
accept
set acl_m2 = ${if def:acl_c1 {${eval:20 + $acl_m2 - $tod_epoch}}{0}}
delay = ${if &#62;{$acl_m2}{0}{$acl_m2}{0}}s
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Then, in <A
HREF="#acl_mail_from_final"
>acl_mail_from</A
> we transfer the
messages from <TT
CLASS="option"
>$acl_c{0,1}</TT
> to
<TT
CLASS="option"
>$acl_m{0,1}</TT
>. We also add the contents of
<TT
CLASS="varname"
>$acl_c1</TT
> to the message header.
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;acl_mail_from:
# Record the current timestamp, in order to calculate elapsed time
# for subsequent delays
warn
set acl_m2 = $tod_epoch
# Accept mail received over local SMTP (i.e. not over TCP/IP).
# We do this by testing for an empty sending host field.
# Also accept mails received from hosts for which we relay mail.
#
accept
hosts = : +relay_from_hosts
# If present, the ACL variables $acl_c0 and $acl_c1 contain rejection
# and/or warning messages to be applied to every delivery attempt in
# in this SMTP transaction. Assign these to the corresponding
# $acl_m{0,1} message-specific variables, and add any warning message
# from $acl_m1 to the message header. (In the case of a rejection,
# $acl_m1 actually contains a log message instead, but this does not
# matter, as we will discard the header along with the message).
#
warn
set acl_m0 = $acl_c0
set acl_m1 = $acl_c1
message = $acl_c1
#
# ... additional checks omitted for this example ...
#
# Accept the sender, but if we previously generated a message in
# $acl_c1, stall the sender until 20 seconds has elapsed.
accept
set acl_m2 = ${if def:acl_c1 {${eval:20 + $acl_m2 - $tod_epoch}}{0}}
delay = ${if &#62;{$acl_m2}{0}{$acl_m2}{0}}s
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; All the pertinent changes are incorporated in the <A
HREF="#exim-final"
>Final ACLs</A
>, to follow.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-greylisting"
></A
>A.6. Adding Greylisting Support</H1
><P
>&#13; There are several alternate greylisting implementations
available for Exim. Here we will cover a couple of these.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-greylistd"
></A
>A.6.1. greylistd</H2
><P
>&#13; This is a Python implementation developed by <EM
>yours
truly</EM
>. (So naturally, this is the implementation
I will include in the <A
HREF="#exim-final"
>Final ACLs</A
> to
follow). It operates as a stand-alone daemon, and thus does
not depend on any external database. Greylist data is
stored as simple 32-bit hashes for efficiency.
</P
><P
>&#13; You can find it at <A
HREF="http://packages.debian.org/unstable/mail/greylistd"
TARGET="_top"
>http://packages.debian.org/unstable/mail/greylistd</A
>.
Debian users can get it via APT:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
># apt-get install greylistd</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; To consult <TT
CLASS="option"
>greylistd</TT
>, we insert two
statements in <A
HREF="#acl_rcpt_to_final"
>acl_rcpt_to</A
> ACL that we
previously declared, right before the final
<TT
CLASS="option"
>accept</TT
> statement:
</P
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Consult "greylistd" to obtain greylisting status for this particular
# peer/sender/recipient triplet.
#
# We do not greylist messages with a NULL sender, because sender
# callout verification would break (and we might not be able to
# send mail to a host that performs callouts).
#
defer
message = $sender_host_address is not yet authorized to deliver mail \
from &#60;$sender_address&#62; to &#60;$local_part@$domain&#62;. \
Please try later.
log_message = greylisted.
domains = +local_domains : +relay_to_domains
!senders = : postmaster@*
set acl_m9 = $sender_host_address $sender_address $local_part@$domain
set acl_m9 = ${readsocket{/var/run/greylistd/socket}{$acl_m9}{5s}{}{}}
condition = ${if eq {$acl_m9}{grey}{true}{false}}
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Unless you incorporate <A
HREF="#exim-sign"
>envelope
sender signatures</A
> to block bogus <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
>s, you may want to add a similar statement in
your <A
HREF="#acl_data_final"
>acl_data</A
> to also greylist messages
with a NULL sender.
</P
><P
>&#13; The data we use for greylisting purposes here will be a little
different than above. In addition to
<TT
CLASS="option"
>$sender_address</TT
> being emtpy, neither
<TT
CLASS="option"
>$local_part</TT
> nor <TT
CLASS="option"
>$domain</TT
> is
defined at this point. Instead, the variable
<TT
CLASS="option"
>$recipients</TT
> contains a comma-separated list
of all recipient addresses. For a legitimate DSN, there
should be only one address.
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Perform greylisting on messages with no envelope sender here.
# We did not subject these to greylisting after RCPT TO: because
# that would interfere with remote hosts doing sender callouts.
#
defer
message = $sender_host_address is not yet authorized to send \
delivery status reports to &#60;$recipients&#62;. \
Please try later.
log_message = greylisted.
senders = : postmaster@*
set acl_m9 = $sender_host_address $recipients
set acl_m9 = ${readsocket{/var/run/greylistd/socket}{$acl_m9}{5s}{}{}}
condition = ${if eq {$acl_m9}{grey}{true}{false}}
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-greylist-mysql"
></A
>A.6.2. MySQL implementation</H2
><P
>&#13; The following inline implementation was contributed by
Johannes Berg <TT
CLASS="email"
>&#60;<A
HREF="mailto:johannes (at) sipsolutions.net"
>johannes (at) sipsolutions.net</A
>&#62;</TT
>,
based in part on:
</P
><P
></P
><UL
><LI
><P
>&#13; work by Rick Stewart <TT
CLASS="email"
>&#60;<A
HREF="mailto:rick.stewart (at)
theinternetco.net"
>rick.stewart (at)
theinternetco.net</A
>&#62;</TT
>, published at <A
HREF="http://theinternetco.net/projects/exim/greylist"
TARGET="_top"
>http://theinternetco.net/projects/exim/greylist</A
>,
in turn based on
</P
></LI
><LI
><P
>&#13; a Postgres implementation created by Tollef Fog Heen
<TT
CLASS="email"
>&#60;<A
HREF="mailto:tfheen (at) raw.no"
>tfheen (at) raw.no</A
>&#62;</TT
>, available at
<A
HREF="http://raw.no/personal/blog/tech/Debian/2004-03-14-15-55_greylisting"
TARGET="_top"
>http://raw.no/personal/blog/tech/Debian/2004-03-14-15-55_greylisting</A
>
</P
></LI
></UL
><P
>&#13; It requires no external programs - the entire implementation
is based on these configuration snippets along with a MySQL
database.
</P
><P
>&#13; An archive containing up-to-date configuration snippets as
well as a <TT
CLASS="option"
>README</TT
> file is available at:
<A
HREF="http://johannes.sipsolutions.net/wiki/Projects/exim-greylist"
TARGET="_top"
>http://johannes.sipsolutions.net/wiki/Projects/exim-greylist</A
>.
</P
><P
>&#13; MySQL needs to be installed on your system. At a MySQL
prompt, create an <TT
CLASS="option"
>exim4</TT
> database with two
tables named <TT
CLASS="option"
>exim_greylist</TT
> and
<TT
CLASS="option"
>exim_greylist_log</TT
>, as follows:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;CREATE DATABASE exim4;
use exim4;
CREATE TABLE exim_greylist (
id bigint(20) NOT NULL auto_increment,
relay_ip varchar(80) default NULL,
sender varchar(255) default NULL,
recipient varchar(255) default NULL,
block_expires datetime NOT NULL default '0000-00-00 00:00:00',
record_expires datetime NOT NULL default '9999-12-31 23:59:59',
create_time datetime NOT NULL default '0000-00-00 00:00:00',
type enum('AUTO','MANUAL') NOT NULL default 'MANUAL',
passcount bigint(20) NOT NULL default '0',
blockcount bigint(20) NOT NULL default '0',
PRIMARY KEY (id)
);
CREATE TABLE exim_greylist_log (
id bigint(20) NOT NULL auto_increment,
listid bigint(20) NOT NULL,
timestamp datetime NOT NULL default '0000-00-00 00:00:00',
kind enum('deferred', 'accepted') NOT NULL,
PRIMARY KEY (id)
);
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; In the <EM
>main</EM
> section of your Exim
configuration file, declare the following macros:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# if you don't have another database defined, then define it here
hide mysql_servers = localhost/exim4/<TT
CLASS="parameter"
><I
>user</I
></TT
>/<TT
CLASS="parameter"
><I
>password</I
></TT
>
# options
# these need to be valid as xxx in mysql's DATE_ADD(..,INTERVAL xxx)
# not valid, for example, are plurals: "2 HOUR" instead of "2 HOURS"
GREYLIST_INITIAL_DELAY = 1 HOUR
GREYLIST_INITIAL_LIFETIME = 4 HOUR
GREYLIST_WHITE_LIFETIME = 36 DAY
GREYLIST_BOUNCE_LIFETIME = 0 HOUR
# you can change the table names
GREYLIST_TABLE=exim_greylist
GREYLIST_LOG_TABLE=exim_greylist_log
# comment out to the following line to disable greylisting (temporarily)
GREYLIST_ENABLED=
# uncomment the following to enable logging
#GREYLIST_LOG_ENABLED=
# below here, nothing should normally be edited
.ifdef GREYLIST_ENABLED
# database macros
GREYLIST_TEST = SELECT CASE \
WHEN now() &#62; block_expires THEN "accepted" \
ELSE "deferred" \
END AS result, id \
FROM GREYLIST_TABLE \
WHERE (now() &#60; record_expires) \
AND (sender = '${quote_mysql:$sender_address}' \
OR (type='MANUAL' \
AND ( sender IS NULL \
OR sender = '${quote_mysql:@$sender_address_domain}' \
) \
) \
) \
AND (recipient = '${quote_mysql:$local_part@$domain}' \
OR (type = 'MANUAL' \
AND ( recipient IS NULL \
OR recipient = '${quote_mysql:$local_part@}' \
OR recipient = '${quote_mysql:@$domain}' \
) \
) \
) \
AND (relay_ip = '${quote_mysql:$sender_host_address}' \
OR (type='MANUAL' \
AND ( relay_ip IS NULL \
OR relay_ip = substring('${quote_mysql:$sender_host_address}',1,length(relay_ip)) \
) \
) \
) \
ORDER BY result DESC LIMIT 1
GREYLIST_ADD = INSERT INTO GREYLIST_TABLE \
(relay_ip, sender, recipient, block_expires, \
record_expires, create_time, type) \
VALUES ( '${quote_mysql:$sender_host_address}', \
'${quote_mysql:$sender_address}', \
'${quote_mysql:$local_part@$domain}', \
DATE_ADD(now(), INTERVAL GREYLIST_INITIAL_DELAY), \
DATE_ADD(now(), INTERVAL GREYLIST_INITIAL_LIFETIME), \
now(), \
'AUTO' \
)
GREYLIST_DEFER_HIT = UPDATE GREYLIST_TABLE \
SET blockcount=blockcount+1 \
WHERE id = $acl_m9
GREYLIST_OK_COUNT = UPDATE GREYLIST_TABLE \
SET passcount=passcount+1 \
WHERE id = $acl_m9
GREYLIST_OK_NEWTIME = UPDATE GREYLIST_TABLE \
SET record_expires = DATE_ADD(now(), INTERVAL GREYLIST_WHITE_LIFETIME) \
WHERE id = $acl_m9 AND type='AUTO'
GREYLIST_OK_BOUNCE = UPDATE GREYLIST_TABLE \
SET record_expires = DATE_ADD(now(), INTERVAL GREYLIST_BOUNCE_LIFETIME) \
WHERE id = $acl_m9 AND type='AUTO'
GREYLIST_LOG = INSERT INTO GREYLIST_LOG_TABLE \
(listid, timestamp, kind) \
VALUES ($acl_m9, now(), '$acl_m8')
.endif
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Now, in the ACL section (after <TT
CLASS="option"
>begin acl</TT
>),
declare a new ACL named <SPAN
CLASS="QUOTE"
>"greylist_acl"</SPAN
>:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;.ifdef GREYLIST_ENABLED
# this acl returns either deny or accept
# since we use it inside a defer with acl = greylist_acl,
# accepting here makes the condition TRUE thus deferring,
# denying here makes the condition FALSE thus not deferring
greylist_acl:
# For regular deliveries, check greylist.
# check greylist tuple, returning "accepted", "deferred" or "unknown"
# in acl_m8, and the record id in acl_m9
warn set acl_m8 = ${lookup mysql{GREYLIST_TEST}{$value}{result=unknown}}
# here acl_m8 = "result=x id=y"
set acl_m9 = ${extract{id}{$acl_m8}{$value}{-1}}
# now acl_m9 contains the record id (or -1)
set acl_m8 = ${extract{result}{$acl_m8}{$value}{unknown}}
# now acl_m8 contains unknown/deferred/accepted
# check if we know a certain triple, add and defer message if not
accept
# if above check returned unknown (no record yet)
condition = ${if eq{$acl_m8}{unknown}{1}}
# then also add a record
condition = ${lookup mysql{GREYLIST_ADD}{yes}{no}}
# now log, no matter what the result was
# if the triple was unknown, we don't need a log entry
# (and don't get one) because that is implicit through
# the creation time above.
.ifdef GREYLIST_LOG_ENABLED
warn condition = ${lookup mysql{GREYLIST_LOG}}
.endif
# check if the triple is still blocked
accept
# if above check returned deferred then defer
condition = ${if eq{$acl_m8}{deferred}{1}}
# and note it down
condition = ${lookup mysql{GREYLIST_DEFER_HIT}{yes}{yes}}
# use a warn verb to count records that were hit
warn condition = ${lookup mysql{GREYLIST_OK_COUNT}}
# use a warn verb to set a new expire time on automatic records,
# but only if the mail was not a bounce, otherwise set to now().
warn !senders = : postmaster@*
condition = ${lookup mysql{GREYLIST_OK_NEWTIME}}
warn senders = : postmaster@*
condition = ${lookup mysql{GREYLIST_OK_BOUNCE}}
deny
.endif
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Incorporate this ACL into your <A
HREF="#acl_rcpt_to_final"
>acl_rcpt_to</A
>
to greylist triplets where the sender address is non-empty.
This is to allow for sender callout verifications:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;.ifdef GREYLIST_ENABLED
defer !senders = : postmaster@*
acl = greylist_acl
message = greylisted - try again later
.endif
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Also incorporate it into your <A
HREF="#acl_data_1"
>acl_data</A
>
block, but this time only if the sender address is empty.
This is to prevent spammers from getting around greylisting by
setting the sender address to NULL.
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;.ifdef GREYLIST_ENABLED
defer senders = : postmaster@*
acl = greylist_acl
message = greylisted - try again later
.endif
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-spf"
></A
>A.7. Adding SPF Checks</H1
><P
>&#13; Here we cover two different ways to check <A
HREF="#spf"
>Sender Policy Framework</A
>
records using Exim. In addition to these explicit mechanisms,
the SpamAssassin suite will in the near future (around version
2.70) incorporate more sophisticated SPF checks, by assigning
weighted scores to the various SPF results.
</P
><P
>&#13; Although we <EM
>could</EM
> perform this check as
early as in the <A
HREF="#acl_mail_from_final"
>acl_mail_from</A
> ACL, there
is an issue that will affect this decision: SPF is incompatible
with traditional e-mail forwarding. Unless the forwarding host
implements <A
HREF="http://spf.pobox.com/srs.html"
TARGET="_top"
>SRS</A
>, you may end up
rejecting forwarded mail because you receive it from a host that
is not authorized to do so per the SPF policy of the domain in
the <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
> address.
</P
><P
>&#13; To avoid doing this, we need to consult a user-specific list of
hosts from which forwarded mails should be accepted (as
described in <A
HREF="#exim-forward"
>Exempting Forwarded Mail</A
>, to follow).
This is only possible after the <B
CLASS="command"
>RCPT TO:</B
>,
when we know the username of the recipient.
</P
><P
>&#13; As such, we will add this check prior to any greylisting
checks and/or the final <TT
CLASS="option"
>accept</TT
> statement in
<A
HREF="#acl_rcpt_to_final"
>acl_rcpt_to</A
>.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-spf-exiscan"
></A
>A.7.1. SPF checks via Exiscan-ACL</H2
><P
>&#13; Recent versions of Tom Kistner's <TT
CLASS="option"
>Exiscan-ACL</TT
>
patch (see <A
HREF="#exim-prereq"
>Prerequisites</A
>) have native support
for SPF.
<A
NAME="AEN1692"
HREF="#FTN.AEN1692"
><SPAN
CLASS="footnote"
>[16]</SPAN
></A
>
Usage is very simple. An <TT
CLASS="option"
>spf</TT
> ACL condition
is added, and can be compared against any of the keywords
<TT
CLASS="option"
>pass</TT
>, <TT
CLASS="option"
>fail</TT
>,
<TT
CLASS="option"
>softfail</TT
>, <TT
CLASS="option"
>none</TT
>,
<TT
CLASS="option"
>neutral</TT
>, <TT
CLASS="option"
>err_perm</TT
> or
<TT
CLASS="option"
>err_temp</TT
>.
</P
><P
>&#13; Prior to any greylisting checks and/or the final
<TT
CLASS="option"
>accept</TT
> statement in <A
HREF="#acl_rcpt_to_final"
>acl_rcpt_to</A
>, insert the following snippet:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Query the SPF information for the sender address domain, if any,
# to see if the sending host is authorized to deliver its mail.
# If not, reject the mail.
#
deny
message = [SPF] $sender_host_address is not allowed to send mail \
from $sender_address_domain
log_message = SPF check failed.
spf = fail
# Add a SPF-Received: header to the message
warn
message = $spf_received
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; This statement will reject the mail if the owner of the domain
in the sender address has disallowed deliveries from the
calling host. Some people find that this gives the domain
owner a little bit too much control, even to the point of
shooting themselves in the foot. A suggested alternative is
to combine the SPF check with other checks, such as Sender
Callout Verification (but note that as before, there is no
point in doing this if you are sending your outgoing mail
through a smarthost):
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Reject the mail if we cannot verify the sender address via callouts,
# and if SPF information for the sending domain does not grant explicit
# authority to the sending host.
#
deny
message = The sender address does not seem to be valid, and SPF \
information does not grant $sender_host_address explicit \
authority to send mail from $sender_address_domain
log_message = SPF check failed.
!verify = sender/callout,random,postmaster
!spf = pass
# Add a SPF-Received: header to the message
warn
message = $spf_received
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-spf-query-perl"
></A
>A.7.2. SPF checks via Mail::SPF::Query</H2
><P
>&#13; <TT
CLASS="option"
>Mail::SPF::Query</TT
> is a the official SPF test
suite, available from <A
HREF="http://spf.pobox.com/downloads.html"
TARGET="_top"
>http://spf.pobox.com/downloads.html</A
>. Debian users,
install <TT
CLASS="option"
>libmail-spf-query-perl</TT
>.
</P
><P
>&#13; The <TT
CLASS="option"
>Mail::SPF::Query</TT
> package comes with a
daemon (<B
CLASS="command"
>spfd</B
>) that listens for requests on
a UNIX domain socket. Unfortunately, it does not come with an
<SPAN
CLASS="QUOTE"
>"init"</SPAN
> script to start this daemon automatically.
Therefore, in the following example, we will use the
standalone <B
CLASS="command"
>spfquery</B
> utility to make our SPF
requests.
</P
><P
>&#13; As above, insert the following prior to any greylisting checks
and/or the final <TT
CLASS="option"
>accept</TT
> statement in <A
HREF="#acl_rcpt_to_1"
>acl_rcpt_to</A
>:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Use "spfquery" to obtain SPF status for this particular sender/host.
# If the return code of that command is 1, this is an unauthorized sender.
#
deny
message = [SPF] $sender_host_address is not allowed to send mail \
from $sender_address_domain.
log_message = SPF check failed.
set acl_m9 = -ipv4=$sender_host_address \
-sender=$sender_address \
-helo=$sender_helo_name
set acl_m9 = ${run{/usr/bin/spfquery $acl_m9}}
condition = ${if eq {$runrc}{1}{true}{false}}
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-mime"
></A
>A.8. Adding MIME and Filetype Checks</H1
><P
>&#13; These checks depend on features found in Tom Kistner's
<TT
CLASS="option"
>Exiscan-ACL</TT
> patch - see <A
HREF="#exim-prereq"
>Prerequisites</A
> for details.
</P
><P
>&#13; Exiscan-ACL includes support for MIME decoding, and file name
suffix checks (or to use a misnomer from the Windows world,
<SPAN
CLASS="QUOTE"
>"file extension"</SPAN
> checks). This check alone will
block most Windows virii - but not those that are transmitted in
<TT
CLASS="option"
>.ZIP</TT
> archives or those that exploit
Outlook/MSIE HTML rendering vulnerabilities - see the discussion
on <A
HREF="#virusscanners"
>Virus Scanners</A
>.
</P
><P
>&#13; These checks should go into <A
HREF="#acl_data_1"
>acl_data</A
>,
before the final <TT
CLASS="option"
>accept</TT
> statement:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Reject messages that have serious MIME errors.
#
deny
message = Serious MIME defect detected ($demime_reason)
demime = *
condition = ${if &#62;{$demime_errorlevel}{2}{1}{0}}
# Unpack MIME containers and reject file extensions used by worms.
# This calls the demime condition again, but it will return cached results.
# Note that the extension list may be incomplete.
#
deny
message = We do not accept ".$found_extension" attachments here.
demime = bat:btm:cmd:com:cpl:dll:exe:lnk:msi:pif:prf:reg:scr:vbs:url
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; You will note that the <TT
CLASS="option"
>demime</TT
> condition is
invoked twice in the example above. However, the results are
cached, so the message is not actually processed twice.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-av"
></A
>A.9. Adding Anti-Virus Software</H1
><P
>&#13; Exiscan-ACL plugs into a number of different virus scanners
directly, or any other scanner that can be run from the
command line via its <TT
CLASS="option"
>cmdline</TT
> backend.
</P
><P
>&#13; To use this feature, the <A
HREF="#exim-options"
>main
section</A
> of your Exim configuration file must specify
which virus scanner to use, along with any options you wish to
pass to that scanner. The basic syntax is:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;av_scanner = <TT
CLASS="parameter"
><I
>scanner-type</I
></TT
>:<TT
CLASS="parameter"
><I
>option1</I
></TT
>:<TT
CLASS="parameter"
><I
>option</I
></TT
>:...
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; For instance:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;av_scanner = sophie:/var/run/sophie
av_scanner = kavdaemon:/opt/AVP/AvpCtl
av_scanner = clamd:127.0.0.1 1234
av_scanner = clamd:/opt/clamd/socket
av_scanner = cmdline:/path/to/sweep -all -rec -archive %s:found:'(.+)'
...
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; In the DATA ACL, you then want to use the
<TT
CLASS="option"
>malware</TT
> condition to perform the actual
scanning:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; deny
message = This message contains a virus ($malware_name)
demime = *
malware = */defer_ok
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; The included file <TT
CLASS="option"
>exiscan-acl-spec.txt</TT
>
contains full usage information.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-sa"
></A
>A.10. Adding SpamAssassin</H1
><P
>&#13; Invoking SpamAssassin at SMTP-time is commonly done in either
of two ways in Exim:
</P
><P
></P
><UL
><LI
><P
>&#13; Via the <TT
CLASS="option"
>spam</TT
> condition offered by
<TT
CLASS="option"
>Exiscan-ACL</TT
>. This is the mechanism we
will cover here.
</P
></LI
><LI
><P
>&#13; Via <TT
CLASS="option"
>SA-Exim</TT
>, another utility written by
Marc Merlins (<TT
CLASS="email"
>&#60;<A
HREF="mailto:marc (at) merlins.org"
>marc (at) merlins.org</A
>&#62;</TT
>),
specifically for running SpamAssassin at SMTP time in Exim.
This program operates through Exim's
<TT
CLASS="option"
>local_scan()</TT
> interface, either patched
directly into the Exim source code, or via Marc's own
<TT
CLASS="option"
>dlopen()</TT
> plugin (which, by the way, is
included in Debian's <TT
CLASS="option"
>exim4-daemon-light</TT
>
and <TT
CLASS="option"
>exim4-daemon-heavy</TT
> packages).
</P
><P
>&#13; <TT
CLASS="option"
>SA-Exim</TT
> offers some other features as
well, namely <EM
>greylisting</EM
> and
<EM
>teergrubing</EM
>. However, because the
scan happens after the message data has been received,
neither of these two features may be as useful as they
would be earlier in the SMTP transaction.
</P
><P
>&#13; <TT
CLASS="option"
>SA-Exim</TT
> can be found at:
<A
HREF="http://marc.merlins.org/linux/exim/sa.html"
TARGET="_top"
>http://marc.merlins.org/linux/exim/sa.html</A
>.
</P
></LI
></UL
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-sa-exiscan"
></A
>A.10.1. Invoke SpamAssassin via Exiscan</H2
><P
>&#13; <TT
CLASS="option"
>Exiscan-ACL</TT
>'s
<SPAN
CLASS="QUOTE"
>"<TT
CLASS="option"
>spam</TT
>"</SPAN
> condition passes the
message through either SpamAssassin or Brightmail, and
triggers if these indicate that the message is junk. By
default, it connects to a SpamAssassin daemon
(<TT
CLASS="option"
>spamd</TT
>) running on
<TT
CLASS="option"
>localhost</TT
>. The host address and port can be
changed by adding a <TT
CLASS="option"
>spamd_address</TT
> setting in
the <EM
>main</EM
> section of the Exim
configuration file. For more information, see the
<TT
CLASS="option"
>exiscan-acl-spect.txt</TT
> file included with the
patch.
</P
><P
>&#13; In our implementation, we are going to reject messages
classified as spam. However, we would like to keep a copy of
such messages in a separate mail folder, at least for the time
being. This is so that the user can periodically scan for
<A
HREF="#falsepos"
><I
CLASS="glossterm"
>False Positive</I
></A
>s.
</P
><P
>&#13; Exim offers <EM
>controls</EM
> that can be applied
to a message that is accepted, such as
<TT
CLASS="option"
>freeze</TT
>. The Exiscan-ACL patch adds one more
of these controls, namely <TT
CLASS="option"
>fakereject</TT
>.
This causes the following SMTP response:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;550-FAKEREJECT id=<TT
CLASS="parameter"
><I
>message-id</I
></TT
>
550-Your message has been rejected but is being kept for evaluation.
550 If it was a legit message, it may still be delivered to the target recipient(s).
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; We can incorporate this feature into our implementation, by
inserting the following snippet in <A
HREF="#acl_data_1"
>acl_data</A
>, prior to the final
<TT
CLASS="option"
>accept</TT
> statement:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Invoke SpamAssassin to obtain $spam_score and $spam_report.
# Depending on the classification, $acl_m9 is set to "ham" or "spam".
#
# If the message is classified as spam, pretend to reject it.
#
warn
set acl_m9 = ham
spam = mail
set acl_m9 = spam
control = fakereject
logwrite = :reject: Rejected spam (score $spam_score): $spam_report
# Add an appropriate X-Spam-Status: header to the message.
#
warn
message = X-Spam-Status: \
${if eq {$acl_m9}{spam}{Yes}{No}} (score $spam_score)\
${if def:spam_report {: $spam_report}}
logwrite = :main: Classified as $acl_m9 (score $spam_score)
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; In this example, <TT
CLASS="varname"
>$acl_m9</TT
> is initially set to
<SPAN
CLASS="QUOTE"
>"ham"</SPAN
>. Then SpamAssassin is invoked as the user
<TT
CLASS="option"
>mail</TT
>. If the message is classified as spam,
then <TT
CLASS="varname"
>$acl_m9</TT
> is set to <SPAN
CLASS="QUOTE"
>"spam"</SPAN
>,
and the <TT
CLASS="option"
>FAKEREJECT</TT
> response above is issued.
Finally, an <TT
CLASS="option"
>X-Spam-Status:</TT
> header is added to
the message. The idea is that the <A
HREF="#mda"
><I
CLASS="glossterm"
>Mail Delivery Agent</I
></A
> or
the recipient's <A
HREF="#mua"
><I
CLASS="glossterm"
>Mail User Agent</I
></A
> can use this header to
filter junk mail into a separate folder.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-sa-config"
></A
>A.10.2. Configure SpamAssassin</H2
><P
>&#13; By default, SpamAssassin presents its report in a verbose,
table-like format, mainly suitable for inclusion in or
attachment to the message body. In our case, we want a terse
report, suitable for the <TT
CLASS="option"
>X-Spam-Status:</TT
>
header in the example above. To do this, we add the following
snippet in its site specific configuration file
(<TT
CLASS="option"
>/etc/spamassassin/local.cf</TT
>,
<TT
CLASS="option"
>/etc/mail/spamassassin/local.cf</TT
>, or similar):
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;### Report template
clear_report_template
report "_TESTSSCORES(, )_"
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Also, a <A
HREF="#bayesian"
>Bayesian</A
> scoring
feature is built in, and is turned on by default. We normally
want to turn this off, because it requires training that will
be specific to each user, and thus is not suitable for
system-wide SMTP time filtering:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;### Disable Bayesian scoring
use_bayes 0
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; For these changes to take effect, you have to restart the
SpamAssassin daemon (<B
CLASS="command"
>spamd</B
>).
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-per-user"
></A
>A.10.3. User Settings and Data</H2
><P
>&#13; Say you have a number of users that want to specify their
individual SpamAssassin preferences, such as the spam
threshold, acceptable languages and character sets,
white/blacklisted senders, and so on. Or perhaps they really
want to be able to make use of SpamAssassin's native Bayesian
scoring (though I don't see why<A
NAME="AEN1828"
HREF="#FTN.AEN1828"
><SPAN
CLASS="footnote"
>[17]</SPAN
></A
>).
</P
><P
>&#13; As discussed in the <A
HREF="#usersettings"
>User Settings and Data</A
> section
earlier in the document, there is a way for this to happen.
We need to limit the number of recipients we accept per
incoming mail delivery to one. We accept the first
<B
CLASS="command"
>RCPT TO:</B
> command issued by the caller, then
defer subsequent ones using a <B
CLASS="command"
>451</B
> SMTP
response. As with <A
HREF="#exim-greylisting"
>greylisting</A
>, if the caller
is a well-behaved MTA it will know how to interpret this
response, and retry later.
</P
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="exim-limit-one-user"
></A
>A.10.3.1. Tell Exim to accept only one recipient per delivery</H3
><P
>&#13; In the <A
HREF="#acl_rcpt_to_final"
>acl_rcpt_to</A
>, we insert the
following statement after validating the recipient address,
but before any <TT
CLASS="option"
>accept</TT
> statements pertaining
to unauthenticated deliveries from remote hosts to local
users (i.e. before any greylist checks, envelope signature
checks, etc):
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Limit the number of recipients in each incoming message to one
# to support per-user settings and data (e.g. for SpamAssassin).
#
# NOTE: Every mail sent to several users at your site will be
# delayed for 30 minutes or more per recipient. This
# significantly slow down the pace of discussion threads
# involving several internal and external parties.
#
defer
message = We only accept one recipient at a time - please try later.
condition = $recipients_count
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="exim-sa-as-user"
></A
>A.10.3.2. Pass the recipient username to SpamAssassin</H3
><P
>&#13; In <A
HREF="#acl_data_final"
>acl_data</A
>, we modify the
<TT
CLASS="option"
>spam</TT
> condition given in the previous
section, so that it passes on to SpamAssassin the username
specified in the local part of the recipient address.
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Invoke SpamAssassin to obtain $spam_score and $spam_report.
# Depending on the classification, $acl_m9 is set to "ham" or "spam".
#
# We pass on the username specified in the recipient address,
# i.e. the portion before any '=' or '@' character, converted
# to lowercase. Multiple recipients should not occur, since
# we previously limited delivery to one recipient at a time.
#
# If the message is classified as spam, pretend to reject it.
#
warn
set acl_m9 = ham
spam = ${lc:${extract{1}{=@}{$recipients}{$value}{mail}}}
set acl_m9 = spam
control = fakereject
logwrite = :reject: Rejected spam (score $spam_score): $spam_report
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Note that instead of using Exim's
<TT
CLASS="option"
>${local_part:...}</TT
> function to get the
username, we manually extracted the portion before any
<SPAN
CLASS="QUOTE"
>"@"</SPAN
> or <SPAN
CLASS="QUOTE"
>"="</SPAN
> character. This is
because we will use the latter character in our <A
HREF="#exim-sign"
>envelope signature</A
> scheme, to
follow.
</P
></DIV
><DIV
CLASS="section"
><HR><H3
CLASS="section"
><A
NAME="exim-per-user-sa"
></A
>A.10.3.3. Enable per-user settings in SpamAssassin</H3
><P
>&#13; Let us now again look at SpamAssassin. First of all, you
may choose to remove the <TT
CLASS="option"
>use_bayes 0</TT
>
setting that we previously added in its site-wide
configuration file. In any case, each user will now have
the ability to decide whether to override this setting for
themselves.
</P
><P
>&#13; If mailboxes on your system map directly to local UNIX
accounts with home directories, you are done. By default,
the SpamAssassin daemon (<B
CLASS="command"
>spamd</B
>) performs
a <TT
CLASS="option"
>setuid()</TT
> to the username we pass to it,
and stores user data and settings in that user's home
directory.
</P
><P
>&#13; If this is not the case (for instance, if your mail accounts
are managed by Cyrus SASL or by another server), you need to
tell SpamAssassin where to find each user's preferences and
data files. Also, <B
CLASS="command"
>spamd</B
> needs to keep
running as a specific local user instead of attempting to
<TT
CLASS="option"
>setuid()</TT
> to a non-existing user.
</P
><P
>&#13; We do these things by specifying the options passed to
<B
CLASS="command"
>spamd</B
> at startup:
</P
><P
></P
><UL
><LI
><P
>&#13; On a Debian system, edit the <TT
CLASS="option"
>OPTIONS=</TT
>
setting in <TT
CLASS="option"
>/etc/default/spamassassin</TT
>.
</P
></LI
><LI
><P
>&#13; On a RedHat system, edit the
<TT
CLASS="option"
>SPAMDOPTIONS=</TT
> setting in
<TT
CLASS="option"
>/etc/sysconfig/spamassassin</TT
>.
</P
></LI
><LI
><P
>&#13; Others, figure it out.
</P
></LI
></UL
><P
>&#13; The options you need are:
</P
><P
></P
><UL
><LI
><P
>&#13; <TT
CLASS="option"
>-u</TT
> <TT
CLASS="parameter"
><I
>username</I
></TT
> -
specify the user under which <B
CLASS="command"
>spamd</B
>
will run (e.g. <TT
CLASS="option"
>mail</TT
>)
</P
></LI
><LI
><P
>&#13; <TT
CLASS="option"
>-x</TT
> - disable configuration files in
user's home directory.
</P
></LI
><LI
><P
>&#13; <TT
CLASS="option"
>--virtual-config-dir=/var/lib/spamassassin/%u</TT
>
- specify where per-user settings and data are stored.
<SPAN
CLASS="QUOTE"
>"%u"</SPAN
> is replaced with the calling username.
<B
CLASS="command"
>spamd</B
> must be able to create or
modify this directory:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# mkdir /var/lib/spamassassin
# chown -R mail:mail /var/lib/spamassassin
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></LI
></UL
><P
>&#13; Needless to say, after making these changes, you need to
restart <B
CLASS="command"
>spamd</B
>.
</P
></DIV
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-sign"
></A
>A.11. Adding Envelope Sender Signatures</H1
><P
>&#13; Here we implement <A
HREF="#signedsender"
>Envelope Sender Signature</A
> in our outgoing
mail, and check for these signatures before accepting incoming
<SPAN
CLASS="QUOTE"
>"bounces"</SPAN
> (i.e. mail with no envelope sender).
</P
><P
>&#13; The envelope sender address of outgoing mails from your host
will be modified as follows:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
><TT
CLASS="parameter"
><I
>sender</I
></TT
>=<TT
CLASS="parameter"
><I
>recipient</I
></TT
>=<TT
CLASS="parameter"
><I
>recipient.domain</I
></TT
>=<TT
CLASS="parameter"
><I
>hash</I
></TT
>@<TT
CLASS="parameter"
><I
>sender.domain</I
></TT
></PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; However, because this scheme may produce unintended consequences
(e.g. in the case of mailing list servers), we make it optional
for your users. We sign the envelope sender address of outgoing
mail only if we find a file named
<SPAN
CLASS="QUOTE"
>".return-path-sign"</SPAN
> in the sender's home directory,
and only if the domain we are sending to is matched in that
file. If the file exists, but is empty, all domains match.
</P
><P
>&#13; Similarly, we only require the recipient address to be signed in
incoming <SPAN
CLASS="QUOTE"
>"bounce"</SPAN
> messages (i.e. messages with no
envelope sender) if the same file exists in recipient's home
directory. Users can exempt specific hosts from this check via
their user specific whitelist, as described in
<A
HREF="#exim-forward"
>Exempting Forwarded Mail</A
>.
</P
><P
>&#13; Also, because this scheme involves tweaking with routers and
transports in addition to ACLs, we do not include it in the
<A
HREF="#exim-final"
>Final ACLs</A
> to follow. If you are able to
follow the instructions pertaining to those sections, you should
also be able to add the ACL section as described here.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-sign-transport"
></A
>A.11.1. Create a Transport to Sign the Sender Address</H2
><P
>&#13; First we create an Exim <EM
>transport</EM
> that
will be used to sign the envelope sender for remote
deliveries:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;remote_smtp_signed:
debug_print = "T: remote_smtp_signed for $local_part@$domain"
driver = smtp
max_rcpt = 1
return_path = $sender_address_local_part=$local_part=$domain=\
${hash_8:${hmac{md5}{SECRET}{${lc:\
$sender_address_local_part=$local_part=$domain}}}}\
@$sender_address_domain
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; The <SPAN
CLASS="QUOTE"
>"local part"</SPAN
> of the sender address now
consists of the following components, separated by equal
signs (<SPAN
CLASS="QUOTE"
>"="</SPAN
>):
</P
><P
></P
><UL
><LI
><P
>&#13; the sender's username, i.e. the original local part,
</P
></LI
><LI
><P
>&#13; the local part of the recipient address,
</P
></LI
><LI
><P
>&#13; the domain part of the recipient address,
</P
></LI
><LI
><P
>&#13; a string unique to this sender/recipient
combination, generated by:
</P
><P
></P
><UL
><LI
><P
>&#13; encrypting the three prior components of the rewritten
sender address, using Exim's
<TT
CLASS="option"
>${hmac{md5}...}</TT
> function along with
the <TT
CLASS="option"
>SECRET</TT
> we declared in the
<TT
CLASS="option"
>main</TT
> section,
<A
NAME="AEN1936"
HREF="#FTN.AEN1936"
><SPAN
CLASS="footnote"
>[18]</SPAN
></A
>
</P
></LI
><LI
><P
>&#13; hashing the result into 8 lowercase letters, using
Exim's <TT
CLASS="option"
>${hash...}</TT
> function.
</P
></LI
></UL
></LI
></UL
><P
>&#13; If you need authentication for deliveries to
<SPAN
CLASS="QUOTE"
>"smarthosts"</SPAN
>, add an appropriate
<TT
CLASS="option"
>hosts_try_auth</TT
> line here as well.
(Take it from your existing smarthost transport).
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-sign-router-remote"
></A
>A.11.2. Create a New Router for Remote Deliveries</H2
><P
>&#13; Add a new router prior to the existing router(s) that
currently handles your outgoing mail. This router will use
the transport above for remote deliveries, but only if the
file <SPAN
CLASS="QUOTE"
>".return-path-sign"</SPAN
> exists in the sender's
home directory, and if the recipient's domain is matched in
that file. For instance, if you send mail directly over the
internet to the final destination:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# Sign the envelope sender address (return path) for deliveries to
# remote domains if the sender's home directory contains the file
# ".return-path-sign", and if the remote domain is matched in that
# file. If the file exists, but is empty, the envelope sender
# address is always signed.
#
dnslookup_signed:
debug_print = "R: dnslookup_signed for $local_part@$domain"
driver = dnslookup
transport = remote_smtp_signed
senders = ! : *
domains = ! +local_domains : !+relay_to_domains : \
${if exists {/home/$sender_address_local_part/.return-path-sign}\
{/home/$sender_address_local_part/.return-path-sign}\
{!*}}
no_more
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Or if you use a smarthost:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# Sign the envelope sender address (return path) for deliveries to
# remote domains if the sender's home directory contains the file
# ".return-path-sign", and if the remote domain is matched in that
# file. If the file exists, but is empty, the envelope sender
# address is always signed.
#
smarthost_signed:
debug_print = "R: smarthost_signed for $local_part@$domain"
driver = manualroute
transport = remote_smtp_signed
senders = ! : *
route_list = * <TT
CLASS="parameter"
><I
>smarthost.address</I
></TT
>
host_find_failed = defer
domains = ! +local_domains : !+relay_to_domains : \
${if exists {/home/$sender_address_local_part/.return-path-sign}\
{/home/$sender_address_local_part/.return-path-sign}\
{!*}}
no_more
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Add other options as you see fit
(e.g. <TT
CLASS="option"
>same_domain_copy_routing = yes</TT
>),
perhaps modelled after your existing routers.
</P
><P
>&#13; Note that we do not use this router for mails with no envelope
sender address - we wouldn't want to tamper with those!
<A
NAME="AEN1959"
HREF="#FTN.AEN1959"
><SPAN
CLASS="footnote"
>[19]</SPAN
></A
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-sign-router-redirect"
></A
>A.11.3. Create New Redirect Router for Local Deliveries</H2
><P
>&#13; Next, you need to tell Exim that incoming recipient
addresses that match the format above should be delivered to
the mailbox identified by the portion before the first equal
(<SPAN
CLASS="QUOTE"
>"="</SPAN
>) sign. For this purpose, you want to
insert a <TT
CLASS="option"
>redirect</TT
> router early in the
<TT
CLASS="option"
>routers</TT
> section of your configuration file
- before any other routers pertaining to local deliveries
(such as a <EM
>system alias</EM
> router):
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;hashed_local:
debug_print = "R: hashed_local for $local_part@$domain"
driver = redirect
domains = +local_domains
local_part_suffix = =*
data = $local_part@$domain
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Recipient addresses that contain a equal sign are rewritten
such that the portion of the local part that follows the
equal sign are stripped off. Then all routers are
processed again.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-sign-acl"
></A
>A.11.4. ACL Signature Check</H2
><P
>&#13; The final part of this scheme is to tell Exim that mails
delivered to valid recipient addresses with this signature
should <EM
>always</EM
> be accepted, and that
other messages with a NULL envelope sender should be
rejected if the recipient has opted in to this scheme.
No greylisting should be done in either case.
</P
><P
>&#13; The following snippet should be placed in <A
HREF="#acl_rcpt_to_final"
>acl_rcpt_to</A
>, prior to any SPF checks,
greylisting, and/or the final <TT
CLASS="option"
>accept</TT
>
statement:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Accept the recipient addresss if it contains our own signature.
# This means this is a response (DSN, sender callout verification...)
# to a message that was previously sent from here.
#
accept
domains = +local_domains
condition = ${if and {{match{${lc:$local_part}}{^(.*)=(.*)}}\
{eq{${hash_8:${hmac{md5}{SECRET}{$1}}}}{$2}}}\
{true}{false}}
# Otherwise, if this message claims to be a bounce (i.e. if there
# is no envelope sender), but if the receiver has elected to use
# and check against envelope sender signatures, reject it.
#
deny
message = This address does not match a valid, signed \
return path from here.\n\
You are responding to a forged sender address.
log_message = bogus bounce.
senders = : postmaster@*
domains = +local_domains
set acl_m9 = /home/${extract{1}{=}{${lc:$local_part}}}/.return-path-sign
condition = ${if exists {$acl_m9}{true}}
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; You will have an issue when sending mail to hosts that
perform callout verification on addresses in the message
<EM
>header</EM
>, such as the one provided in the
<TT
CLASS="option"
>From:</TT
> field of your outgoing mail. The
<TT
CLASS="option"
>deny</TT
> statement here will effectively give a
negative response to such a verification attempt.
</P
><P
>&#13; For that reason, you may want to convert the last
<TT
CLASS="option"
>deny</TT
> statement into a <TT
CLASS="option"
>warn</TT
>
statement, store the rejection message in
<TT
CLASS="varname"
>$acl_m0</TT
>, and perform the actual rejection
after the <B
CLASS="command"
>DATA</B
> command, in a fashion
similar to previously described:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Otherwise, if this message claims to be a bounce (i.e. if there
# is no envelope sender), but if the receiver has elected to use
# and check against envelope sender signatures, store a reject
# message in $acl_m0, and a log message in $acl_m1. We will later
# use these to reject the mail. In the mean time, their presence
# indicate that we should keep stalling the sender.
#
warn
senders = : postmaster@*
domains = +local_domains
set acl_m9 = /home/${extract{1}{=}{${lc:$local_part}}}/.return-path-sign
condition = ${if exists {$acl_m9}{true}}
set acl_m0 = The recipient address &#60;$local_part@$domain&#62; does not \
match a valid, signed return path from here.\n\
You are responding to a forged sender address.
set acl_m1 = bogus bounce for &#60;$local_part@$domain&#62;.
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Also, even if the recipient has chosen to use envelope sender
signatures in their outgoing mail, they may want to exempt
specific hosts from having to provide this signature in
incoming mail, even if the mail has no envelope sender
address. This may be required for specific mailing list
servers, see the discussion on <A
HREF="#signedsender"
>Envelope Sender Signature</A
>
for details.
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-bounces"
></A
>A.12. Accept Bounces Only for Real Users</H1
><P
>&#13; As discussed in <A
HREF="#dsnrealuser"
>Accept Bounces Only for Real Users</A
>, there is now a
loophole that prevents us from catching bogus <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
> sent to system users and aliases, such as
<TT
CLASS="option"
>postmaster</TT
>. Here we cover two alternate ways
to ensure that bounces are only accepted for users that actually
send outgoing mail.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-dsn-mailbox"
></A
>A.12.1. Check for Recipient Mailbox</H2
><P
>&#13; The first method is performed in the <A
HREF="#acl_rcpt_to_final"
>acl_rcpt_to</A
> ACL. Here, we check that the
recipient address corresponds to a local mailbox:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Deny mail for users that do not have a mailbox (i.e. postmaster,
# webmaster...) if no sender address is provided. These users do
# not send outgoing mail, so they should not receive returned mail.
#
deny
message = This address never sends outgoing mail. \
You are responding to a forged sender address.
log_message = bogus bounce for system user &#60;$local_part@$domain&#62;
senders = : postmaster@*
domains = +local_domains
!<TT
CLASS="parameter"
><I
>mailbox check</I
></TT
>
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Unfortunately, how we perform the <TT
CLASS="parameter"
><I
>mailbox
check</I
></TT
> will depend on how you deliver your mail (as
before, we extract the portion before the first <SPAN
CLASS="QUOTE"
>"="</SPAN
>
sign of the recipient address, to accomodate for <A
HREF="#exim-sign"
>Envelope Sender Signatures</A
>):
</P
><P
></P
><UL
><LI
><P
>&#13; If mailboxes map to local user accounts on your server, we
can check that the recipient name maps to a user ID that
corresponds to <SPAN
CLASS="QUOTE"
>"regular"</SPAN
> users on your
system, e.g. in the range 500 - 60000:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; set acl_m9 = ${extract{1}{=}{${lc:$local_part}}}
set acl_m9 = ${extract{2}{:}{${lookup passwd {$acl_m9}{$value}}}{0}}
condition = ${if and {{&#62;={$acl_m9}{500}} {&#60;${acl_m9}{60000}}} {true}}
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></LI
><LI
><P
>&#13; If you deliver mail to the <A
HREF="http://asg.web.cmu.edu/cyrus/"
TARGET="_top"
>Cyrus</A
> IMAP
suite, you can use the provided <B
CLASS="command"
>mbpath</B
>
command-line utility to check that the mailbox exists.
You will want to make sure that the Exim user has
permission to check for mailboxes (for instance, you may
add it to the <TT
CLASS="option"
>cyrus</TT
> group:
<B
CLASS="command"
># adduser exim4 cyrus</B
>).
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; set acl_m9 = ${extract{1}{=}{${lc:$local_part}}}
condition = ${run {/usr/sbin/mbpath -q -s user.$acl_m9} {true}}
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></LI
><LI
><P
>&#13; If you forward all mail to a remote machine for delivery,
you may need to perform a <A
HREF="#callforward"
>Recipient Callout Verification</A
>
and let that machine decide whether to accept the mail.
You need to keep the original envelope sender intact in
the callout:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; verify = recipient/callout=use_sender
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></LI
></UL
><P
>&#13; Since in the case of locally delivered mail, this mailbox
check duplicates some of the logic that is performed in the
routers, and since it is specific to the mail delivery
mechanism on our site, it is perhaps a bit kludgy for the
perfectionists among us. So we will now provide an alternate
way.
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="exim-dsn-noalias"
></A
>A.12.2. Check for Empty Sender in Aliases Router</H2
><P
>&#13; You probably have a router named
<TT
CLASS="option"
>system_aliases</TT
> or similar, to redirect mail
for users such as <TT
CLASS="option"
>postmaster</TT
> and
<TT
CLASS="option"
>mailer-demon</TT
>. Typically, these aliases are
not used in the sender address of outgoing mail. As such, you
can ensure that incoming <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
>s are not routed
through it by adding the following condition to the router:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>!senders = : postmaster@*</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; A sample aliases router may now look like this:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;system_aliases:
driver = redirect
domains = +local_domains
!senders = : postmaster@*
allow_fail
allow_defer
data = ${lookup{$local_part}lsearch{/etc/aliases}}
user = mail
group = mail
file_transport = address_file
pipe_transport = address_pipe
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Although we now block bounces to <EM
>some</EM
>
system aliases, other aliases were merely shadowing existing
system users (such as <SPAN
CLASS="QUOTE"
>"root"</SPAN
>,
<SPAN
CLASS="QUOTE"
>"daemon"</SPAN
>, etc). If you deliver local mail
through the the <TT
CLASS="option"
>accept</TT
> driver, and use
<TT
CLASS="option"
>check_local_user</TT
> to validate the recipient
address, you may now find yourself routing mail directly to
these system accounts.
</P
><P
>&#13; To fix this problem, we now want to add an additional
condition in the router that handles your local mail
(e.g. <EM
>local_user</EM
>) to ensure that the
recipient not only exists, but is a <SPAN
CLASS="QUOTE"
>"regular"</SPAN
>
user. For instance, as above, we can check that the user ID
is in the range 500 - 60000:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; condition = ${if and {{&#62;={$local_user_uid}{500}}\
{&#60;{$local_user_uid}{60000}}}\
{true}}
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; A sample router for local delivery may now look like this:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;local_user:
driver = accept
domains = +local_domains
check_local_user
condition = ${if and {{&#62;={$local_user_uid}{500}}\
{&#60;{$local_user_uid}{60000}}}\
{true}}
transport = <TT
CLASS="parameter"
><I
>transport</I
></TT
>
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; Beware that if you implement this method, the reject response
from your server in response to bogus bounce mail for system
users will be the same as for unknown recipients (<B
CLASS="command"
>550
Unknown User</B
> in our case).
</P
></DIV
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-forward"
></A
>A.13. Exempting Forwarded Mail</H1
><P
>&#13; After adding all these checks in the SMTP transaction, we may
find ourselves indirectly creating collateral spam as a result
of rejecting mails forwarded from trusted sources, such as
mailing lists and mail accounts on other sites (see the
discussion on <A
HREF="#forwardedmail"
>Forwarded Mail</A
> for details). We
now need to whitelist these hosts in order to exempt them from
SMTP rejections -- at least those rejections that are caused by
our spam and/or virus filtering.
</P
><P
>&#13; In this example, we will consult two files in response to each
<B
CLASS="command"
>RCPT TO:</B
> command:
</P
><P
></P
><UL
><LI
><P
>&#13; A global whitelist in
<TT
CLASS="option"
>/etc/mail/whitelist-hosts</TT
>, containing
backup MX hosts and other whitelisted senders
<A
HREF="#FTN.noretrysenders"
><SPAN
CLASS="footnote"
>[9]</SPAN
></A
>, and
</P
></LI
><LI
><P
>&#13; A user-specific list in
<TT
CLASS="option"
>/home/<TT
CLASS="parameter"
><I
>user</I
></TT
>/.forwarders</TT
>,
specifying hosts from which that particuar user will receive
forwarded mail (e.g. mailing list servers, outgoing mail
servers for accounts elsewhere...)
</P
></LI
></UL
><P
>&#13; If your mail users do not have local user accounts and home
directories, you may want to modify the file paths and/or lookup
mechanisms to something more suitable for your system
(e.g. database lookups or LDAP queries).
</P
><P
>&#13; If the sender host is found in one of these whitelists, we save
the word <SPAN
CLASS="QUOTE"
>"accept"</SPAN
> in <TT
CLASS="varname"
>$acl_m0</TT
>, and
clear the contents of <TT
CLASS="varname"
>$acl_m1</TT
>, as described in
the previous section on <A
HREF="#exim-smtpdelays-selective"
>Selective Delays</A
>. This will indicate that
we should not reject the mail in subsequent statements.
</P
><P
>&#13; In the <A
HREF="#acl_rcpt_to_final"
>acl_rcpt_to</A
>, we insert the
following statement after validating the recipient address, but
before any <TT
CLASS="option"
>accept</TT
> statements pertaining to
unauthenticated deliveries from remote hosts to local users
(i.e. before any greylist checks, envelope signature checks,
etc):
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; # Accept the mail if the sending host is matched in the global
# whitelist file. Temporarily set $acl_m9 to point to this file.
# If the host is found, set a flag in $acl_m0 and clear $acl_m1 to
# indicate that we should not reject this mail later.
#
accept
set acl_m9 = /etc/mail/whitelist-hosts
hosts = ${if exists {$acl_m9}{$acl_m9}}
set acl_m0 = accept
set acl_m1 =
# Accept the mail if the sending host is matched in the ".forwarders"
# file in the recipient's home directory. Temporarily set $acl_m9 to
# point to this file. If the host is found, set a flag in $acl_m0 and
# clear $acl_m1 to indicate that we should not reject this mail later.
#
accept
domains = +local_domains
set acl_m9 = /home/${extract{1}{=}{${lc:$local_part}}}/.forwarders
hosts = ${if exists {$acl_m9}{$acl_m9}}
set acl_m0 = accept
set acl_m1 =
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; In various statements in the <A
HREF="#acl_data_final"
>acl_data</A
>
ACL, we check the contents of <TT
CLASS="varname"
>$acl_m0</TT
> to avoid
rejecting the mail if this is set as per above. For instance,
to avoid rejecting mail from whitelisted hosts due to a missing
RFC2822 header:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13; deny
message = Your message does not conform to RFC2822 standard
log_message = missing header lines
!hosts = +relay_from_hosts
!senders = : postmaster@*
condition = ${if !eq {$acl_m0}{accept}{true}}
condition = ${if or {{!def:h_Message-ID:}\
{!def:h_Date:}\
{!def:h_Subject:}} {true}{false}}
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
><P
>&#13; The appropriate checks are embedded in the <A
HREF="#exim-final"
>Final ACLs</A
>, next.
</P
></DIV
><DIV
CLASS="section"
><HR><H1
CLASS="section"
><A
NAME="exim-final"
></A
>A.14. Final ACLs</H1
><P
>&#13; OK, time to wake up! This has been very long reading - but
congratulations on making it this far!
</P
><P
>&#13; The following ACLs incorporate all of the checks we have
described so in this implementation. However, some have been
commented out, for the following reasons:
</P
><P
></P
><UL
><LI
><P
>&#13; <A
HREF="#exim-greylisting"
>Greylisting</A
>. This
either requires additional software to be installed, or
fairly complex inline configuration by way of additional
ACLs and definitions in the Exim configuration file.
I highly recommend it, though.
</P
></LI
><LI
><P
>&#13; <A
HREF="#exim-av"
>Virus scanning</A
>.
There is no <EM
>ubiquitous</EM
> scanner that
nearly everyone uses, similar to SpamAssassin for spam
identification. On the other hand, the documentation that
comes with <TT
CLASS="option"
>Exiscan-ACL</TT
> should be easy to
follow.
</P
></LI
><LI
><P
>&#13; <A
HREF="#exim-per-user"
>Per-user settings for
SpamAssassin</A
>. This is a trade-off that for many is
unacceptable, as it involves deferring mail to all but the
first recipient of a message.
</P
></LI
><LI
><P
>&#13; <A
HREF="#exim-sign"
>Envelope Sender Signatures</A
>.
There are consequences, e.g. for roaming users. Also, it
involves configuring routers and transports as well as
ACLs. See that section for details.
</P
></LI
><LI
><P
>&#13; <A
HREF="#exim-bounces"
>Accepting Bounces Only for Real
Users</A
>. There are several ways of doing this, and
determining which users are real is specific to how mail is
delivered.
</P
></LI
></UL
><P
>&#13; Without further ado, here comes the final result we have all
been waiting for.
</P
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="acl_connect_final"
></A
>A.14.1. acl_connect</H2
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# This access control list is used at the start of an incoming
# connection. The tests are run in order until the connection is
# either accepted or denied.
acl_connect:
# Record the current timestamp, in order to calculate elapsed time
# for subsequent delays
warn
set acl_m2 = $tod_epoch
# Accept mail received over local SMTP (i.e. not over TCP/IP). We do
# this by testing for an empty sending host field.
# Also accept mails received over a local interface, and from hosts
# for which we relay mail.
accept
hosts = : +relay_from_hosts
# If the connecting host is in one of several DNSbl's, then prepare
# a warning message in $acl_c1. We will later add this message to
# the mail header. In the mean time, its presence indicates that
# we should keep stalling the sender.
#
warn
!hosts = ${if exists {/etc/mail/whitelist-hosts} \
{/etc/mail/whitelist-hosts}}
dnslists = list.dsbl.org : \
dnsbl.sorbs.net : \
dnsbl.njabl.org : \
bl.spamcop.net : \
dsn.rfc-ignorant.org : \
sbl-xbl.spamhaus.org : \
l1.spews.dnsbl.sorbs.net
set acl_c1 = X-DNSbl-Warning: \
$sender_host_address is listed in $dnslist_domain\
${if def:dnslist_text { ($dnslist_text)}}
# Likewise, if reverse DNS lookup of the sender's host fails (i.e.
# there is no rDNS entry, or a forward lookup of the resulting name
# does not match the original IP address), then generate a warning
# message in $acl_c1. We will later add this message to the mail
# header.
warn
condition = ${if !def:acl_c1 {true}{false}}
!verify = reverse_host_lookup
set acl_m9 = Reverse DNS lookup failed for host $sender_host_address
set acl_c1 = X-DNS-Warning: $acl_m9
# Accept the connection, but if we previously generated a message in
# $acl_c1, stall the sender until 20 seconds has elapsed.
accept
set acl_m2 = ${if def:acl_c1 {${eval:20 + $acl_m2 - $tod_epoch}}{0}}
delay = ${if &#62;{$acl_m2}{0}{$acl_m2}{0}}s
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="acl_helo_final"
></A
>A.14.2. acl_helo</H2
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# This access control list is used for the HELO or EHLO command in
# an incoming SMTP transaction. The tests are run in order until the
# greeting is either accepted or denied.
acl_helo:
# Record the current timestamp, in order to calculate elapsed time
# for subsequent delays
warn
set acl_m2 = $tod_epoch
# Accept mail received over local SMTP (i.e. not over TCP/IP).
# We do this by testing for an empty sending host field.
# Also accept mails received from hosts for which we relay mail.
#
accept
hosts = : +relay_from_hosts
# If the remote host greets with an IP address, then prepare a reject
# message in $acl_c0, and a log message in $acl_c1. We will later use
# these in a "deny" statement. In the mean time, their presence indicate
# that we should keep stalling the sender.
#
warn
condition = ${if isip {$sender_helo_name}{true}{false}}
set acl_c0 = Message was delivered by ratware
set acl_c1 = remote host used IP address in HELO/EHLO greeting
# Likewise if the peer greets with one of our own names
#
warn
condition = ${if match_domain{$sender_helo_name}\
{$primary_hostname:+local_domains:+relay_to_domains}\
{true}{false}}
set acl_c0 = Message was delivered by ratware
set acl_c1 = remote host used our name in HELO/EHLO greeting.
# If HELO verification fails, we prepare a warning message in acl_c1.
# We will later add this message to the mail header. In the mean time,
# its presence indicates that we should keep stalling the sender.
#
warn
condition = ${if !def:acl_c1 {true}{false}}
!verify = helo
set acl_c1 = X-HELO-Warning: Remote host $sender_host_address \
${if def:sender_host_name {($sender_host_name) }}\
incorrectly presented itself as $sender_helo_name
log_message = remote host presented unverifiable HELO/EHLO greeting.
# Accept the greeting, but if we previously generated a message in
# $acl_c1, stall the sender until 20 seconds has elapsed.
accept
set acl_m2 = ${if def:acl_c1 {${eval:20 + $acl_m2 - $tod_epoch}}{0}}
delay = ${if &#62;{$acl_m2}{0}{$acl_m2}{0}}s
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="acl_mail_from_final"
></A
>A.14.3. acl_mail_from</H2
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# This access control list is used for the MAIL FROM: command in an
# incoming SMTP transaction. The tests are run in order until the
# sender address is either accepted or denied.
#
acl_mail_from:
# Record the current timestamp, in order to calculate elapsed time
# for subsequent delays
warn
set acl_m2 = $tod_epoch
# Accept mail received over local SMTP (i.e. not over TCP/IP).
# We do this by testing for an empty sending host field.
# Also accept mails received from hosts for which we relay mail.
#
# Sender verification is omitted here, because in many cases
# the clients are dumb MUAs that don't cope well with SMTP
# error responses.
#
accept
hosts = : +relay_from_hosts
# Accept if the message arrived over an authenticated connection,
# from any host. Again, these messages are usually from MUAs.
#
accept
authenticated = *
# If present, the ACL variables $acl_c0 and $acl_c1 contain rejection
# and/or warning messages to be applied to every delivery attempt in
# in this SMTP transaction. Assign these to the corresponding
# $acl_m{0,1} message-specific variables, and add any warning message
# from $acl_m1 to the message header. (In the case of a rejection,
# $acl_m1 actually contains a log message instead, but this does not
# matter, as we will discard the header along with the message).
#
warn
set acl_m0 = $acl_c0
set acl_m1 = $acl_c1
message = $acl_c1
# If sender did not provide a HELO/EHLO greeting, then prepare a reject
# message in $acl_m0, and a log message in $acl_m1. We will later use
# these in a "deny" statement. In the mean time, their presence indicate
# that we should keep stalling the sender.
#
warn
condition = ${if def:sender_helo_name {0}{1}}
set acl_m0 = Message was delivered by ratware
set acl_m1 = remote host did not present HELO/EHLO greeting.
# If we could not verify the sender address, create a warning message
# in $acl_m1 and add it to the mail header. The presence of this
# message indicates that we should keep stalling the sender.
#
# You may choose to omit the "callout" option. In particular, if
# you are sending outgoing mail through a smarthost, it will not
# give any useful information.
#
warn
condition = ${if !def:acl_m1 {true}{false}}
!verify = sender/callout
set acl_m1 = Invalid sender &#60;$sender_address&#62;
message = X-Sender-Verify-Failed: $acl_m1
log_message = $acl_m1
# Accept the sender, but if we previously generated a message in
# $acl_c1, stall the sender until 20 seconds has elapsed.
accept
set acl_m2 = ${if def:acl_c1 {${eval:20 + $acl_m2 - $tod_epoch}}{0}}
delay = ${if &#62;{$acl_m2}{0}{$acl_m2}{0}}s
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="acl_rcpt_to_final"
></A
>A.14.4. acl_rcpt_to</H2
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# This access control list is used for every RCPT command in an
# incoming SMTP message. The tests are run in order until the
# recipient address is either accepted or denied.
acl_rcpt_to:
# Accept mail received over local SMTP (i.e. not over TCP/IP).
# We do this by testing for an empty sending host field.
# Also accept mails received from hosts for which we relay mail.
#
# Recipient verification is omitted here, because in many
# cases the clients are dumb MUAs that don't cope well with
# SMTP error responses.
#
accept
hosts = : +relay_from_hosts
# Accept if the message arrived over an authenticated connection,
# from any host. Again, these messages are usually from MUAs, so
# recipient verification is omitted.
#
accept
authenticated = *
# Deny if the local part contains @ or % or / or | or !. These are
# rarely found in genuine local parts, but are often tried by people
# looking to circumvent relaying restrictions.
#
# Also deny if the local part starts with a dot. Empty components
# aren't strictly legal in RFC 2822, but Exim allows them because
# this is common. However, actually starting with a dot may cause
# trouble if the local part is used as a file name (e.g. for a
# mailing list).
#
deny
local_parts = ^.*[@%!/|] : ^\\.
# Deny if we have previously given a reason for doing so in $acl_m0.
# Also stall the sender for another 20s first.
#
deny
message = $acl_m0
log_message = $acl_m1
condition = ${if and {{def:acl_m0}{def:acl_m1}} {true}}
delay = 20s
# If the recipient address is not in a domain for which we are handling
# mail, stall the sender and reject.
#
deny
message = relay not permitted
!domains = +local_domains : +relay_to_domains
delay = 20s
# If the address is in a local domain or in a domain for which are
# relaying, but is invalid, stall and reject.
#
deny
message = unknown user
!verify = recipient/callout=20s,defer_ok,use_sender
delay = ${if def:sender_address {1m}{0s}}
# Drop the connection if the envelope sender is empty, but there is
# more than one recipient address. Legitimate DSNs are never sent
# to more than one address.
#
drop
message = Legitimate bounces are never sent to more than one \
recipient.
senders = : postmaster@*
condition = $recipients_count
delay = 5m
# --------------------------------------------------------------------
# Limit the number of recipients in each incoming message to one
# to support per-user settings and data (e.g. for SpamAssassin).
#
# NOTE: Every mail sent to several users at your site will be
# delayed for 30 minutes or more per recipient. This
# significantly slow down the pace of discussion threads
# involving several internal and external parties.
# Thus, it is commented out by default.
#
#defer
# message = We only accept one recipient at a time - please try later.
# condition = $recipients_count
# --------------------------------------------------------------------
# Accept the mail if the sending host is matched in the ".forwarders"
# file in the recipient's home directory. Temporarily set $acl_m9 to
# point to this file. If the host is found, set a flag in $acl_m0 and
# clear $acl_m1 to indicate that we should not reject this mail later.
#
accept
domains = +local_domains
set acl_m9 = /home/${extract{1}{=}{${lc:$local_part}}}/.forwarders
hosts = ${if exists {$acl_m9}{$acl_m9}}
set acl_m0 = accept
set acl_m1 =
# Accept the mail if the sending host is matched in the global
# whitelist file. Temporarily set $acl_m9 to point to this file.
# If the host is found, set a flag in $acl_m0 and clear $acl_m1 to
# indicate that we should not reject this mail later.
#
accept
set acl_m9 = /etc/mail/whitelist-hosts
hosts = ${if exists {$acl_m9}{$acl_m9}}
set acl_m0 = accept
set acl_m1 =
# --------------------------------------------------------------------
# Envelope Sender Signature Check.
# This is commented out by default, because it requires additional
# configuration in the 'transports' and 'routers' sections.
#
# Accept the recipient addresss if it contains our own signature.
# This means this is a response (DSN, sender callout verification...)
# to a message that was previously sent from here.
#
#accept
# domains = +local_domains
# condition = ${if and {{match{${lc:$local_part}}{^(.*)=(.*)}}\
# {eq{${hash_8:${hmac{md5}{SECRET}{$1}}}}{$2}}}\
# {true}{false}}
#
# Otherwise, if this message claims to be a bounce (i.e. if there
# is no envelope sender), but if the receiver has elected to use
# and check against envelope sender signatures, reject it.
#
#deny
# message = This address does not match a valid, signed \
# return path from here.\n\
# You are responding to a forged sender address.
# log_message = bogus bounce.
# senders = : postmaster@*
# domains = +local_domains
# set acl_m9 = /home/${extract{1}{=}{${lc:$local_part}}}/.return-path-sign
# condition = ${if exists {$acl_m9}{true}}
# --------------------------------------------------------------------
# --------------------------------------------------------------------
# Deny mail for local users that do not have a mailbox (i.e. postmaster,
# webmaster...) if no sender address is provided. These users do
# not send outgoing mail, so they should not receive returned mail.
#
# NOTE: This is commented out by default, because the condition is
# specific to how local mail is delivered. If you want to
# enable this check, uncomment one and only one of the
# conditions below.
#
#deny
# message = This address never sends outgoing mail. \
# You are responding to a forged sender address.
# log_message = bogus bounce for system user &#60;$local_part@$domain&#62;
# senders = : postmaster@*
# domains = +local_domains
# set acl_m9 = ${extract{1}{=}{${lc:$local_part}}}
#
# --- Uncomment the following 2 lines if recipients have local accounts:
# set acl_m9 = ${extract{2}{:}{${lookup passwd {$acl_m9}{$value}}}{0}}
# !condition = ${if and {{&#62;={$acl_m9}{500}} {&#60;${acl_m9}{60000}}} {true}}
#
# --- Uncomment the following line if you deliver mail to Cyrus:
# condition = ${run {/usr/sbin/mbpath -q -s user.$acl_m9} {true}}
# --------------------------------------------------------------------
# Query the SPF information for the sender address domain, if any,
# to see if the sending host is authorized to deliver its mail.
# If not, reject the mail.
#
deny
message = [SPF] $sender_host_address is not allowed to send mail \
from $sender_address_domain
log_message = SPF check failed.
spf = fail
# Add a SPF-Received: line to the message header
warn
message = $spf_received
# --------------------------------------------------------------------
# Check greylisting status for this particular peer/sender/recipient.
# Before uncommenting this statement, you need to install "greylistd".
# See: http://packages.debian.org/unstable/main/greylistd
#
# Note that we do not greylist messages with NULL sender, because
# sender callout verification would break (and we might not be able
# to send mail to a host that performs callouts).
#
#defer
# message = $sender_host_address is not yet authorized to deliver mail \
# from &#60;$sender_address&#62; to &#60;$local_part@$domain&#62;. \
# Please try later.
# log_message = greylisted.
# domains = +local_domains : +relay_to_domains
# !senders = : postmaster@*
# set acl_m9 = $sender_host_address $sender_address $local_part@$domain
# set acl_m9 = ${readsocket{/var/run/greylistd/socket}{$acl_m9}{5s}{}{}}
# condition = ${if eq {$acl_m9}{grey}{true}{false}}
# delay = 20s
# --------------------------------------------------------------------
# Accept the recipient.
accept
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
><DIV
CLASS="section"
><HR><H2
CLASS="section"
><A
NAME="acl_data_final"
></A
>A.14.5. acl_data</H2
><P
>&#13;<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
>&#13;# This access control list is used for message data received via
# SMTP. The tests are run in order until the recipient address
# is either accepted or denied.
acl_data:
# Log some header lines
warn
logwrite = Subject: $h_Subject:
# Add Message-ID if missing in messages received from our own hosts.
warn
condition = ${if !def:h_Message-ID: {1}}
hosts = +relay_from_hosts
message = Message-ID: &#60;E$message_id@$primary_hostname&#62;
# Accept mail received over local SMTP (i.e. not over TCP/IP).
# We do this by testing for an empty sending host field.
# Also accept mails received from hosts for which we relay mail.
#
accept
hosts = : +relay_from_hosts
# Accept if the message arrived over an authenticated connection, from
# any host.
#
accept
authenticated = *
# Deny if we have previously given a reason for doing so in $acl_m0.
# Also stall the sender for another 20s first.
#
deny
message = $acl_m0
log_message = $acl_m1
condition = ${if and {{def:acl_m0}{def:acl_m1}} {true}{false}}
delay = 20s
# enforce a message-size limit
#
deny
message = Message size $message_size is larger than limit of \
MESSAGE_SIZE_LIMIT
condition = ${if &#62;{$message_size}{MESSAGE_SIZE_LIMIT}{yes}{no}}
# Deny unless the addresses in the header is syntactically correct.
#
deny
message = Your message does not conform to RFC2822 standard
log_message = message header fail syntax check
!verify = header_syntax
# Uncomment the following to deny non-local messages without
# a Message-ID:, Date:, or Subject: header.
#
# Note that some specialized MTAs, such as certain mailing list
# servers, do not automatically generate a Message-ID for bounces.
# Thus, we add the check for a non-empty sender.
#
#deny
# message = Your message does not conform to RFC2822 standard
# log_message = missing header lines
# !hosts = +relay_from_hosts
# !senders = : postmaster@*
# condition = ${if !eq {$acl_m0}{accept}{true}}
# condition = ${if or {{!def:h_Message-ID:}\
# {!def:h_Date:}\
# {!def:h_Subject:}} {true}{false}}
# Warn unless there is a verifiable sender address in at least
# one of the "Sender:", "Reply-To:", or "From:" header lines.
#
warn
message = X-Sender-Verify-Failed: No valid sender in message header
log_message = No valid sender in message header
!verify = header_sender
# --------------------------------------------------------------------
# Perform greylisting on messages with no envelope sender here.
# We did not subject these to greylisting after RCPT TO: because
# that would interfere with remote hosts doing sender callouts.
# Note that the sender address is empty, so we don't bother using it.
#
# Before uncommenting this statement, you need to install "greylistd".
# See: http://packages.debian.org/unstable/main/greylistd
#
#defer
# message = $sender_host_address is not yet authorized to send \
# delivery status reports to &#60;$recipients&#62;. \
# Please try later.
# log_message = greylisted.
# senders = : postmaster@*
# condition = ${if !eq {$acl_m0}{accept}{true}}
# set acl_m9 = $sender_host_address $recipients
# set acl_m9 = ${readsocket{/var/run/greylistd/socket}{$acl_m9}{5s}{}{}}
# condition = ${if eq {$acl_m9}{grey}{true}{false}}
# delay = 20s
# --------------------------------------------------------------------
# --- BEGIN EXISCAN configuration ---
# Reject messages that have serious MIME errors.
#
deny
message = Serious MIME defect detected ($demime_reason)
demime = *
condition = ${if &#62;{$demime_errorlevel}{2}{1}{0}}
# Unpack MIME containers and reject file extensions used by worms.
# This calls the demime condition again, but it will return cached results.
# Note that the extension list may be incomplete.
#
deny
message = We do not accept ".$found_extension" attachments here.
demime = bat:btm:cmd:com:cpl:dll:exe:lnk:msi:pif:prf:reg:scr:vbs:url
# Messages larger than MESSAGE_SIZE_SPAM_MAX are accepted without
# spam or virus scanning
accept
condition = ${if &#62;{$message_size}{MESSAGE_SIZE_SPAM_MAX} {true}}
logwrite = :main: Not classified \
(message size larger than MESSAGE_SIZE_SPAM_MAX)
# --------------------------------------------------------------------
# Anti-Virus scanning
# This requires an 'av_scanner' setting in the main section.
#
#deny
# message = This message contains a virus ($malware_name)
# demime = *
# malware = */defer_ok
# --------------------------------------------------------------------
# Invoke SpamAssassin to obtain $spam_score and $spam_report.
# Depending on the classification, $acl_m9 is set to "ham" or "spam".
#
# If the message is classified as spam, and we have not previously
# set $acl_m0 to indicate that we want to accept it anyway, pretend
# reject it.
#
warn
set acl_m9 = ham
# ------------------------------------------------------------------
# If you want to allow per-user settings for SpamAssassin,
# uncomment the following line, and comment out "spam = mail".
# We pass on the username specified in the recipient address,
# i.e. the portion before any '=' or '@' character, converted
# to lowercase. Multiple recipients should not occur, since
# we previously limited delivery to one recipient at a time.
#
# spam = ${lc:${extract{1}{=@}{$recipients}{$value}{mail}}}
# ------------------------------------------------------------------
spam = mail
set acl_m9 = spam
condition = ${if !eq {$acl_m0}{accept}{true}}
control = fakereject
logwrite = :reject: Rejected spam (score $spam_score): $spam_report
# Add an appropriate X-Spam-Status: header to the message.
#
warn
message = X-Spam-Status: \
${if eq {$acl_m9}{spam}{Yes}{No}} (score $spam_score)\
${if def:spam_report {: $spam_report}}
logwrite = :main: Classified as $acl_m9 (score $spam_score)
# --- END EXISCAN configuration ---
# Accept the message.
#
accept
</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></DIV
></DIV
></DIV
><DIV
CLASS="GLOSSARY"
><H1
><A
NAME="glossary"
></A
>Glossary</H1
><BLOCKQUOTE
CLASS="ABSTRACT"
><DIV
CLASS="abstract"
><A
NAME="AEN2126"
></A
><P
></P
><P
>&#13; These are definitions for some of the words and terms that are
used throughout this document.
</P
><P
></P
></DIV
></BLOCKQUOTE
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2128"
></A
>B</H1
><DL
><DT
><A
NAME="bayesian"
></A
><B
>Bayesian Filters</B
></DT
><DD
><P
>&#13; A filter that assigns a probability of spam based on the
recurrence of words (or, more recently, word
constellations/phrases) between messages.
</P
><P
>&#13; You initially train the filter by feeding it known junk mail
(spam) and known legitimate mail (ham). A bayesian score
is then be assigned to each word (or phrase) in each
message, indicating whether this particular word or phrase
occurs most commonly in ham or in spam. The word, along
with its score, is stored in a <EM
>bayesian
index</EM
>.
</P
><P
>&#13; Such filters may catch indicators that may be missed by
human programmers trying to manually create keyword-based
filters. At the very least, they automate this task.
</P
><P
>&#13; Bayesian word indexes are most certainly specific to the
language in which they received training. Moreover, they are
specific to individual users. Thus, they are perhaps more
suitable for individual content filters (e.g. in <A
HREF="#mua"
><I
CLASS="glossterm"
>Mail User Agent</I
></A
>s) than they are for system-wide, SMTP-time
filtering.
</P
><P
>&#13; Moreover, spammers have developed techniques to defeat
simple bayesian filters, by including random dictionary
words and/or short stories in their messages. This
decreases the spam probability assigned by a baynesian
filter, and in the long run, degrades the quality of the
bayesian index.
</P
><P
>&#13; See also:
<A
HREF="http://www.everything2.com/index.pl?node=Bayesian"
TARGET="_top"
>http://www.everything2.com/index.pl?node=Bayesian</A
>.
</P
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2142"
></A
>C</H1
><DL
><DT
><A
NAME="coldamage"
></A
><B
>Collateral Damage</B
></DT
><DD
><P
>&#13; Blocking of a legitimate sender host due to an entry in a
DNS blocklist.
</P
><P
>&#13; Some blocklists (like SPEWS) routinely list the entire IP
address space of an ISP if they feel the ISP is not
responsive to abuse complaints, thereby affecting
<EM
>all</EM
> its customers.
</P
><P
>&#13; See also: <A
HREF="#falsepos"
><I
CLASS="glossterm"
>False Positive</I
></A
>
</P
></DD
><DT
><A
NAME="colspam"
></A
><B
>Collateral Spam</B
></DT
><DD
><P
>&#13; Automated messages sent in response to an original message
(mostly spam or malware) where the sender address is forged.
Typical examples of collateral spam include virus scan
reports (<SPAN
CLASS="QUOTE"
>"You have a virus"</SPAN
>) or other <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
>s).
</P
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2158"
></A
>D</H1
><DL
><DT
><A
NAME="dns"
></A
><B
>Domain Name System</B
></DT
><DD
><P
>&#13; (<EM
>abbrev: DNS</EM
>) The de-facto standard for
obtaining information about internet domain names. Examples
of such information include IP addresses of its servers
(so-called <EM
>A records</EM
>), the dedication
of incoming mail exchangers (MX records), generic server
information (SRV records), and miscellaneous text
information (TXT records).
</P
><P
>&#13; DNS is a hierarctical, distributed system; each domain name
is associated with a set of one or more DNS servers that
provide information about that domain - including delegation
of name service for its subdomains.
</P
><P
>&#13; For instance, the top-level domain <SPAN
CLASS="QUOTE"
>"org"</SPAN
> is
operated by The Public Interest Registry; its DNS servers
delegate queries for the domain name <SPAN
CLASS="QUOTE"
>"tldp.org"</SPAN
>
to specific name servers for The Linux Documentation
Project. In turn, TLDPs name server (actually operated by
UNC) may or may not delegate queries for third-level names,
such as <SPAN
CLASS="QUOTE"
>"www.tldp.org"</SPAN
>.
</P
><P
>&#13; DNS lookups are usually performed by forwarding name
servers, such as those provided by an Internet Service
Provider (e.g. via DHCP).
</P
></DD
><DT
><A
NAME="dsn"
></A
><B
>Delivery Status Notification</B
></DT
><DD
><P
>&#13; (<EM
>abbrev: DSN</EM
>) A message automatically
created by an MTA or MDA, to inform the sender of an
original messsage (usually included in the DSN) about its
status. For instance, DSNs may inform the sender of the
original message that it could not be delivered due to a
temporary or permanent problem, and/or whether or not and
for how long delivery attempts will continue.
</P
><P
>&#13; Delivery Status Notifications are sent with an empty <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
> address.
</P
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2179"
></A
>E</H1
><DL
><DT
><A
NAME="envfrom"
></A
><B
>Envelope Sender</B
></DT
><DD
><P
>&#13; The e-mail address given as sender of a message during the
SMTP transaction, using the <B
CLASS="command"
>MAIL FROM:</B
>
command. This may be different from the address provided in
the <SPAN
CLASS="QUOTE"
>"From:"</SPAN
> header of the message itself.
</P
><P
>&#13; One special case is <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
> (bounced message,
return receipt, vacation message..). For such mails, the
<A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
> is empty. This is to prevent
<A
HREF="#loop"
><I
CLASS="glossterm"
>Mail Loop</I
></A
>s, and generally to be able to
distinguish these from <SPAN
CLASS="QUOTE"
>"regular"</SPAN
> mails.
</P
><P
>&#13; See also: <A
HREF="#smtpintro"
>The SMTP Transaction</A
>
</P
></DD
><DT
><A
NAME="envto"
></A
><B
>Envelope Recipient</B
></DT
><DD
><P
>&#13; The e-mail address(es) to which the message is sent. These
are provided during the SMTP transaction, using the
<B
CLASS="command"
>RCPT TO</B
> command. These may be different
from the addresses provided in the <SPAN
CLASS="QUOTE"
>"To:"</SPAN
> and
<SPAN
CLASS="QUOTE"
>"Cc:"</SPAN
> headers of the message itself.
</P
><P
>&#13; See also: <A
HREF="#smtpintro"
>The SMTP Transaction</A
>
</P
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2203"
></A
>F</H1
><DL
><DT
><A
NAME="falseneg"
></A
><B
>False Negative</B
></DT
><DD
><P
>&#13; Junk mail (spam, virus, malware) that is misclassified as
legitimate mail (and consequently, not filtered out).
</P
></DD
><DT
><A
NAME="falsepos"
></A
><B
>False Positive</B
></DT
><DD
><P
>&#13; Legitimate mail that is misclassified as junk (and
consequently, blocked).
</P
><P
>&#13; See also: <A
HREF="#coldamage"
><I
CLASS="glossterm"
>Collateral Damage</I
></A
>.
</P
></DD
><DT
><A
NAME="fqdn"
></A
><B
>Fully Qualified Domain Name</B
></DT
><DD
><P
>&#13; (a.k.a. <SPAN
CLASS="QUOTE"
>"FQDN"</SPAN
>). A full, globally unique,
internet name, including DNS domain. For instance:
<SPAN
CLASS="QUOTE"
>"www.yahoo.com"</SPAN
>.
</P
><P
>&#13; A <EM
>FQDN</EM
> does not always point to a single
host. For instance, common service names such as
<SPAN
CLASS="QUOTE"
>"www"</SPAN
> often point to many IP addresses, in
order to provide some load balancing on the servers.
However, the <EM
>primary</EM
> host name of a
given machine should always be unique to that machine; for
instance: <SPAN
CLASS="QUOTE"
>"p16.www.scd.yahoo.com"</SPAN
>.
</P
><P
>&#13; A <EM
>FQDN</EM
> always contains a period (".").
The part before the first period is the
<EM
>unqualified name</EM
>, and is not globally
unique.
</P
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2229"
></A
>J</H1
><DL
><DT
><A
NAME="joejob"
></A
><B
>Joe Job</B
></DT
><DD
><P
>&#13; A spam designed to look like it came from someone else's
valid address, often in a malicous attempt at generating
complaints from third parties and/or cause other damage to
the owner of that address.
</P
><P
>&#13; See also:
<A
HREF="http://www.everything2.com/index.pl?node=Joe%20Job"
TARGET="_top"
>http://www.everything2.com/index.pl?node=Joe%20Job</A
>
</P
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2237"
></A
>M</H1
><DL
><DT
><A
NAME="mda"
></A
><B
>Mail Delivery Agent</B
></DT
><DD
><P
>&#13; (<EM
>abbrev: MDA</EM
>) Software that runs on the
machine where a users' mailbox is located, to deliver mail
into that mailbox. Often, that delivery is performed
directly by the MTA <A
HREF="#mta"
><I
CLASS="glossterm"
>Mail Transport Agent</I
></A
>, which then
serves a secondary role as an MDA. Examples of separate
Mail Delivery Agents include: Deliver, Procmail, Cyrmaster
and/or Cyrdeliver (from the Cyrus IMAP suite).
</P
></DD
><DT
><A
NAME="loop"
></A
><B
>Mail Loop</B
></DT
><DD
><P
>&#13; A situation where one automated message triggers another,
which directly or indirectly triggers the first message
over again, and so on.
</P
><P
>&#13; Imagine a mailing list where one of the subscribers is the
address of the list itself. This situation is often dealt
with by the list server adding an <SPAN
CLASS="QUOTE"
>"X-Loop:"</SPAN
>
line in the message header, and not processing mails that
already have one.
</P
><P
>&#13; Another equivalent term is <EM
>Ringing</EM
>.
</P
></DD
><DT
><A
NAME="mta"
></A
><B
>Mail Transport Agent</B
></DT
><DD
><P
>&#13; (<EM
>abbrev: MTA</EM
>) Software that runs on a
mail server, such as the mail exchanger(s) of a internet
domain, to send mail to and receive mail from other hosts.
Popular MTAs include: Sendmail, Postfix, Exim, Smail.
</P
></DD
><DT
><A
NAME="mua"
></A
><B
>Mail User Agent</B
></DT
><DD
><P
>&#13; (<EM
>abbrev: MUA</EM
>; a.k.a. <EM
>Mail
Reader</EM
>) User software to access, download, read,
and send mail. Examples include Microsoft Outlook/Outlook
Express, Apple Mail.app, Mozilla Thunderbird, Ximian
Evolution.
</P
></DD
><DT
><A
NAME="mx"
></A
><B
>Mail Exchanger</B
></DT
><DD
><P
>&#13; (<EM
>abbrev: MX</EM
>) A machine dedicated to
(sending and/or) receiving mail for an internet domain.
</P
><P
>&#13; The DNS zone information for a internet domain normally
contains a list of <A
HREF="#fqdn"
><I
CLASS="glossterm"
>Fully Qualified Domain Name</I
></A
>s that act as
incoming mail exchangers for that domain. Each such listing
is called an <SPAN
CLASS="QUOTE"
>"MX record"</SPAN
>, and it also contains
a number indicating its <SPAN
CLASS="QUOTE"
>"priority"</SPAN
> among
several <SPAN
CLASS="QUOTE"
>"MX records"</SPAN
>. The listing with the
lowest number has the first priority, and is considered the
<SPAN
CLASS="QUOTE"
>"primary mail exchanger"</SPAN
> for that domain.
</P
></DD
><DT
><A
NAME="micropay"
></A
><B
>Micropayment Schemes</B
></DT
><DD
><P
>&#13; (a.k.a. <EM
>sender pay</EM
> schemes). The
sender of a message expends some machine resources to create
a virtual <EM
>postage stamp</EM
> for each
recipient of a message - usually by solving a mathematical
challenge that requires a large number of memory read/write
operations, but is relatively CPU speed insensitive. This
stamp is then added to the headers of the message, and the
recipient would validate the stamp through a much simpler
decoding operation.
</P
><P
>&#13; The idea is that because the message requires a postage
stamp for every recipient address, spamming hundreds or
thousands of users at once would be prohibitively
"expensive".
</P
><P
>&#13; Two such systems are:
</P
><P
></P
><UL
><LI
><P
>&#13; <A
HREF="http://www.camram.org/"
TARGET="_top"
>Camram</A
>
</P
></LI
><LI
><P
>&#13; <A
HREF="http://research.microsoft.com/research/sv/PennyBlack/"
TARGET="_top"
>Microsoft's
Penny Black Project</A
>
</P
></LI
></UL
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2290"
></A
>O</H1
><DL
><DT
><A
NAME="openproxy"
></A
><B
>Open Proxy</B
></DT
><DD
><P
>&#13; A <A
HREF="#proxy"
><I
CLASS="glossterm"
>proxy</I
></A
> which openly accepts TCP/IP
connections from anywhere, and forwards them anywhere.
</P
><P
>&#13; These are typically exploited by spammers and virii, who
use them to conceal their own IP address, and/or to more
effectively distribute transmission loads across several
hosts and networks.
</P
><P
>&#13; See also: <A
HREF="#zombie"
><I
CLASS="glossterm"
>Zombie Host</I
></A
>
</P
></DD
><DT
><A
NAME="openrelay"
></A
><B
>Open Relay</B
></DT
><DD
><P
>&#13; A <A
HREF="#relay"
><I
CLASS="glossterm"
>Relay</I
></A
> which openly accepts mail from
anywhere, and forwards them to anywhere.
</P
><P
>&#13; In the 1980s, virtually every public SMTP server was an
<A
HREF="#openrelay"
><I
CLASS="glossterm"
>Open Relay</I
></A
>. Messages would often travel
between multiple third-party machines before it reached the
intended recipient. Now, legitimate mail are almost
exclusively sent directly from an outgoing <A
HREF="#mta"
><I
CLASS="glossterm"
>Mail Transport Agent</I
></A
> on the sender's end to the incoming <A
HREF="#mx"
><I
CLASS="glossterm"
>Mail Exchanger</I
></A
>(s) for the recipient's domain.
</P
><P
>&#13; Conversely, <A
HREF="#openrelay"
><I
CLASS="glossterm"
>Open Relay</I
></A
> servers that still
exist on the internet are almost exclusively exploited by
spammers to hide their own identity, and to perform some
load balancing on the task of sending out millions of
messages, presumably before DNS blocklists have a chance to
get all of these machines listed.
</P
><P
>&#13; See also the discussion on <A
HREF="#relayprevent"
>Open Relay Prevention</A
>.
</P
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2313"
></A
>P</H1
><DL
><DT
><A
NAME="proxy"
></A
><B
>proxy</B
></DT
><DD
><P
>&#13; A machine that acts on behalf of someone else. It may
forward e.g. HTTP requests or TCP/IP connections, usually to
or from the internet. For instance, companies - or
sometimes entire countries - often use <SPAN
CLASS="QUOTE"
>"Web Proxy
Servers"</SPAN
> to filter outgoing HTTP requests from their
internal network. This may or may not be transparent to the
end user.
</P
><P
>&#13; See also: <A
HREF="#openproxy"
><I
CLASS="glossterm"
>Open Proxy</I
></A
>, <A
HREF="#relay"
><I
CLASS="glossterm"
>Relay</I
></A
>.
</P
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2323"
></A
>R</H1
><DL
><DT
><A
NAME="ratware"
></A
><B
>Ratware</B
></DT
><DD
><P
>&#13; Mass-mailing virii and e-mail software used by spammers,
specifically designed to deliver large amounts of mail in a
very short time.
</P
><P
>&#13; Most ratware implementations incorporate only as much SMTP
client code as strictly neccessary to deliver mail in the
best-case scenario. They provide false or inaccurate
information in the SMTP dialogue with the receiving host.
They do not wait for responses from the receiver before
issuing commands, and disconnect if no response has been
received in a few seconds. They do not follow normal retry
mechanisms in case of temporary failures.
</P
></DD
><DT
><A
NAME="relay"
></A
><B
>Relay</B
></DT
><DD
><P
>&#13; A machine that forwards e-mail, usually to or from the
internet. One example of a relay is the
<SPAN
CLASS="QUOTE"
>"smarthost"</SPAN
> that an ISP provides to its
customers for sending outgoing mail.
</P
><P
>&#13; See also: <A
HREF="#openrelay"
><I
CLASS="glossterm"
>Open Relay</I
></A
>, <A
HREF="#proxy"
><I
CLASS="glossterm"
>proxy</I
></A
>
</P
></DD
><DT
><A
NAME="rfc"
></A
><B
>Request for Comments</B
></DT
><DD
><P
>&#13; (<EM
>abbrev: RFC</EM
>) From
<A
HREF="http://www.rfc-editor.org/"
TARGET="_top"
>http://www.rfc-editor.org/</A
>:
<SPAN
CLASS="QUOTE"
>"
The Request for Comments (RFC) document series is a set of
technical and organizational notes about the internet
[...]. Memos in the RFC series discuss many aspects of
computer networking, incluing protocols, procedures,
programs, and concepts, as well as meeting notes,
opinions, and sometimes humor.
"</SPAN
>
</P
><P
>&#13; These documents make up the <SPAN
CLASS="QUOTE"
>"rules"</SPAN
> internet
conduct, including descriptions of protocols and data
formats. Of particular interest for mail deliveries are:
<P
></P
><UL
><LI
><P
>&#13; <A
HREF="http://www.ietf.org/rfc/rfc2821"
TARGET="_top"
>RFC
2821</A
>, "Simple Mail transfer Protocol", and
</P
></LI
><LI
><P
>&#13; <A
HREF="http://www.ietf.org/rfc/rfc2821"
TARGET="_top"
>RFC
2822</A
>, "Internet Message Format".
</P
></LI
></UL
>
</P
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2354"
></A
>S</H1
><DL
><DT
><A
NAME="spamtrap"
></A
><B
>Spam Trap</B
></DT
><DD
><P
>&#13; An e-mail address that is <EM
>seeded</EM
> to
address-harvesting robots via public locations, then used to
feed collaborative tools such as <A
HREF="#dnsbl"
>DNS Blacklists</A
> and
<A
HREF="#jmsr"
>Junk Mail Signature Repository</A
>.
</P
><P
>&#13; Mails sent to these addresses are normally spam or malware.
However, some of it will be <EM
>collateral</EM
>,
spam - i.e. <A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
> to faked sender addresses.
Thus, unless the spam trap has safeguards in place to
disregard such messages, the resulting tool may not be
completely reliable.
</P
></DD
></DL
></DIV
><DIV
CLASS="glossdiv"
><H1
CLASS="glossdiv"
><A
NAME="AEN2366"
></A
>Z</H1
><DL
><DT
><A
NAME="zombie"
></A
><B
>Zombie Host</B
></DT
><DD
><P
>&#13; A machine with an internet connection that is infected by a
mass-mailing virus or worm. Such machines invariably run a
flavor of the Microsoft<66> Windows<77> operating system,
and are almost always in <SPAN
CLASS="QUOTE"
>"residential"</SPAN
> IP
address blocks. Their owners either do not know or do not
care that the machines are infected, and often, their ISP
will not take any actions to shut them down.
</P
><P
>&#13; Fortunately, there are various DNS blocklists, such as
<SPAN
CLASS="QUOTE"
>"dul.dnsbl.sorbs.net"</SPAN
>, that incorporate such
"residential" address blocks. You should be able to use
these blocklists to reject incoming mail. Legitimate mail
from residential users should normally go through their
ISP's <SPAN
CLASS="QUOTE"
>"smarthost"</SPAN
>.
</P
></DD
></DL
></DIV
></DIV
><DIV
CLASS="appendix"
><HR><H1
><A
NAME="gpl"
></A
>Appendix B. GNU General Public License</H1
><DIV
CLASS="sect1"
><H1
CLASS="sect1"
><A
NAME="gpl-1"
></A
>B.1. Preamble</H1
><P
> The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public License is
intended to guarantee your freedom to share and change
free software - to make sure the software is free for all its users.
This General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit
to using it. (Some other Free Software Foundation software is covered
by the GNU Library General Public License instead.) You can apply it
to your programs, too.
</P
><P
> When we speak of free software, we are referring to freedom, not price.
Our General Public Licenses are designed to make sure that you have the
freedom to distribute copies of free software (and charge for this
service if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
</P
><P
> To protect your rights, we need to make restrictions that forbid anyone
to deny you these rights or to ask you to surrender the rights. These
restrictions translate to certain responsibilities for you if you distribute
copies of the software, or if you modify it.
</P
><P
> For example, if you distribute copies of such a program, whether gratis or
for a fee, you must give the recipients all the rights that you have. You
must make sure that they, too, receive or can get the source code. And you
must show them these terms so they know their rights.
</P
><P
> We protect your rights with two steps:
<P
></P
><OL
TYPE="1"
><LI
><P
> copyright the software, and
</P
></LI
><LI
><P
> offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
</P
></LI
></OL
>
</P
><P
> Also, for each author's protection and ours, we want to make certain that
everyone understands that there is no warranty for this free software. If
the software is modified by someone else and passed on, we want its
recipients to know that what they have is not the original, so that any
problems introduced by others will not reflect on the original authors'
reputations.
</P
><P
> Finally, any free program is threatened constantly by software patents.
We wish to avoid the danger that redistributors of a free program will
individually obtain patent licenses, in effect making the program
proprietary. To prevent this, we have made it clear that any patent must be
licensed for everyone's free use or not licensed at all.
</P
><P
> The precise terms and conditions for copying, distribution and modification
follow.
</P
></DIV
><DIV
CLASS="sect1"
><HR><H1
CLASS="sect1"
><A
NAME="gpl-2"
></A
>B.2. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H1
><DIV
CLASS="sect2"
><H2
CLASS="sect2"
><A
NAME="gpl-2-0"
></A
>B.2.1. Section 0</H2
><P
> This License applies to any program or other work which contains a notice
placed by the copyright holder saying it may be distributed under the terms
of this General Public License. The "Program", below, refers to any such
program or work, and a
<SPAN
CLASS="QUOTE"
>"work based on the Program
"</SPAN
> means either
the Program or any derivative work under copyright law: that is to say, a
work containing the Program or a portion of it, either verbatim or with
modifications and/or translated into another language. (Hereinafter, translation
is included without limitation in the term
<SPAN
CLASS="QUOTE"
>"modification
"</SPAN
>.) Each licensee is addressed as <SPAN
CLASS="QUOTE"
>"you"</SPAN
>.
</P
><P
> Activities other than copying, distribution and modification are not covered by
this License; they are outside its scope. The act of running the Program is not
restricted, and the output from the Program is covered only if its contents
constitute a work based on the Program (independent of having been made by running
the Program). Whether that is true depends on what the Program does.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-1"
></A
>B.2.2. Section 1</H2
><P
> You may copy and distribute verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and appropriately
publish on each copy an appropriate copyright notice and disclaimer of warranty;
keep intact all the notices that refer to this License and to the absence of any
warranty; and give any other recipients of the Program a copy of this License
along with the Program.
</P
><P
> You may charge a fee for the physical act of transferring a copy, and you may at
your option offer warranty protection in exchange for a fee.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-2"
></A
>B.2.3. Section 2</H2
><P
> You may modify your copy or copies of the Program or any portion of it, thus
forming a work based on the Program, and copy and distribute such modifications
or work under the terms of
<A
HREF="#gpl-2-1"
>Section 1
</A
> above, provided
that you also meet all of these conditions:
<P
></P
><OL
TYPE="1"
><LI
><P
> You must cause the modified files to carry prominent notices stating that
you changed the files and the date of any change.
</P
></LI
><LI
><P
> You must cause any work that you distribute or publish, that in whole or
in part contains or is derived from the Program or any part thereof, to be
licensed as a whole at no charge to all third parties under the terms of
this License.
</P
></LI
><LI
><P
> If the modified program normally reads commands interactively when run, you
must cause it, when started running for such interactive use in the most
ordinary way, to print or display an announcement including an appropriate
copyright notice and a notice that there is no warranty (or else, saying
that you provide a warranty) and that users may redistribute the program
under these conditions, and telling the user how to view a copy of this
License.
<DIV
CLASS="note"
><P
></P
><TABLE
CLASS="note"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="../images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TH
ALIGN="LEFT"
VALIGN="CENTER"
><B
>Exception:</B
></TH
></TR
><TR
><TD
>&nbsp;</TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
> If the Program itself is interactive but does not normally print such an
announcement, your work based on the Program is not required to print an
announcement.)
</P
></TD
></TR
></TABLE
></DIV
>
</P
></LI
></OL
>
</P
><P
> These requirements apply to the modified work as a whole. If identifiable sections
of that work are not derived from the Program, and can be reasonably considered
independent and separate works in themselves, then this License, and its terms,
do not apply to those sections when you distribute them as separate works. But when
you distribute the same sections as part of a whole which is a work based on the
Program, the distribution of the whole must be on the terms of this License, whose
permissions for other licensees extend to the entire whole, and thus to each and
every part regardless of who wrote it.
</P
><P
> Thus, it is not the intent of this section to claim rights or contest your rights
to work written entirely by you; rather, the intent is to exercise the right to control
the distribution of derivative or collective works based on the Program.
</P
><P
> In addition, mere aggregation of another work not based on the Program with the Program
(or with a work based on the Program) on a volume of a storage or distribution medium
does not bring the other work under the scope of this License.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-3"
></A
>B.2.4. Section 3</H2
><P
> You may copy and distribute the Program (or a work based on it, under
<A
HREF="#gpl-2-2"
>Section 2
</A
> in object code or executable form under the terms of
<A
HREF="#gpl-2-1"
>Sections 1
</A
> and
<A
HREF="#gpl-2-2"
>2
</A
> above provided that you also do one of the following:
<P
></P
><OL
TYPE="1"
><LI
><P
> Accompany it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
</P
></LI
><LI
><P
> Accompany it with a written offer, valid for at least three years, to give any
third party, for a charge no more than your cost of physically performing source
distribution, a complete machine-readable copy of the corresponding source code,
to be distributed under the terms of Sections 1 and 2 above on a medium customarily
used for software interchange; or,
</P
></LI
><LI
><P
> Accompany it with the information you received as to the offer to distribute
corresponding source code. (This alternative is allowed only for noncommercial
distribution and only if you received the program in object code or executable form
with such an offer, in accord with Subsection b above.)
</P
></LI
></OL
>
</P
><P
> The source code for a work means the preferred form of the work for making modifications
to it. For an executable work, complete source code means all the source code for all modules
it contains, plus any associated interface definition files, plus the scripts used to control
compilation and installation of the executable. However, as a special exception, the source
code distributed need not include anything that is normally distributed (in either source or
binary form) with the major components (compiler, kernel, and so on) of the operating system
on which the executable runs, unless that component itself accompanies the executable.
</P
><P
> If distribution of executable or object code is made by offering access to copy from a
designated place, then offering equivalent access to copy the source code from the same place
counts as distribution of the source code, even though third parties are not compelled to
copy the source along with the object code.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-4"
></A
>B.2.5. Section 4</H2
><P
> You may not copy, modify, sublicense, or distribute the Program except as expressly provided
under this License. Any attempt otherwise to copy, modify, sublicense or distribute the
Program is void, and will automatically terminate your rights under this License. However,
parties who have received copies, or rights, from you under this License will not have their
licenses terminated so long as such parties remain in full compliance.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-5"
></A
>B.2.6. Section 5</H2
><P
> You are not required to accept this License, since you have not signed it. However, nothing
else grants you permission to modify or distribute the Program or its derivative works.
These actions are prohibited by law if you do not accept this License. Therefore, by modifying
or distributing the Program (or any work based on the Program), you indicate your acceptance
of this License to do so, and all its terms and conditions for copying, distributing or
modifying the Program or works based on it.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-6"
></A
>B.2.7. Section 6</H2
><P
> Each time you redistribute the Program (or any work based on the Program), the recipient
automatically receives a license from the original licensor to copy, distribute or modify
the Program subject to these terms and conditions. You may not impose any further restrictions
on the recipients' exercise of the rights granted herein. You are not responsible for enforcing
compliance by third parties to this License.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-7"
></A
>B.2.8. Section 7</H2
><P
> If, as a consequence of a court judgment or allegation of patent infringement or for any other
reason (not limited to patent issues), conditions are imposed on you (whether by court order,
agreement or otherwise) that contradict the conditions of this License, they do not excuse you
from the conditions of this License. If you cannot distribute so as to satisfy simultaneously
your obligations under this License and any other pertinent obligations, then as a consequence
you may not distribute the Program at all. For example, if a patent license would not permit
royalty-free redistribution of the Program by all those who receive copies directly or
indirectly through you, then the only way you could satisfy both it and this License would be
to refrain entirely from distribution of the Program.
</P
><P
> If any portion of this section is held invalid or unenforceable under any particular circumstance,
the balance of the section is intended to apply and the section as a whole is intended to apply
in other circumstances.
</P
><P
> It is not the purpose of this section to induce you to infringe any patents or other property
right claims or to contest validity of any such claims; this section has the sole purpose of
protecting the integrity of the free software distribution system, which is implemented by public
license practices. Many people have made generous contributions to the wide range of software
distributed through that system in reliance on consistent application of that system; it is up
to the author/donor to decide if he or she is willing to distribute software through any other
system and a licensee cannot impose that choice.
</P
><P
> This section is intended to make thoroughly clear what is believed to be a consequence of the
rest of this License.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-8"
></A
>B.2.9. Section 8</H2
><P
> If the distribution and/or use of the Program is restricted in certain countries either by patents
or by copyrighted interfaces, the original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding those countries, so that
distribution is permitted only in or among countries not thus excluded. In such case, this License
incorporates the limitation as if written in the body of this License.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-9"
></A
>B.2.10. Section 9</H2
><P
> The Free Software Foundation may publish revised and/or new versions of the General Public License
from time to time. Such new versions will be similar in spirit to the present version, but may differ
in detail to address new problems or concerns.
</P
><P
> Each version is given a distinguishing version number. If the Program specifies a version number of
this License which applies to it and "any later version", you have the option of following the terms
and conditions either of that version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of this License, you may choose any
version ever published by the Free Software Foundation.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-10"
></A
>B.2.11. Section 10</H2
><P
> If you wish to incorporate parts of the Program into other free programs whose distribution
conditions are different, write to the author to ask for permission. For software which is copyrighted
by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions
for this. Our decision will be guided by the two goals of preserving the free status of all
derivatives of our free software and of promoting the sharing and reuse of software generally.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-11"
></A
>B.2.12. NO WARRANTY Section 11</H2
><P
> BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT
PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
</P
></DIV
><DIV
CLASS="sect2"
><HR><H2
CLASS="sect2"
><A
NAME="gpl-2-12"
></A
>B.2.13. Section 12</H2
><P
> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR
ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH
ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
</P
><P
>END OF TERMS AND CONDITIONS
</P
></DIV
></DIV
><DIV
CLASS="sect1"
><HR><H1
CLASS="sect1"
><A
NAME="gpl-3"
></A
>B.3. How to Apply These Terms to Your New Programs</H1
><P
>&#13; If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
</P
><P
>&#13; To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
</P
><P
>&#13; &#60;one line to give the program's name and a brief idea of what it does.&#62;
Copyright (C) &#60;year&#62; &#60;name of author&#62;
</P
><P
>&#13; This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
</P
><P
>&#13; This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
</P
><P
>&#13; You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
</P
><P
>&#13; Also add information on how to contact you by electronic and paper mail.
</P
><P
>&#13; If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
</P
><P
>&#13; Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
</P
><P
>&#13; The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
</P
><P
>&#13; You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
</P
><P
>&#13; Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
</P
><P
>&#13; &#60;signature of Ty Coon&#62;, 1 April 1989
Ty Coon, President of Vice
</P
><P
>&#13; This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
</P
></DIV
></DIV
></DIV
><H3
CLASS="FOOTNOTES"
>Notes</H3
><TABLE
BORDER="0"
CLASS="FOOTNOTES"
WIDTH="100%"
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN419"
HREF="#AEN419"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; Untrusted third party hosts may still generate
collateral spam if you reject the mail. However,
unless that host is an <A
HREF="#openproxy"
><I
CLASS="glossterm"
>Open Proxy</I
></A
> or
<A
HREF="#openrelay"
><I
CLASS="glossterm"
>Open Relay</I
></A
>, it presumably delivers
mail only from legitimate senders, whose addresses are
valid. If it <EM
>is</EM
> an Open Proxy or
SMTP Relay - well, it is better that you reject the
mail and let it freeze in <EM
>their</EM
>
outgoing mail queue than letting it freeze in yours.
Eventually, this ought to give the owners of that
server a clue.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN452"
HREF="#AEN452"
><SPAN
CLASS="footnote"
>[2]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; Personally I do not think challenge/response systems are
a good idea in any case. They generate <A
HREF="#colspam"
><I
CLASS="glossterm"
>Collateral Spam</I
></A
>, they require special attention for
mail sent from automated sources such as monthly bank
statements, and they degrade the usability of e-mail as
people need to jump through hoops to get in touch with
each other. Many times, senders of legitimate mail will
not bother to or know that they need to follow up to the
confirmation request, and the mail is lost.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN465"
HREF="#AEN465"
><SPAN
CLASS="footnote"
>[3]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; My view stands in sharp contrast to that of a large number
of <SPAN
CLASS="QUOTE"
>"spam hacktivists"</SPAN
>, such as the maintainers
of the <A
HREF="http://www.spews.org/"
TARGET="_top"
>SPEWS</A
>
<A
HREF="#dnsbl"
>blacklist</A
>. One of the stated
aims of this list is precisely to inflict <A
HREF="#coldamage"
><I
CLASS="glossterm"
>Collateral Damage</I
></A
> as a means of putting pressure on ISPs
to react on abuse complaints. Listing complaints are
typically met with knee-jerk responses such as <SPAN
CLASS="QUOTE"
>"bother
your ISP, not us"</SPAN
>, or <SPAN
CLASS="QUOTE"
>"get another ISP"</SPAN
>.
</P
><P
>&#13; Often, these are not viable options. Consider developing
countries. For that matter, consider the fact that nearly
everywhere, broadband providers are regulated monopolies. I
believe that these attitudes illustrate the exact crux of
the problem with trusting these groups.
</P
><P
>&#13; Put plainly, there are much better and more accurate ways
available to filter junk mail.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN632"
HREF="#AEN632"
><SPAN
CLASS="footnote"
>[4]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; Beware that while you are holding up an incoming SMTP
delivery, you are also holding up a TCP socket on your
server, as well as memory and other server resources. If
your server is generally busy, imposing SMTP transaction
delays will make you more vulnerable to Denial-of-Service
attacks. A more <SPAN
CLASS="QUOTE"
>"scalable"</SPAN
> option may be to
drop the connection once you have conclusive evidence that
the sender is a ratware client.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN649"
HREF="#AEN649"
><SPAN
CLASS="footnote"
>[5]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; Similar lists exist for different purposes. For instance,
<SPAN
CLASS="QUOTE"
>"bondedsender.org"</SPAN
> is a <EM
>DNS
whitelist</EM
> (DNSwl), containing
<SPAN
CLASS="QUOTE"
>"trusted"</SPAN
> IP addresses, whose owners have
posted a financial bond that will be debited in the event
that spam originates from that address. Other lists
contain IP addresses in use by specific countries,
specific ISPs, etc.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN661"
HREF="#AEN661"
><SPAN
CLASS="footnote"
>[6]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; For instance, the outgoing mail exchangers (<SPAN
CLASS="QUOTE"
>"smart
hosts"</SPAN
>) of the world's largest Internet Service
Provider (ISP), comcast.net, is as of the time of this
writing included in the SPEWS <EM
>Level 1</EM
>
list. Not wholly undeserved from the viewpoint that
Comcast needs to more effectively enforce their own AUP,
but this listing does affect 30% of all US internet users,
mostly <SPAN
CLASS="QUOTE"
>"innocent"</SPAN
> subscribers such as myself.
</P
><P
>&#13; To make matters worse, information published in the <A
HREF="http://spews.org/faq.html"
TARGET="_top"
>SPEWS FAQ</A
> states:
<EM
>&#13; The majority of the Level 1 list is made up of netblocks
owned by the spammers or spam support operations
themselves, with few or no other legitimate customers
detected.
</EM
>
Technically, this information is accurate if (a) you
consider Comcast a <SPAN
CLASS="QUOTE"
>"spam support operation"</SPAN
>,
and (b) pay attention to the word <SPAN
CLASS="QUOTE"
>"other"</SPAN
>.
Word parsing aside, this information is clearly misleading.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN718"
HREF="#AEN718"
><SPAN
CLASS="footnote"
>[7]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; Although this check is normally quite effective at
weeding out junk, there are reports of buggy L-Soft
<A
HREF="http://www.lsoft.com/products/default.asp?item=listserv"
TARGET="_top"
>listserv</A
>
installations that greet with the plain IP address of
the list server.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN756"
HREF="#AEN756"
><SPAN
CLASS="footnote"
>[8]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; A special case is the NULL envelope sender address
(i.e. <B
CLASS="command"
>MAIL FROM:</B
> &#60;&#62;) used in
<A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
>s and other automatically generated
responses. This address should always be accepted.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.noretrysenders"
HREF="#noretrysenders"
><SPAN
CLASS="footnote"
>[9]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; Although rare, some <SPAN
CLASS="QUOTE"
>"legitimate"</SPAN
> bulk mail
senders, such as <TT
CLASS="option"
>groups.yahoo.com</TT
>, will not
retry temporarily failed deliveries. Evan Harris has
compiled a list of such senders, suitable for whitelisting
purposes:
<A
HREF="http://cvs.puremagic.com/viewcvs/greylisting/schema/whitelist_ip.txt?view=markup"
TARGET="_top"
>http://cvs.puremagic.com/viewcvs/greylisting/schema/whitelist_ip.txt?view=markup</A
>.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN914"
HREF="#AEN914"
><SPAN
CLASS="footnote"
>[10]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; Large sites often use multiple servers to handle outgoing
mail. For instance, one server or pool of servers may be
used for immediate delivery. If the first delivery
attempt fails, the mail is handed off to a fallback server
which has been tuned for large queues. Hence, from such
sites, the first two delivery attempts will fail.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1045"
HREF="#AEN1045"
><SPAN
CLASS="footnote"
>[11]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; Some specialized MTAs, such as certain mailing list
servers, do not automatically generate a
<TT
CLASS="option"
>Message-ID:</TT
> header for
<SPAN
CLASS="QUOTE"
>"bounced"</SPAN
> messages (<A
HREF="#dsn"
><I
CLASS="glossterm"
>Delivery Status Notification</I
></A
>s). These messages are identified by an
empty <A
HREF="#envfrom"
><I
CLASS="glossterm"
>Envelope Sender</I
></A
>.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1096"
HREF="#AEN1096"
><SPAN
CLASS="footnote"
>[12]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; The IMAP protocol does not allow for NUL characters to be
transmitted to the mail user agent, so the Cyrus
developers decided that the easiest way to deal with mails
containing it was to reject them.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1165"
HREF="#AEN1165"
><SPAN
CLASS="footnote"
>[13]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>Why on earth the authors
of anti-virus software are stupid enough to trust the sender
address in an e-mail containing a virus is perhaps a topic for
a closer psychoanalytic study.</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1361"
HREF="#AEN1361"
><SPAN
CLASS="footnote"
>[14]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; In particular, Exim is perhaps most popular among users of
<A
HREF="http://www.debian.org/"
TARGET="_top"
>Debian GNU/Linux</A
>,
as it is the default MTA in that distribution. If you use
Debian (<SPAN
CLASS="QUOTE"
>"Sarge"</SPAN
> or later), you can obtain
Exim+Exiscan-ACL by installing the
<TT
CLASS="option"
>exim4-daemon-heavy</TT
> package:
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="screen"
># apt-get install exim4-daemon-heavy</PRE
></FONT
></TD
></TR
></TABLE
>
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1380"
HREF="#AEN1380"
><SPAN
CLASS="footnote"
>[15]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; <EM
>Debian users:</EM
> The
<TT
CLASS="option"
>exim4-config</TT
> package gives you a choice
between splitting the Exim configuration into several small
chunks distributed within subdirectories below
<TT
CLASS="option"
>/etc/exim4/conf.d</TT
>, or to keep the entire
configuration in a single file.
</P
><P
>&#13; If you chose the former option (I recommend this!), you can
keep your customization well separated from the stock
configuration provided with the <TT
CLASS="option"
>exim4-config</TT
>
package by creating new files within these subdirectories,
rather than modifying the existing ones. For instance, you
may create a file named
<TT
CLASS="option"
>/etc/exim4/conf.d/acl/80_local-config_rcpt_to</TT
>
to declare your own ACL for the <B
CLASS="command"
>RCPT TO:</B
>
command (see <A
HREF="#acl_rcpt_to_1"
>below</A
>).
</P
><P
>&#13; The Exim <SPAN
CLASS="QUOTE"
>"init"</SPAN
> script
(<TT
CLASS="option"
>/etc/init.d/exim4</TT
>) will automatically
consolidate all these files into a single large run-time
configuration file next time you (re)start.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1692"
HREF="#AEN1692"
><SPAN
CLASS="footnote"
>[16]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; Debian users: As of July 14th, 2004, the version of
Exiscan-ACL that is included in the
<TT
CLASS="option"
>exim4-daemon-heavy</TT
> package does not yet
have support for SPF. In the mean time, you may choose
the other SPF implementation; install
<TT
CLASS="option"
>libmail-spf-query-perl</TT
>.
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1828"
HREF="#AEN1828"
><SPAN
CLASS="footnote"
>[17]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; Although it is true that Bayesian training is specific to
each user, it should be noted that SpamAssassin's
Bayesian classifier is, IMHO, not that stellar in any case.
Especially I find this to be the case since spammers have
learned to defeat such systems by seeding random dictionary
words or stories in their mail (e.g. in the metadata of
HTML messages).
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1936"
HREF="#AEN1936"
><SPAN
CLASS="footnote"
>[18]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; If you think this is an overkill, would I tend to
agree on the surface. In previous versions of
this document, I simply used
<TT
CLASS="option"
>${hash_8:SECRET=....}</TT
> to generate
the last component of the signature. However,
with this it would be technically possible, with a
bit of insight into Exim's
<TT
CLASS="option"
>${hash...}</TT
> function and some
samples of your outgoing mail sent to different
recipients, to forge the signature. Matthew
Byng-Maddic <TT
CLASS="email"
>&#60;<A
HREF="mailto:mbm (at) colondot.net"
>mbm (at) colondot.net</A
>&#62;</TT
>
notes:
<EM
>&#13; What you're writing is a document that you
expect many people to just copy. Given that,
kerchoff's principle starts applying, and all of
your secrecy should be in the key. If the key
can be reversed out, as seems likely with a few
return paths, then the spammer kan once again
start emitting valid return-paths from that
domain, and you're back to where you
started. [...] Better, IMO, to have it being
strong from the start.
</EM
>
</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1959"
HREF="#AEN1959"
><SPAN
CLASS="footnote"
>[19]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>&#13; In the examples above, the <TT
CLASS="option"
>senders</TT
>
condition is actually redundant, since the file
<TT
CLASS="option"
>/home//.return-path-sign</TT
> is not likely to
exist. However, we make the condition explicit for
clarity.
</P
></TD
></TR
></TABLE
></BODY
></HTML
>