the djb way

you've got spam!


rbl: whitelists, blacklists

In the previous section we saw how to shield a standard qmail-smtpd service from known spammers with the rblsmtpd utility.

Although the basic setup is a simple way to provide good solid spam protection, there may come a time when a mail site may wish to fine-tune the data provided by the RBLs in use:

The tools at our disposal actually allow a few different approaches for fine-tuning RBLs:

The first two methods are described in this page. The use of rbldns will be described in the next section.

$RBLSMTPD and tcprules

Before the rblsmtpd utility makes any DNS queries, it first checks its environment for the presence of a variable named RBLSMTPD:

How do we take advantage of this mechanism, using $RBLSMTPD to whitelist and/or blacklist remote hosts of our choosing? With tcprules of course!

Remember that our qmail-smtpd run script makes use of the -x option to tcpserver, specifying the tcprules we define in /etc/tcprules/smtp.rules. We can modify that ruleset to take advantage of the $RBLSMTPD mechanism:


# smtp.rules
#  + rblsmtpd control
# ===
127.:allow,RELAYCLIENT=""
10.0.1.:allow,RELAYCLIENT=""
# override spews block on moveon.org:
64.124.204.39:allow,RBLSMTPD=""
# quick block persistent rbl:
24.21.223.117:allow,RBLSMTPD="-rblsmtpd deny: halt thy spam!"
### that's all, folks!

The original rules for the qmail-smtpd service shown here have been modified with two new entries. These rules tell tcpserver to set up the environmental variable RBLSMTPD, depending on the IP address of the remote host.

In this example the first new rule sets $RBLSMTPD empty, so rblsmtpd will permit mail from the host at 64.124.204.39. In this way we can whitelist hosts that would otherwise be blocked by an RBL.

The second new rule sets $RBLSMTPD non-empty, to blacklist the host at 24.21.223.117. This particular entry demonstrates an additional feature of the $RBLSMTPD variable: values beginning with the '-' character instruct rblsmtpd to return permanent error code 553 to the remote host, rather than temporary error code 451.

Here is a summary table for the use of RBLSMTPD in tcprules:

sample entry effect
11.22.33.44:allow,RBLSMTPD="" whitelist
11.22.33.55:allow,RBLSMTPD="halt thy spam!" blacklist; error code 451
11.22.33.66:allow,RBLSMTPD="-halt thy spam!" blacklist; error code 553

Don't forget to "recompile" the rules after modifying them!

# (cd /etc/tcprules; make smtp.rules)

using tinydns

The way rblsmtpd queries DNS should suggest how your own tinydns service may be used to provide additional whitelist and blacklist information.

First, look at this new qmail-smtpd run script:


#!/bin/sh
# qmail-smtpd/run
# daemontools run script for qmail smtp service
#   + use rblsmtpd spam block
#   + local whitelist/blacklist servers 
# ===
CONLIMIT=49

exec 2>&1

echo "*** Starting qmail-smtpd..."
exec \
  envuidgid qmaild \
    softlimit -m 3000000 -f 10000000 \
      tcpserver -v -PHR \
      -U \
      -c ${CONLIMIT} \
      -x /etc/tcprules/smtp.cdb \
      0 25 \
        /usr/local/bin/rblsmtpd -B -t 300 \
        -a whitelist.example.org \
        -r blacklist.example.org \
        -r l2.spews.dnsbl.sorbs.net \
        -r sbl-xbl.spamhaus.org \
          /var/qmail/bin/qmail-smtpd

### that's all, folks!

We have added a couple additional arguments to rblsmtpd, referring to local whitelist and blacklist information in the DNS server for the example.org domain:

Now simply add appropriate TXT and A records to the data file of your tinydns service (using a text editor to edit the file directly):


# tinydns service for example.org
# root/data
# ===
# SOA:
.example.org:1.2.3.4:a:259200
# hosts:
=alice.example.org:1.2.3.4:86400
=betty.example.org:1.2.3.5:86400
=carol.example.org:1.2.3.6:86400
# MX:
@example.org:1.2.3.4:a::86400
# aliases:
+www.example.org:1.2.3.5:86400
#
# records for rblsmtpd:
# whitelist:
+39.204.124.64.whitelist.example.org:127.0.0.2:86400
'39.204.124.64.whitelist.example.org:Good to go!:86400
# blacklist:
+117.223.21.24.blacklist.example.org:127.0.0.2:86400
'117.223.21.24.blacklist.example.org:Halt thy spam!:86400
### that's all, folks!

For each host to either whitelist or blacklist, add two records:

Note that each entry is based on a construction of the fully qualified domain name, just as rblsmtpd will use DNS to look for it. That is, by reversing the "dot-quad" rendition of the remote IP address, then prepending it to the basename of the RBL. (The entries here correspond to the same remote hosts described in the tcprules setup above.)

Remember to compile the new tinydns data into cdb form:

# cd /service/tinydns/root; make

The new DNS records will then be available immediately. Test them with the djbdns utilities in the usual way:

$ dnsip 39.204.124.64.whitelist.example.org
127.0.0.2
$ dnstxt 117.223.21.24.blacklist.example.org
Halt thy spam!

This shows the DNS records working as desired; rblsmtpd will now whitelist or blacklist accordingly.

which is better?

Here we have shown a couple methods to both override and supplement the RBL databases used by rblsmtpd. Which is "better"?

Once again, that's for you to decide. Both are effective, both compile to cdb hashes and give fast results.

The $RBLSMTPD/tcprules approach is a little easier to implement and is a little faster in operation. It also offers an advantage in being able to cover a block range of IP addresses with one entry.

On the other hand, the tinydns approach is the true client/server solution. It offers the important advantage that a single tinydns service can provide RBL data to any number of mailservers on a network.

If your needs run to publishing a large number of RBL records, though, the tinydns method described here may become a little tedious after awhile. In that case, you may want to use Bernstein's special-purpose rbldns server, discussed in the next section.


Copyright © 2003, 2004, Wayne Marshall.
All rights reserved.

Last edit 2004.09.30, wcm.