[ English / Japanese ]

- Anti bad-mail SMTP wrapper -

What's new?

What's this?

The SMTP wrapper `antibadmail' provides generic spam rejection on SMTP session. This program is a successor of my qmail patches.

Because `antibadamail' is a wrapper, it can work not only with qmail, but also with sendmail, postfix and any other RFC2821 compliances.

Unlike the `Message contents spam filter', antibadmail rejects bad mail without seeing any contents of them. Imagine if you were a large scale bad mail sender. Do you send bad mails from valid SMTP server? Do you send bad mails with your correct email addresses?

No.

Antibadmail reject all bad mails seeing the bogus parameters in SMTP session. Doing so reduces the load of mail servers because antibadmail program check only three SMTP parameters(HELO, MAIL-FROM and RCPT-TO) and smtp-client's DNS-record settings.

How to get

To get latest version, use cvs.

cvs -d :pserver:anonymous@yatex.org:/qmail co antibadmail

Snapshot here.
antibadmail-1.34.tar.gz

And join abmusers ML.

Features

The antibadmail program enables handy bad mail rejection for qmail/sendmail/Postfix as below;

($CONTROLDIR defaults to /var/qmail/control)

Note that this is not a virus scanner. Most virus-infected PC sends malicious email with infected person's email addresses. Introduction of antibadmail does not mean unnecessity of virus scanner. But `contents filter' including virus scanners always waste tremendous computing resources which are essentially unnecessary.

You'll find 60%-99% of undesirable emails are comfortably rejected by antibadmail. Save your mail server's resources!

Installation

Antibadmail should be invoked by tcpserver which is in ucspi-tcp package.

# gtar zxpf ucspi-tcp-0.88.tar.gz
# cd ucspi-tcp-0.88
# vi conf-home
(edit conf-home to define installation prefix)
# make && make setup check
  1. Installaion step to wrap sendmail/postfix smtpd
  2. Installaion step to wrap qmail-smtpd
  1. Installaion step to wrap sendmail/postfix smtpd

    1. Change smtp daemon port other than 25. 10025 for example here.

    2. Create a unprivileged user for antibadmail

      # groupadd abm
      # useradd -g abm abm
      

      User name `abm' is arbitrary. Suppose uid and gid of `abm' user are 250 and 25 respectively.

    3. Start antibadmail as follows;

      RELAYCHECK=1 tcpserver -u 250 -g 25 -x /etc/smtp.cdb 0 25 \
        antibadmail mconnect 127.0.0.1 10025
      

      Make sure antibadmail and mconnect command are located in $PATH. `mconnect' is a SMTP connection client, which comes with ucspi-tcp. /etc/smtp.cdb is the tcpserver's connection control rule database. If you are not familiar with tcpserver, see the tcpserver rule section below.

    4. Put list of domain names your server can accept.

      If your server can accept(or relay) foo.example.com and *.bar.example.net, create empty files below in /var/qmail/control/rcpthostsdir/

      foo.example.com
      .bar.example.net

      Note that not at(@)marks necessary for domain patterns, unlike patterns for bad*dir described below. RELAYCHECK=1 on a startup command line indicates enable acceptable RCPT-TO domain check. Even if RELAYCHECK=1, when the client pass SMTP-AUTH, any RCPT-TO domain the client send will be accepted by antibadmail.

      If you alter acceptable domains by "POP before SMTP" control, please ask it at the abmusers ML.

  2. Installaion step to wrap qmail-smtpd

    The qmail-smtpd daemon program is well designed to be wrapped by others. All you have to do is to add antibadmail to starting script. For example, you may already have script like this;

    tcpserver -u 250 -g 25 -x /etc/smtp.cdb 0 25 qmail-smtpd
    

    Rewrite it as follows;

    tcpserver -u 250 -g 25 -x /etc/smtp.cdb 0 25 \
        antibadmail qmail-smtpd
    

    That's all.

tcpserver rule

If you are not familiar with tcpserver yet, try this simplest rule file /etc/smtp.

127.0.0.1:allow,RELAYCLIENT=""
10.0.0.:allow,RELAYCLIENT=""
all:allow

where 10.0.0. is IP-address prefix of your LAN. RELAYCLIENT="" means setting environment variable like that at invocation of antibadmail when smtp connection comes from corresponding address. Like qmail-smtpd, antibadmail assume that the client is located in LAN when the environment variable RELAYCLIENT is set, so that connection at that time must not be abusing. Antibadmail accepts all message when RELAYCLIENT set.

If you wrote rule database in /etc/smtp, you have to convert it to cdb-format as follows.

# cd /etc
# tcprules smtp.cdb tmp < smtp

After starting tcpserver+antibadmail, try `telnet localhost smtp' to confirm it is running. If the SMTP greeting message of original smtp-daemon shows up, almost goes well.

