You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gentoo-overlay/mail-filter/postgrey/files/targrey-0.31-postgrey-1.34....

203 lines
8.4 KiB

--- postgrey.orig 2011-05-04 22:54:15.000000000 +0200
+++ postgrey 2011-10-17 10:10:21.000000000 +0200
@@ -309,6 +309,22 @@
$self->mylog(1, "cleaning clients database finished. before: $nr_keys_before, after: $nr_keys_after");
}
+ if($self->{postgrey}{targrey}) {
+ # cleanup tarpit blacklist database
+ my $tarpit_db = $self->{postgrey}{db_tarpit};
+ ($nr_keys_before, $nr_keys_after) = (0, 0);
+ while (my ($key, $tarpit_last_seen) = each %$tarpit_db) {
+ $nr_keys_before++;
+ if($now - $tarpit_last_seen > $retry_window) {
+ delete $tarpit_db->{$key};
+ }
+ else {
+ $nr_keys_after++;
+ }
+ }
+ $self->mylog(1, "cleaning tarpit blacklist database finished. before: $nr_keys_before, after: $nr_keys_after");
+ }
+
$self->{postgrey}{last_maint_keys}=$now;
}
}
@@ -383,7 +399,7 @@
# whitelist if count is enough
if(defined $cawl_count and $cawl_count >= $self->{postgrey}{awl_clients})
{
- if(($now >= $cawl_last+3600) or ($cawl_last > $now)) {
+ if(($now >= $cawl_last + $self->{postgrey}{awl_delay}) or ($cawl_last > $now)) {
$cawl_count++; # for statistics
$cawl_db->{$cawl_key}=$cawl_count.','.$now;
}
@@ -392,6 +408,28 @@
}
}
+ # check tarpit passed if targrey mode
+ if ($self->{postgrey}{targrey} && $attr->{protocol_state} eq 'DATA') { # passed tarpit
+ # remove tarpit blacklist
+ my $tarpit_db = $self->{postgrey}{db_tarpit};
+ my $tarpit_key = $attr->{client_address};
+ delete $tarpit_db->{$tarpit_key};
+
+ # auto whitelist clients by tarpit
+ if ($self->{postgrey}{awl_clients}) {
+ # enough time has passed (record only one attempt per hour)
+ if (! defined $cawl_last or $now >= $cawl_last + $self->{postgrey}{awl_delay}) {
+ # ok, increase count
+ $cawl_count++;
+ $cawl_db->{$cawl_key}=$cawl_count.','.$now;
+ $self->mylog(1, "tarpit whitelisted: $attr->{client_name}"."[".$attr->{client_address}."]")
+ if $cawl_count==$self->{postgrey}{awl_clients};
+ }
+ }
+
+ return 'DUNNO';
+ }
+
# lookup
my $sender = $self->do_sender_substitutions($attr->{sender});
my ($client_net, $client_host) =
@@ -402,10 +440,11 @@
}
my $val = $db->{$key};
my $first;
+ my $retry_count=0;
my $last_was_successful=0;
if(defined $val) {
my $last;
- ($first, $last) = split(/,/,$val);
+ ($first, $last, $retry_count) = split(/,/,$val);
# find out if the last time was unsuccessful, so that we can add a header
# to say how much had to be waited
if($last - $first >= $self->{postgrey}{delay}) {
@@ -426,16 +465,19 @@
$first = $now;
}
+ my $diff = $self->{postgrey}{delay} - ($now - $first);
+
+ # enough waited? -> increase retry_count
+ $retry_count++ if($diff <= 0);
+
# update (put as last element stripped host-part if it was stripped)
if(defined $client_host) {
- $db->{$key}="$first,$now,$client_host";
+ $db->{$key}="$first,$now,$retry_count,$client_host";
}
else {
- $db->{$key}="$first,$now";
+ $db->{$key}="$first,$now,$retry_count";
}
- my $diff = $self->{postgrey}{delay} - ($now - $first);
-
# auto whitelist clients
# algorithm:
# - on successful entry in the greylist db of a triplet:
@@ -443,23 +485,41 @@
# - client whitelisted already? -> update last-seen timestamp
if($self->{postgrey}{awl_clients}) {
# greylisting succeeded
- if($diff <= 0 and !$last_was_successful) {
+ if($retry_count >= $self->{postgrey}{retry_count} and !$last_was_successful) {
# enough time has passed (record only one attempt per hour)
- if(! defined $cawl_last or $now >= $cawl_last + 3600) {
+ if(! defined $cawl_last or $now >= $cawl_last + $self->{postgrey}{awl_delay}) {
# ok, increase count
$cawl_count++;
$cawl_db->{$cawl_key}=$cawl_count.','.$now;
my $client = $attr->{client_name} ?
$attr->{client_name}.'['.$attr->{client_address}.']' :
$attr->{client_address};
- $self->mylog(1, "whitelisted: $client")
+ $self->mylog(1, "whitelisted: $attr->{client_name}"."[".$attr->{client_address}."]")
if $cawl_count==$self->{postgrey}{awl_clients};
}
}
}
- # not enough waited? -> greylist
- if ($diff > 0 ) {
+ # not enough retry? -> greylist
+ if ($retry_count < $self->{postgrey}{retry_count}) {
+ if($self->{postgrey}{tarpit} && ! $self->{postgrey}{targrey}) {
+ # do tarpit and greylist if tarpit option only
+ # don't add message after greylist_action
+ return "SLEEP $self->{postgrey}{tarpit}, $self->{postgrey}{greylist_action}";
+ }
+ if($self->{postgrey}{targrey}) {
+ # do tarpit if targrey option
+ # add tarpit blacklist
+ my $tarpit_db = $self->{postgrey}{db_tarpit};
+ my $tarpit_key = $attr->{client_address};
+ my $tarpit_last = $tarpit_db->{$tarpit_key};
+ $tarpit_last = 0 unless (defined $tarpit_last);
+ $tarpit_db->{$tarpit_key} = "$now" if ($now >= $tarpit_last+300); # update if 5min ago
+
+ # return sleep if not tarpit blacklisted
+ return "SLEEP $self->{postgrey}{tarpit}" if ($tarpit_last == 0);
+ # greylist if tarpit blacklisted
+ }
my $msg = $self->{postgrey}{greylist_text};
# Workaround for an Exchange bug related to Greylisting:
# use DSN 4.2.0 instead of the default 4.7.1. This works
@@ -517,6 +577,7 @@
'syslogfacility|syslog-facility|facility=s',
'retry-window=s', 'greylist-action=s', 'greylist-text=s', 'privacy',
'hostname=s', 'exim', 'listen-queue-size=i', 'x-greylist-header=s',
+ 'tarpit:s', 'targrey', 'retry-count=i', 'auto-whitelist-delay=i',
) or exit(1);
# note: lookup-by-subnet can be given for compatibility, but it is default
# so do not do nothing with it...
@@ -606,7 +667,9 @@
awl_clients => defined $opt{'auto-whitelist-clients'} ?
($opt{'auto-whitelist-clients'} ne '' ?
$opt{'auto-whitelist-clients'} : 5) : 5,
+ awl_delay => $opt{'auto-whitelist-delay'} || 3600,
retry_window => $retry_window,
+ retry_count => $opt{'retry-count'} || 1,
greylist_action => $opt{'greylist-action'} || 'DEFER_IF_PERMIT',
greylist_text => $opt{'greylist-text'} || 'Greylisted, see http://postgrey.schweikert.ch/help/%r.html',
whitelist_clients_files => $opt{'whitelist-clients'} ||
@@ -618,6 +681,10 @@
hostname => defined $opt{hostname} ? $opt{hostname} : hostname,
exim => defined $opt{'exim'},
x_greylist_header => $opt{'x-greylist-header'} || 'X-Greylist: delayed %t seconds by postgrey-%v at %h; %d',
+ tarpit => defined $opt{'tarpit'} ?
+ ($opt{'tarpit'} ne '' ?
+ $opt{'tarpit'} : 65) : undef,
+ targrey => defined $opt{'targrey'},
},
}, 'postgrey';
@@ -633,6 +700,11 @@
require Digest::SHA;
}
+ # --targrey needs tarpit sec
+ if(defined $opt{'targrey'} && ! defined $opt{'tarpit'}) {
+ $server->{postgrey}{tarpit} = 125;
+ }
+
$0 = join(' ', @{$server->{server}{commandline}});
$server->run;
@@ -711,6 +783,13 @@
-Env => $self->{postgrey}{db_env}
) or die "ERROR: can't create database $self->{server}{dbdir}/postgrey_clients.db: $!\n";
}
+ if($self->{postgrey}{targrey}) { # use targrey
+ tie(%{$self->{postgrey}{db_tarpit}}, 'BerkeleyDB::Btree',
+ -Filename => 'tarpit_clients.db',
+ -Flags => DB_CREATE,
+ -Env => $self->{postgrey}{db_env}
+ ) or die "ERROR: can't create database $self->{server}{dbdir}/tarpit_clients.db: $!\n";
+ }
}
sub mux_input()