flagging “dictionary attack” spam at the MTA level

I have a server that hosts several domain names. It gets gobs of “dictionary attack” spam to addresses that have never been valid.

Spamassassin is running at the MTA level, and set to quarantine mail between a set of threshhold values. (Mostly to give me a chance to identify false positives while I’m tuning the rulesets.) The problem is, the quarantine operation happens before the MTA decides whether to accept the incoming mail message, so mail to boty72fg@mydomain.example.com can be quarantined to my review queue even though it would normally be rejected.

I started by playing around with the blacklist_to and whitelist_to directives. The problem is, I don’t want to just whitelist_to every valid alias (because valid aliases get plenty of spam). And I don’t want to have to blacklist_to everything of the form boty72fg@mydomain.example.com. What I want is to flag all mail that doesn’t match a known alias as probable spam.

Here’s my first cut at implementing this as a meta rule:

header __EXAMPLE_ALIAS_RECOGNIZED ToCc =~ /\b(?:bogus|bugos|gosub|gubos|sobug|sugob)@/i

header __EXAMPLE_DOM_RECOGNIZED ToCc =~ /\bexample\.com/i

describe EXAMPLE_ALIAS_UNRECOGNIZED Mail to invalid alias
meta EXAMPLE_ALIAS_UNRECOGNIZED (!__EXAMPLE_ALIAS_RECOGNIZED && __EXAMPLE_DOM_RECOGNIZED)
score EXAMPLE_ALIAS_UNRECOGNIZED 5.0

Seems to work okay, but it’s a little verbose, and will need to be updated whenever valid email addresses are added or removed.

I also thought about trying something like this:

# ALL addresses @mydomain.example.com are blacklisted
score USER_IN_BLACKLIST_TO 5.0
# some addresses @mydomain.example.com are ALSO whitelisted
# negating the effect of the blacklist
score USER_IN_WHITELIST_TO -5.0
blacklist_to *mydomain.example.com
whitelist_to bogus@mydomain.example.com
whitelist_to bugos@mydomain.example.com
whitelist_to gosub@mydomain.example.com
whitelist_to gubos@mydomain.example.com
whitelist_to sobug@mydomain.example.com
whitelist_to subog@mydomain.example.com

But I’m not sure if that’s truly equivalent (?). And it’s even more verbose, and doesn’t strike me as any easier to maintain — I still have a requirement to either generate the rulesets from virtusertable or manually update the rulesets when virtusertable is updated.

Anybody got a better way to do this?

Leave a Reply