Hi Tim,
On Wed, Mar 24, 2004 at 09:38:24PM +0000, Tim Meadowcroft wrote:
> I started off thinking that I'd suggest adding basic tar-pitting
> (http://www.gordano.com/kb.htm?q=1112) to selected plugins (such as SPF) that
> are detecting blatant abuse - the idea being that if a spammer has recruited
> 5,000 trojan home-cable machines worldwide to send out his spam, us just
> rejecting his connection at the start of a conversation might reduce our
> personal spam, but it doesn't hurt the spammer - in fact it saves him time
> (and therefore money) in that we've rejected him early and he's now free to
> get on to the next person (the equivalent of slamming the phone down on a
> tele-marketer, when what really costs them money is when they waste 10
> minutes on the phone and then you slam the phone down).
>
> So, I was going to modify selected plugins to not just return DENY, but to
> waste a bit of his time too
>
> my ($result, $smtp_comment, $comment) = $query->result2($rcpt->address);
> if ($result eq "fail" and $self->{_args}{spf_deny}) {
> # added a delay (default 30 seconds) to tar-pit nasty joe-jobbers
> sleep( $self->qp->config("tarpittime") );
> return (DENY, "SPF forgery: $smtp_comment");
> }
>
> And then I figured that this holds up his SMTP conversation with me, but
> probably doesn't do much more if he's using multiple threads (well, it does,
> but not an awful lot) so then I thought why not exploit the fact that if he's
> recruited a lot of home machines on cable/DSL connections, they have
> asymmetric connections and so very limited upload speeds, so we want to waste
> his time/bandwidth transmitting the stuff, and thereby reduce the
> effectiveness of his 5,000 machines to some fraction of that number...
>
> So perhaps I could add a new plugin return code of "DENYEVENTUALLY", which
> remembers that we're going to reject his message, but lets him transmit the
> whole thing, DATA and all (discarding it all as I go, of course), before
> rejecting it, but slows down reading the socket so that he still has to send
> all the data, but it takes a long time - maybe long enough for someone to
> notice.
>
> I'd want to make sure that I don't end up doing a DoS on myself, so I'd
> probably put a cap on how many of these I'm running simultaneously and how
> much bandwidth they're using, but then I started getting all sorts of nasty
> thoughts about closing my end of the socket but sending back raw packets to
> leave his socket in the infamous FIN_WAIT2 state (where it chews up resources
> but can't be cleaned up)... and that's when I thought I'd check what the
> interested parties think of the idea - has it been tried, does it sound fun,
> does it already exist, do you already do this using one of these tcpwrapper /
> smtproute whatever mechanisms ??
I think this sounds fun, but I'd suggest not putting tarpitting code inside
existing plugins. Better to factor it out altogether - what about something
like this:
- add a 'tarpit' plugin, that tarpits based on ip address (or just DENYs in
the event your tarpit caps are hit). Load this up early in your plugins/conf,
register for most hooks, and tarpit away
- add a 'tarpit_helper' plugin that records the ip address of the current host
in your tarpit database (var/db/tarpit/$ip_address ?) if a tarpit note is
set, and then returns a DENYSOFT. Load this up late in your plugins/conf
(but before check_relay), also registering for most hooks.
Then adding tarpit support to existing plugins just becomes:
$self->transaction->notes('tarpit', 1) if $tarpit_condition;
tarpit_helper then records the ip address, denysofts, and tarpit picks it up
next time it tries and does its thing.
Cheers,
Gavin