[ English / Japanese ]
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.
cvs -d :pserver:anonymous@yatex.org:/qmail co antibadmail
And join abmusers ML.
The antibadmail program enables handy bad mail rejection for qmail/sendmail/Postfix as below;
($CONTROLDIR defaults to /var/qmail/control)
Reject mail from host which sent HELO parameter that matches with file name in $CONTROLDIR/badhelodir/. Entries starting with period are treated as wildcard.
Some spammer's smtp hosts send helo of bogus IP address. Almost all of them are spam. Reject them.
More strict HELO qualification as below will be done for unknwon-host(hosts with PTR record of IP address unset).
No dots in HELO string assumed to be a bad host.
Much wider wildcard match for helo string, `.jp' for example, can be applied for unknown host. Put wider wildcard patterns into $CONTROLDIR/badhelodir/unknown/ by creating empty file with that name.
In any case above, badhelo check is skipped when $RELAYCLIENT or $RELIABLECLIENT is set like qmail manner.
In the same way as badhelo rejection, you can reject certain pattern of MAIL-FROM addresses. Put the email address string you want to reject into $CONTROLDIR/badmailfromdir/. Any patterns starting with `@' means all email addresses on that domain. Any patterns starting with dot(.) matches with all email domains under that domain.
(eg.) @hotmail.com -> matches with all *@hotmail.com addresses .biz -> matches with all *@*.biz addresses
You might know there are very very very many spam under the assumed name of RANDOM@hotmail.com. Giving up receiving all @hotmail.com is a clever solution. Do you think is it a overdosing?? Read the next.
Setting GOODMAILFROM to acceptable domains in tcpserver rule
file. Domains listed in this variable should be accepted even if
that domain is in $CONTROLDIR/badmailfromdir/
list.
With this feature, you can reject all false @hotmail.com while you
get real hotmail messages from real hotmail servers. To achieve
this, put
=.hotmail.com:allow,GOODMAILFROM="@hotmail.com"
in tcpserver's rule and put @hotmail.com in
badmailfrom
database. Note that tcpserver for
antibadmail should be invoked *WITHOUT* -H flag(-H means not
to lookup remote host name).
Like the manner of $GOODMAILFROM, values listed in $GOODHELO
should be accepted even if the string is in
$CONTROLDIR/badhelodir/
.
USE THIS WITH CARE
There are some ISP which provide free email service and commercial Internet connection service, such as Yahoo. Authentic Yahoo SMTP servers send correct FQDN name of them. So it is good idea to reject `HELO yahoo.com' because 100% of them are sent from badmail. You'd better to put 'yahoo.com' entry in badhelodir/ database. Do not set $GOODHELO for this case. But..
Disgusting SMTP servers, hotmail.com for example, don't send FQDN of them. Hotmail SMTP server stupidly sends `HELO hotmail.com'. Sigh.. Use $GOODHELO only for these case.
=.hotmail.com:allow,GOODMAILFROM="@hotmail.com",GOODHELO="hotmail.com"
Finally, you can receive emails from silly setting servers.
Reject all mail of localpart-only sender, except messages of bounce or messages from RELAYCLIENT.
Null-sender is used for bounce mail. Some spammer's MTA sends emails with null-sender to multiple recipients. That's wrong. The antibadmail program refuses null-sender emails once the client requests more than one RCPT TO.
If $RELAYCLIENT or $RELIABLECLIENT is set, cancel mail-from domain chek. Useful for receiving bounce mail from reliable mail server.
When you had old mail account on host you previously used, you want to forward emails to current mail server. In such case, you ought to know "forwarded email are full of spam!!", because your current mail server should rely the forwarding servers. Against this problem, the antibadmail program rejects all forwarded mail from such server except those listed in $PASSONLY, If you want to limit forwarded emails from old server to *.jp and *.org, put
=old.server.previously.used:allow,PASSONLY=".jp/.org"
in tcpserver's rule.
Reject any RCPT-TO recipient addresses listed in $CONTROLDIR/badrcpttodir/.
If the environment variable BADHOST set, reject the mail from that host with SMTP error 553. It is bad idea to refuse TCP connection from host which sends emails you want to reject, because natural action of SMTP client is to try to connect to secondary MX and/or more. Set $BADHOST by tcpserver as follows;
=.evil.domain:allow,BADHOST=""
It will sends SMTP-5xx error code to smtp client.
Requires tcpserver with tcpserver-paranoid patch.
It is true IP'addresse's DNS PTR record is not absolutely required. But almost all UBE sender disguise or omit PTR record.
If you want to reject mail from server whose PTR record is disguising, add -p option to tcpserver
tcpserver -p ......
and replace tcpserver with tcpserver-paranoid patch. antibadmail will reject mail from such host whose IP address has invalid PTR record.
Paranoid check is too much powerful. It sometimes rejects desirable email. You can find rejection log by grep-ping "BAD_PARANOID". To forgive x.y.z.w which sends *@xyz.its.dom.ain for incorrect PTR record setting, add a rule to tcprule file as follows;
x.y.z.w:allow,PASSONLY="@xyz.its.dom.ain"
Emails from x.y.z.w that matches with $PASSONLY is acceptable even if x.y.z.w has wrong PTR record.
In most case, spammer's computer is connected as unknown host. So it is clever to reject from unknwon host. But in fact, many desirable messages are sent from unknown host, since some mail-server administrators can't imagine the importance of correct DNS settings.
For this problem, we should request PTR record of IP-address blocks for unfamiliar country. If you and your site's users all don't have need to communicate with AAA-country, and IP-address block of `XXX.YYY.*.*' is allocated to AAA-country, put
XXX.YYY.:allow,REQPTR=""
in tcpserver's rule file. All connections from XXX.YYY.*.* without PTR record will be rejected.
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!
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
Change smtp daemon port other than 25. 10025 for example here.
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.
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.
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.
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.
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).
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.
/var/qmail/control/badhelodir/
Contains files whose names are patterns of SMTP-HELO string for rejection
/var/qmail/control/badmailfromdir/
Contains files whose names are patterns of envelope sender for rejection
/var/qmail/control/badrcpttodir/
Contains files whose names are patterns of envelope recipient for rejection
You can change the prefix /var/qmail/control
by
environment variable $CONTROLDIR at running time or by
`CFLAGS=-DCONTROLDIR=/foo/' at compilation.
A filename should be one of as follows;
For badhelodir, badmailfromdir and badrcpttodir, reject all clients which send parameter same as `name'.
For badhelodir and badmailfromdir, reject all clients which send parameter whose domain ends with `.name'. That is, wildcard matching with `*.name'.
For badmailfromdir, reject all clients which send MAIL-FROM parameter whose domain part is the same as `@name'. That is, wildcard matching with `*@name'.
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. 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.
Any file whose name begins with `p' is evaluated as fixed string pattern to be compared with the value of FieldName. A pattern must be written in a line. Patterns more than one line are AND-ed. Patterns in different files are OR-ed.
SMTP error message to be sent for clients when their sending header match with pattern.
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)
For (2);
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. As a conclusion,
--- 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.".
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;
# touch /var/qmail/control/badmailfromdir/@hotmail.com
=.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.
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.
Create datadir for soiled recipients.
# mkdir /var/qmail/control/soiledrcpttodir
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.
local-@your.domain
When local part ends with `-', pass all for `local-*@your.domain'.
@any.domain
Pass all for `*@any.domain'.
Note that rejection avoidance don't occur when smtp client sends parameter which matches strictly with entry of one of badhelodir, badmailfromdir and badrcpttodir.
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.
Any database which has multiple records in a file always suffers from these difficulties;
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.
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. :)
Sorry, Japanese only below.