To record the rejecting/accepting result, add the following line to /etc/syslog.conf.

local1.info                  /var/log/smtp-stat

It is more desirable to add a notation for log rotation to /etc/newsyslog.conf(BSD) or /etc/logrotate.conf(Linux).

Constructing badmail database

Antibadmail refers `datadir' database structure. Datadir is maildir-similar structure where an entity exists in a form of `file in a directory' instead of `line in a file'. By default, antibadmail referes three directories.

You can change the prefix /var/qmail/control by environment variable $CONTROLDIR at running time or by `CFLAGS=-DCONTROLDIR=/foo/' at compilation.

Blacklist

A filename should be one of as follows;

Rejection by header

The policy of antibadmail is ``Don't inspect contents''.

However, as to badmail forwarded by (friendly) SMTP server, we can find rejection ground only in message header.

Antibadmail can reject mails by mail header pattern. Rejection by header is a `last resort', and can't be diverted once message header matches with a pattern even if the pattern is misspelled. Use with great care. Header inspection defaults to off. To activate this, set environment variable HEADERCHECK to 1 at invocation of antibadmail.

HEADERCHECK=1 tcpserver ..... antibadmail .....

Then, antibadmail reads header patterns from regular data-directory. The datadir structure for rejection by header is little bit different from above. Datadir for one header pattern consists of as follows;

$CONTROLDIR/badhdrdir/FieldName/EntryName/p*
$CONTROLDIR/badhdrdir/FieldName/EntryName/errmsg

where FieldName is header-field name all lower case, EntryName is arbitrary name for pattern set.

For example, if you reject message whose header field contains as follows;

Received: from hogehoge.fugafuga.com (HELO oldserver.you.used) ....(1)
  or
Received: from unknown .... by oldserver.you.used ....(2)

where `....' is any string. You might want to reject forwarded badmails by seeing received-header added by SMTP server you previously used. Pattern for (1) is like this;

(HELO oldserer.you.used)

Why is this bad pattren? Because "HELO oldserver.you.used" was told by spamming server when it connects to oldserver.you.used. Sending opponent's name as HELO is typical spamming behavior.

Then, think about pattern for (2). It's as follows;

from unknown
by oldserver.you.used

Note that pattern(2) is written in two lines so that each string ("from unknwn" and "by oldserver.you.used") must match with received header. Now define this rule named `foo'

--- File: $CONTROLDIR/badhdrdir/received/foo/ptn-1 ---
(HELO oldserer.you.used)

--- File: $CONTROLDIR/badhdrdir/received/foo/ptn-2 ---
from unknwon
by oldserer.you.used

--- File: $CONTROLDIR/badhdrdir/received/foo/errmsg ---
We cannot receive suspicious messages.

refuses the messages which have received-header that matches with "(HELO oldserer.you.used)", or matches with both "from unknwon" and "by oldserer.you.used", returning the SMTP error message of "We cannot receive suspicious messages.".

More precise pattern for headers

When you are aware of the power of header rejection, you might want to describe patterns more precisely. The first character in each line of pattern files determines the matching method. There are five methods for matching.

STRING
Pattern lineMeaning
=STRING Whole line is exactly same as STRING
^STRING Line is beginning with STRING
$STRING Line is ending with STRING
/REGEX Line is matching with regular expression REGEX
:STRING Line has the part which exactly same asSTRING
Same as above

Note that all header field contents will be joined into one line, converted all lower case. Therefore all matching will be done in case-insensitive.

