Table of Contents

How to run a private DNSBL for SpamAssassin

Here we will present a recipe to create a personal Domain Name System-based Blackhole List to be used with SpamAssassin. This will enable you to assign a custom SPAM score to mails coming from specific IP addresses (at the moment only IPv4 addresses).

We will use the well-known mechanism of DNSBLs, so that the general-purpose DNS server software Bind9 and SpamAssassin are used, just with some specific configuration. This allows us to combine our blackhole list with the traditional ones provided by e.g. dnsbl.sorbs.net and zen.spamhaus.org.

Configure the DNS

Dynamic updates using an HMAC-MD5 key

Our DNSBL zone will be updated dynamically on our DNS server using a Python script; to allow only authenticated queries we create a DNS key. To generate the key we run the command:

dnssec-keygen -a HMAC-MD5 -b 512 -n USER bl-rigacci-org_rndc-key

Notice that bl-rigacci-org_rndc-key is the username associated with the key. Two file will be created: one with the .key and one with the .private extension. Get the secret from the generated private file:

cat Kbl-rigacci-org_rndc-key.+157+27575.private
...
Key: rg2aizg+T6XkKkmpI42K7g==
...

Now create a file name /etc/bind/bl-rigacci-org_rndc-key containing the secret, be sure to set the file into 640 mode and owned by bind:bind:

key "bl-rigacci-org_rndc-key" {
        algorithm hmac-md5;
        secret "rg2aizg+T6XkKkmpI42K7g==";
};

The dynamic zone

Your DNS server will manage a dynamic zone dedicated to the DNSBL service. Create a file /var/cache/bind/bl.rigacci.org owned by bind:bind:

$TTL 900     ; 15 minutes
bl.rigacci.org   IN SOA  ns1.rigacci.org. postmaster.rigacci.org. (
                1       ; serial
                3600    ; refresh (1 hour)
                600     ; retry (5 minutes)
                432000  ; expire (5 days)
                10      ; minimum (10 seconds)
                )

                NS      ns1.rigacci.org.
                NS      ns2.rigacci.org.

$ORIGIN bl.rigacci.org.
$TTL 900        ; 15 minutes

Add that zone to /etc/bind/named.conf.local. Suppose that 10.100.101.102 is your secondary DNS server, this is the snippet required:

//--------------------------------------------------------------
// Dynamic update zone for DNS Blackhole List.
//--------------------------------------------------------------
zone "bl.rigacci.org" {
    type master;
    allow-update { 127.0.0.1; 10.100.101.102; };
    allow-transfer { 127.0.0.1; 10.100.101.102; };
    file "bl.rigacci.org";
    max-journal-size 500k;
};
include "/etc/bind/bl-rigacci-org_rndc-key";

Configure SpamAssassin

To add a check against our DNSBL, just edit /etc/spamassassin/local.cf and add a section like this:

header     LOCAL_CUSTOM_DNSBL    eval:check_rbl('bl-rigacci','bl.rigacci.org.')
describe   LOCAL_CUSTOM_DNSBL    Entries listed in bl.rigacci.org RBL
score      LOCAL_CUSTOM_DNSBL    100.0

You can customize the score (default SPAM score is 5.0 in SpamAssassin) to match your requirements.

Python script to manage the dynamic zone

Finally we need a script to add, remove or query IP address into the DNSBL zone. We have written a dnsbl-tool (use this one if you have the python3-dnspython 2.0.0 library dnsbl-tool_0.4.0) which can be used as follow:

dnsbl-tool -a 192.168.10.1
Adding record type "A" for 1.10.168.192.bl.rigacci.org
dnsbl-tool -q 192.168.10.1
Address 192.168.10.1 is listed: 1.10.168.192.bl.rigacci.org => 127.0.0.1
dnsbl-tool -r 192.168.10.1
Removing record type "A" for 1.10.168.192.bl.rigacci.org

To query the entire zone from the DNS server, you can request an AXFR (zone transfer). For doing that, you must do it from an IP address listed into the allow-transfer declared into named.conf.local:

dig -tAXFR bl.rigacci.org