A DNSBL and Greylisting Hybrid Approach

I have long been a critic of greylisting as a method of reducing spam.  I recently broke down and implemented it on my servers after a couple of back-to-back blacklisting issues.  The problem with DNSBL blacklists is that even the “big boys” get their relays listed which causes mail to bounce for some period of time while they resolve the issue.  Recently, someone for which I host mail was getting frustrated as my server continued to turn away msn.com and google.com due to their presence on a couple of blacklists.  That’s just silly and really hard to explain to someone in a way that doesn’t make it sound like your fault.

So, I nixed the blacklists and moved to using postgrey for greylisting.  This process, which is well-documented elsewhere, relies on some required behaviors of the SMTP protocol to turn away spammers that don’t fully implement the protocol.  It automatically refuses mail from new and unknown servers in a soft way, asking them to “try again later”.  If they do, then their mail is accepted.  Most spammers won’t retry, they just move on to the next person.  It works very well, but it introduces a delay to the delivery of valid email.  Even if you only require that they try again immediately, or after a short period like five minutes, there is no way of communicating that to them.  As a result, many servers will wait an hour or even a day before retrying.  That really destroys the usefulness of instantaneous email and I hate it.

Recently I came across a page by a colleague of mine, Dave Hansen.  He suggested a hybrid approach to the problem, using the best of both systems.  He suggested that you first look up the remote server in a DNSBL.  If they’re not listed, then you accept their mail; if they are, you greylist them and introduce the delay.  This means that most mail (from unlisted servers) flows immediately as expected, and mail from incorrectly-listed machines will get the greylist delay.  He has a hacked up version of greylist.pl to do this.

In searching for a permanent way to do this, I came across postfwd, the postfix firewall daemon.  It allows you to delegate a lot of your policy out to another daemon (like you do with postgrey itself), but with far more control over how those rules are implemented.  What I came up with is a script that implements the hybrid approach, but with a few extra features.  The remote server is checked against seven blacklists.  If it is in two or more of them, then mail is rejected outright, assuming that you wouldn’t be erroneously listed on two at the same time.  If it’s listed on one of them, then the server is greylisted (actually delegated back to postgrey itself, which works very well).  If it’s not listed at all, then the mail is accepted and everyone is happy.  My postfwd config looks like this:

    &&DNSBLS {
             rbl=zen.spamhaus.org ;    \
             rbl=bl.spamcop.net ;      \
             rbl=dnsbl.sorbs.net ;     \
             rbl=ix.dnsbl.manitu.net ; \
             rhsbl=rddn.dnsbl.net.au ; \
             rhsbl=rhsbl.ahbl.org ;    \
             rhsbl=rhsbl.sorbs.net ;   \
    };

# DNSBL checks - lookup
id=RBL_QUERY  ;  &&DNSBLS ;  rhsblcount=all ; rblcount=all ;   \     
    action=set(HIT_dnsbls=$$rhsblcount,HIT_dnsbls+=$$rblcount,DSBL_text=$$dnsbltext)

# DNSBL checks - evaluation
id=RBL_TOOMANY  ;  HIT_dnsbls>=2 ;
    action=554 5.7.1 blocked using $$DSBL_count dnsbls, INFO: [$$DSBL_text]

# Greylist
id=GREYLIST ;  action=ask(127.0.0.1:10041)  ;  HIT_dnsbls>=1

So far, it seems to be working very well and doing exactly what I wanted.  I just configure postfix to use postfwd as an external policy server after all my normal checks have been satisfied.  I may up the count of blacklists that cause mail to be rejected outright to three or more, just to be safe, but I’ll have to see how many false positives I get over the next week or so.

Category(s): Miscellaneous
Tags: , ,

Comments are closed.