qpsmtpd Wiki

[[plugins:spam:tarpit]]

You are here: start » plugins » spam » tarpit

Login

You are currently not logged in! Enter your authentication credentials below to log in. You need to have cookies enabled to log in.

Login

You don't have an account yet? Just get one: Register

Forgotten your password? Get a new one: Set new password

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

plugins:spam:tarpit [2007/01/08 13:43] (current)
jamtur01 Document moved from tarpit
Line 1: Line 1:
 +<code perl>
 +=head1 NAME
  
 +tarpit
 +
 +=head1 DESCRIPTION
 +
 +This plugin slows the connections
 +
 +=head1 CONFIG
 +
 +=over 4
 +
 +=item <tarpit_initial> <tarpit_exponent> <tarpit_toplimit>
 +
 +The sleep value is: 
 +   First time: tarpit_initial
 +   Next time: min(tarpit_previous + (tarpit_previous*tarpit_exponent), tarpit_toplimit)
 +   
 +We have a whitelist (tarpit_whitelist) in the configuration directory
 +
 +It must be placed I<before> hosts_allow plugin (or any other pre_connection hook)
 +
 +=back
 +
 +=head1 BUGS
 +
 +
 +=head1 AUTHOR
 +
 +Written by Leonardo Helman <lhelman@pert(punto)com(punto)ar>.
 +Pert Consultores SRL
 +Argentina
 +
 +=head1 COPYRIGHT AND LICENSE
 +
 +Copyright (c) 2005 Leonardo Helman. Pert Consultores SRL Argentina
 +
 +This plugin is licensed under the same terms as the qpsmtpd package itself.
 +Please see the LICENSE file included with qpsmtpd for details.
 +
 +=head1 VERSION
 +
 +$Id: tarpit,v 1.10 2006/05/16 14:12:34 leoh Exp $
 +
 +=cut
 +
 +
 +use strict;
 +use warnings;
 +
 +use Time::HiRes;
 +
 +my $VERSION = substr q$Revision: 1.10 $, 10;
 +
 +sub init {
 +    my( $self, $qp, $tarpit_initial, $tarpit_exponent, $tarpit_toplimit )=@_;
 +    $self->{ _tarpit_initial }= $tarpit_initial || 2;
 +    $self->{ _tarpit_exponent }= $tarpit_exponent || 1.6;
 +    $self->{ _tarpit_toplimit }= $tarpit_toplimit || 20;
 +    $self->{ _tarpit_actual }= 0;
 +    $self->log( LOGNOTICE, "config: Tarpit $self->{ _tarpit_initial } $self->{ _tarpit_exponent } $self->{ _tarpit_toplimit }"  );
 +}
 +
 +# qpsmtpd-forkserver is reusing connections
 +sub hook_pre_connection {
 +    my ($self,$transaction,%args) = @_;
 +
 +    $self->{ _tarpit_actual }= 0;
 +    $self->qp->connection->notes('tarpit_whitelist_analyzed',0);
 +    
 +    return (DECLINED);
 +}
 +
 +sub hook_ehlo {
 +  my ( $self )= @_;
 +
 +  $self->doTarpit();
 +  return DECLINED;
 +}
 +
 +sub hook_helo {
 +  my ( $self )= @_;
 +
 +  $self->doTarpit();
 +  return DECLINED;
 +}
 +
 +sub hook_rcpt {
 +  my ( $self )= @_;
 +
 +  $self->doTarpit();
 +  return DECLINED;
 +}
 +
 +sub hook_mail {
 +  my ( $self )= @_;
 +
 +  $self->doTarpit();
 +  return DECLINED;
 +}
 +
 +# a este llega con reset, y con quit, solo uso el tarpit si no es quit
 +sub hook_reset_transaction {
 +  my ( $self, $transaction, @args )= @_;
 +
 +  if( lc($self->qp->connection->notes('original_string')) ne 'quit') {
 +    $self->doTarpit();
 +  }
 +  return DECLINED;
 +}
 +
 +sub hook_deny {
 +  my ( $self, $transaction, $prev_hook, $return, $return_text ) = @_;
 +
 +  $self->doTarpit();
 +  $self->nextTarpit();
 +  return DECLINED;
 +}
 +
 +sub hook_unrecognized_command {
 +  my ($self) = @_;
 +  
 +  $self->doTarpit();
 +  $self->nextTarpit();
 +  return DECLINED;
 +}
 +
 +sub nextTarpit {
 +  my ( $self )=@_;
 +
 +  unless( $self->isWhitelisted() ) {
 +    if( $self->{_tarpit_actual} ) {
 +      $self->{_tarpit_actual} += $self->{_tarpit_actual}*$self->{_tarpit_exponent};
 +      if( $self->{_tarpit_actual} > $self->{_tarpit_toplimit} ) {
 +        $self->{_tarpit_actual}= $self->{_tarpit_toplimit};
 +      } 
 +    }
 +    else {
 +      $self->{_tarpit_actual} = $self->{_tarpit_initial};
 +    }
 +  }
 +  return DECLINED;
 +}
 +
 +sub doTarpit {
 +  my ( $self )=@_;
 +
 +  if( $self->{ _tarpit_actual } ) {
 +    $self->log( LOGNOTICE, "Tarpiting $self->{ _tarpit_actual }" );
 +    sleep( $self->{ _tarpit_actual } );
 +  }
 +  return DECLINED;
 +}
 +
 +sub isWhitelisted {
 +  my( $self )=@_;
 +
 +  unless( $self->qp->connection->notes('tarpit_whitelist_analyzed') ) {
 +    my $client_ip = $self->qp->connection->remote_ip;
 +    my @tarpit_whitelist = $self->qp->config("tarpit_whitelist");
 +    my %tarpit_whitelist = map { $_ => 1 } @tarpit_whitelist;
 +
 +    $self->qp->connection->notes('tarpit_whitelist_analyzed', 1);
 +    $self->qp->connection->notes('tarpit_whitelist', 0);
 +    # TODO: Cambiar esto (en TODOS lados) por un chequeo por modulo de perl con formato cidr
 +    while ($client_ip) {
 +      if (exists($tarpit_whitelist{$client_ip}) ) {
 +        $self->log( LOGINFO, "The IP " . $self->qp->connection->remote_ip . " is in tarpit_whitelist" );
 +        $self->qp->connection->notes('tarpit_whitelist', 1);
 +        last;
 +      }
 +      $client_ip =~ s/\d+\.?$//; # strip off another 8 bits
 +    }
 +  }
 +
 +
 +  return $self->qp->connection->notes('tarpit_whitelist');
 +}
 +
 +# vim:ft=perl:
 +</code>