qpsmtpd Wiki

[[plugins:spam:connection_shaper]]

You are here: start » plugins » spam » connection_shaper

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

=head1 NAME 
 
connection_shaper - limit the connection rate for each IP address.
 
=head1 DESCRIPTION
 
The B<connection_shaper> module reject clients who try to connect more than specified
times during specified period. The rate is specified in the config file I<connection_shaper>.
 
memcached 1.2.4 or newer is required.
C<Cache::Memcached::Fast> module from CPAN is required.
 
=head1 CONFIG
 
The config file contains lines with two. The first is a key.
The second is a value.
 
Example:
 
exptime 60
threshold 10
memcached_port 11211
memcached_server memcached.example.com
whitelist 192.168.1., 192.168.2., 10.0.0
 
It means that a client can connect upto 10 times every 60 seconds.
 
=head1 AUTHOR
 
Copyright 2008 Yoshifumi Kinoshita <yoshifumi1975@gmail.com>
 
This software is free software and may be distributed under the same
terms as qpsmtpd itself.
 
=cut
 
use Qpsmtpd::Constants;
use Socket;
use Cache::Memcached::Fast;
 
my $memcached;
my $config;
my @whitelist;
 
sub hook_pre_connection {
    my ($self,$transaction,%args) = @_;
 
    unless($memcached){
    foreach ($self->qp->config("connection_shaper")) {
        next if( m/^#/ );
        s/^\s*//;
        s/\s*$//;
        my ($key, $value) = split /\s+/, $_, 2;
        $config->{$key} = $value;
    }
    $config->{exptime} ||= 60; # 1 min.
    $config->{threshold} ||= 10;
    @whitelist = split /,\s*/, $config->{whitelist};
    $memcached = init_memcached($config);
    }
 
    return (DECLINED, "") if match_whitelist( $args{remote_ip} );
 
    $memcached->add($args{remote_ip}, 0, $config->{exptime});
    my $current_value = $memcached->incr($args{remote_ip}) || 0;
 
    if( $current_value > $config->{threshold} ){
        $self->log(LOGINFO, "Exceeds the threshold from $args{remote_ip}.");
        return (DENYSOFT, "");
    }
    return (DECLINED, "");
}
 
sub init_memcached{
    my($config) = shift;
    $config->{memcached_server} ||= 'localhost';
    $config->{memcached_port} ||= 11211;
 
    return new Cache::Memcached::Fast({
        servers => [ { address => "$config->{memcached_server}:$config->{memcached_port}" } ],
        failure_timeout => 2,
        max_failures => 1,
    });
}
 
sub match_whitelist{
    my($remote_ip) = shift;
    foreach (@whitelist){
        return 1 if( $remote_ip =~ m/$_/ );
    }
    return 0;
}