Regular expression engine is supplied by libc of your driving operating system. So it is different from that of Perl, Emacs-Lisp, (GNU)egrep which you may be experienced with. If you want to examine how regexp pattern matches with, use debugging mode of header module. It is obtained by typing this;

% make h

Using h command interactively as follows.

% ./h
Received: from hogehoge.blah.example.org (HELO oldserver.you.used) by oldserver.you.used

The `h' command acquires all patterns in $CONTROLDIR/badhdrdir/*/* and apply all patterns over given strings from stdin.

Be aware that although regular expression is friendly, using regexp easily causes configuration errors. It is difficult enough to confuse system administrators. Absolutely NO errors for mail configurations!

Exclusion from blacklist

You might want to reject all false `*@hotmail.com' mails. But you might want to receive `*@hotmail.com' from real hostmail server. In this case, do as follows;

  1. Put reject pattern in badmailfromdir/
    # touch /var/qmail/control/badmailfromdir/@hotmail.com
    
  2. Authorize client whose PTR-record matches with *.hotmai.com. Put the following line to /etc/smtp and convert it to smtp.cdb.
    =.hotmail.com:allow,GOODMAILFROM="@hotmail.com"
    

If you want to receive any message from certain server, Set environment variable RELIABLECLIENT for the server.

=smtp.server.you.wantto.rely:allow,RELIABLECLIENT=""

Antibadmail stops all rejection check except extremely insecure parameter when RELIABLECLIENT is set.

Soiled recipient address

If you or users of your SMTP server want to receive all email even if the sender's SMTP server has wrong DNS-record settings. Suppose when you apply web-shoping, auction, mail-magazine or so. Those sites as a whole are held in ill-mannered service provider. Many of them don't have correct settings of DNS(A and PTR record) nor SMTP-HELO. Althogh antibadmail reject emails from those incorrect servers by default, you can stop rejection upon certain receipient addresses.

You can make `soiled recipient address' as follows.

  1. Create datadir for soiled recipients.

    # mkdir /var/qmail/control/soiledrcpttodir
    
  2. Make the entry of recipient address for no rejection.

    # mkdir /var/qmail/control/soiledrcpttodir/local-foo@your.domain
    

Then antibadmail will pass all emails for `local-foo@your.domain'.

For qmail, wildcard patterns acceptable for soiledrcpttodir are as follows.

Note that rejection avoidance don't occur when smtp client sends parameter which matches strictly with entry of one of badhelodir, badmailfromdir and badrcpttodir.

Public spamdb

The public spam rejection database is available via anoncvs.

cvs -d :pserver:anonymous@yatex.org:/qmail co spamdb

This database is in plain text format, not datadir structure. You can convert plain text database to datadir struct by f2d command, which comes with antibadmail package.

You can convert, for example, badmailfrom file from spamdb to badmailfromdir/ structure by executing f2d as follows.

f2d -d ./badmailfromdir badmailfrom

Note that ./badmailfromdir/ and badmailfrom is accessible from working directory.

The Datadir structure

Any database which has multiple records in a file always suffers from these difficulties;

  1. file locking, which is the goal of `Don Quixote'
  2. one data file corruption means whole data corruption
  3. Updating data file without atomic-operation causes another referer to confusion

With `Datadir' structure, there's no need for file locking because all the updation on an entity can be done without referring any other entities. All addition/deletion operation is automatically atomic because they are file creation or file deletion.

Antibadmail Users ML

There is Mailing List for discussing about development and trouble shooting related to antibadmail. Please join it to nourish antibadmail!

To join the antibadmail users ML(abmusers), send your self introduction(more than 5 lines) to abmusers@ml.gentei.org with subject="subscribe". Here is an example.

To: abmusers@ml.gentei.org
Subject: subscribe
--
(Self-introduction more than 5 lines)
I'm newbie administrator of FOO company.
I love email!
I don't like spam!
---
YourMail@foo.comp....

Do not mimic above. :)

No Warranty

This program is free software and comes with absolutely NO WARRANTY. The author is not responsible for any possible defects caused by this software. You can freely modify this program for your convenience. But if you want to publish modified program, please tell me before announcement. Take it easy to write me comments and bug-reports.

yuuji@gentei.org

Publications

Sorry, Japanese only below.