I think the problem with naughty and blocking "mostly good" servers is fully solved. The naughty plugin has been reimplemented as karma.
POD: https://www.tnpi.net/internet/mail/karma.html Code: https://github.com/msimerson/qpsmtpd/blob/karma/plugins/karma Here's a sample connection with the 'reject connect' option set: 26945 Accepted connection 0/15 from 201.238.201.232 / exchange.mauiandsons.cl 26945 Connection from exchange.mauiandsons.cl [201.238.201.232] 26945 (connect) ident::geoip: CL, Chile 26945 (connect) ident::p0f: Windows XP 26945 (connect) karma: fail, 1 naughty, 0 nice, 158 connects 26945 550 You were naughty. You are penalized for 0.79 more days. 26945 click, disconnecting 26945 (post-connection) connection_time: 0.038 s. 24709 cleaning up after 26945 Of course, it supports the reaper plugin, so disconnecting can happen at later hooks as well. Matt On May 24, 2012, at 3:06 PM, Jared Johnson wrote: > We do something not exactly similar to this, but which might be somewhat > instructive. We modified the banner delay plugin so that the amount of > delay we apply to a server depends on its previous behavior with us. The > default delay is 15 seconds; if you send a message that we reject as spam > or virus, we increase the delay by 5 seconds. If you send us a message > that we deliver as clean (whether that's because of spam scanners, > whitelists, or whatever), we reduce the delay by 5 seconds. We attached > other values to some other rejections; for instance, if you try to send > mail to an invalid user, the delay is increased by 1 or 2 seconds. We do > not increase the delay to more than around 300 seconds, so that at least > some very RFC-compliant MTA's at least have a chance to deliver, even if > they manage to get themselves horribly delayed. > > What we've found is that the main strength of the banner delay for us is > not that it exposes early talkers (it exposes some), but that it > encourages early disconnectors :) Some spambots give up after just 5 > seconds of delay; the one that wait out our 15 second delay will often try > to send a few messages and get rejected, then once we make our way up to > 20 or 30 seconds they start giving up on us altogether. > > So after we implemented this we noticed that what we had on our hands was > a rough score card for all connecting IP's indicating how well we know > them and how "naughty" they have been. From this we've been able to > further reduce the number of transactions for which scanning is required; > for instance, if a client gets the default delay (e.g. for all intents and > purposes we haven't heard from them), we only let them have a single > concurrent connection with us. We can also be more lenient with clients > that have won and maintained a banner delay of zero by sending us some > good mail and not screwing it up with bad mail. If your 'naughty' plugin > is pretty successful, perhaps we could benefit from adding a 'penalty box' > like this based on the delay -- clients that have earned, say, a 30 or 60 > second delay by trying to send us too much spam and not enough ham get > sent to the penalty box and are therefore no longer able to increase our > concurrency. I had an idea similar to this a while ago (we haven't got > around to implementing it), where we *randomly* disconnect at the outset a > client that's earned an increased banner delay, and the frequency of > disconnection depends on long high a banner delay they've earned. This > would allow us to throw away connections while, again, still giving good > clients a chance to eventually connect to us and send legit mail, thereby > decreasing their delay. > > Others may or may not find it worthwhile to implement this sort of mucking > with banner delays (I'll list a couple of problems with it below); but > simply scoring clients might be an answer to the problem of legit clients > being rejected. Rather than putting a client in the penalty box at the > first violation, give them a few chances, and let clean mail put them back > into good graces. > > For storage of these scores we have been using a table Postgres with three > fields: IP, delay (aka score), and timestamp, with entries expired after a > client has not talked to us at all for 24 hours. We've talked about using > Cache::FastMMap for this because there is not really any benefit to > keeping it in the database (we don't even try to synchronize it across > clusters, if your score is effectively reset because you started talking > to a new node then so be it). But honestly, we haven't seen any big > bottlenecks with the DB, so we haven't bothered doing the coding and > testing work to move it to obviously more efficient mechanisms. > > For anyone considering the delay method itself, one big weakness with this > method is that since it does not "get rid of naughty connections as > quickly as possible", unless you're using the async daemon (we aren't), it > can wind up taking up a lot of resources. Obviously it will still save > plenty of CPU on account of spammers giving up instead of giving us > something to scan; but without async, the sharp increase in concurrency > will hurt memory usage. One thing we recently added which I think will > really help in this area is that we do our RBL lookup before starting the > delay, and if a server is RBL'd we skip the delay and go right to > disconnecting them. Since so many servers are RBL'd this should help > concurrency a lot. If the server is not RBL'd, we subtract the amount of > time it took for us to do the RBL lookup (and anything else we might have > done first) from their banner delay -- after all, we've already been > delaying our banner for that amount of time. > > Aside from that, simply doing a banner delay has caused problems for a few > legit servers which give up before they even get to our default delay. > We've pretty much completely gotten around this by excluding all private > IP's, and clients that are given relay permission by our IP-based rules, > from any banner delay whatsoever. > > HTH! > > -Jared > >> I have written a plugin that is currently named naughty. >> >> The POD has a good description of what it does and how it works. You can >> read the POD here: >> >> https://www.tnpi.net/internet/mail/naughty.html >> >> The plugin is very effective at blocking spam and it has reduced my CPU >> load enough to be measurable on munin graphs (which aren't exactly >> granular). Read the POD at the URL above to see how and why. >> >> The plugin has one teensy tiny problem. Because it penalizes servers that >> send spam, it occasionally penalizes a "mostly good" server. In a week of >> running, it has done this exactly twice, and the two servers it nabbed are >> mx.develooper.com and mx2.freebsd.org. Both are servers that send lots of >> ham, and occasionally, some spam. >> >> I see a couple options. >> >> a) Whitelist the "mostly good" servers that get penalized. While that >> would be easy, it requires manual effort on the part of the sysadmin, and >> users will likely lose valid mail. >> >> b) Keep track of senders who send us ham. Then we have lots of options. We >> can allow mail from "mostly good" senders, randomly defer their >> connections with a "We like you, but you're sending spam" error, or any >> number of other ways to deal with them. >> >> c) Other? >> >> The data store for naughty is currently a database of key/value pairs. The >> key is the remote IP (in integer form) and the value is a timestamp. >> That's all that's needed for naughty to function. >> >> To track naughty and nice senders, I'm imagining the DB would need >> counters to track of the number of ham and spam messages received from >> that server. Or even a single signed integer, where anything above zero is >> bad and below zero is good. >> >> The only other thing needed is a reliable way to detect that incoming mail >> is ham. For my server, I'll use 'dspam reject agree', so that if SA & >> dspam agree that it's ham, then the naughty plugin increments the nice >> counter. When new connection arrive, they would be blocked based on their >> karma (the weighting of naughty -vs- nice emails) they send. >> >> I'm fishing for other ideas, better ideas, or experience (we tried that, >> and these are the results) you can share. >> >> Thanks, >> Matt