[Mimedefang] Blocking Dictionary Attacks

Paul Murphy Paul.Murphy at argentadiscovery.com
Tue Jun 9 13:20:39 EDT 2009

>>> afo cliff <afocliff at gmail.com> 09/06/2009 17:18 >>>
> Ok, then it looks like it's better to stick with access/virtusertable

No, it is infinitely better to do it in filter_recipient, and terminate
the connection after a number of invalid recipients.

Consider the case where a spammer connects and tries a list of 2000
common accounts (root, postmaster, admin, daemon, staff, info, etc...). 
Rejecting via the access DB will reject all of the ones which are
invalid, and will do so quickly.  However, all of the valid ones will
get the spam, and the spammer will also get a 2xx OK code to that
recipient, so they can tune their mailing lists to remove known bad
addresses, and sell on the ones which they now know to be working.

Doing it via filter_recipient, the spammer sends RCPT_TO with the first
address, which might be valid.  However, long before they have gone
through the 2000 in their list, you've seen 3 bad addresses, and have
rejected the whole message.  If you have coded it, you may also then
firewall the sending server, so you never hear from them again, and
they've still got no idea which addresses are valid apart from any which
were flagged as OK before they got 3 bad recipients.  To date, we've
never had a valid user who gets 3 addresses wrong in our domain - one is
common, two is rare, three has never happened.  YMMV.

I count recipients in filter_recipient:

# check if we've seen any previous recipients
@lines=split / /,$scores;
if (defined $lines[0] )
if (defined $lines[1] )

# How many recipients so far?  History plus this current one...

# if there have been more than 3 bad recipients, drop the connection
if ( $badrcpt > 3) 
  # CALLS TO MY ADDITIONAL CODE -  firewall_block($ip,$hostname,"Too
many bad recipients");
  # open(PROG,">>./Progress");
  # print PROG " BOUNCE - too many invalid recipients\n";
  # close(PROG);
  # md_dbrcptlog($MsgID,$recipient,DB_MANYBADRECIPS);
  return("REJECT","Too many bad recipients");

# now check the recipient address against our database of valid users

if ( # recipient is not recognised # )
    print DATA "$badrcpt $goodrcpt\n";
    return("BOUNCE","Invalid user address - not known here.");
    print DATA "$badrcpt $goodrcpt\n";

My code to firewall offending servers makes a socket connection to a
Perl-based daemon which accepts the request, adds it to the firewall
config (IPTables in my case), and then adds it to a persistent database
table which is scanned on restarts to put the history back in place.  I
also have a cleanup script to limit the firewall table to around 1000
entries - most offenders are transient, and change IP addresses
regularly, so there's no point in blocking an IP for weeks/months/years.
 I also log progress to a file, and I have custom logging to a database,
all of which you can ignore.

Since my firewall code runs with a delay, the spammer gets the SMTP
error, and then we firewall them, despite the code looking like we
firewall them and then try to send them a reject message...

Best Wishes,


Argenta Discovery Ltd, 8-9 Spire Green Centre, Harlow, Essex, CM19 5TR
Registered in England No. 3671653

More information about the MIMEDefang mailing list