Description: whitelist whatever dnswl.org whitelists . postgrey (1.35-1+miab1) unstable; urgency=low . * Added DNSWL.org whitelisting. Author: Joshua Tauberer --- postgrey-1.35.orig/README +++ postgrey-1.35/README @@ -13,7 +13,7 @@ Requirements - BerkeleyDB (Perl Module) - Berkeley DB >= 4.1 (Library) - Digest::SHA (Perl Module, only for --privacy option) - +- Net::DNS (Perl Module) Documentation ------------- --- postgrey-1.35.orig/postgrey +++ postgrey-1.35/postgrey @@ -18,6 +18,7 @@ use Fcntl ':flock'; # import LOCK_* cons use Sys::Hostname; use Sys::Syslog; # used only to find out which version we use use POSIX qw(strftime setlocale LC_ALL); +use Net::DNS; # for DNSWL.org whitelisting use vars qw(@ISA); @ISA = qw(Net::Server::Multiplex); @@ -26,6 +27,8 @@ my $VERSION = '1.35'; my $DEFAULT_DBDIR = '/var/lib/postgrey'; my $CONFIG_DIR = '/etc/postgrey'; +my $dns_resolver = Net::DNS::Resolver->new; + sub cidr_parse($) { defined $_[0] or return undef; @@ -48,6 +51,36 @@ sub cidr_match($$$) return ($addr & $mask) == $net; } +sub reverseDottedQuad { + # This is the sub _chkValidPublicIP from Net::DNSBL by PJ Goodwin + # at http://www.the42.net/net-dnsbl. + my ($quad) = @_; + if ($quad =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { + my ($ip1,$ip2,$ip3,$ip4) = ($1, $2, $3, $4); + if ( + $ip1 == 10 || #10.0.0.0/8 (10/8) + ($ip1 == 172 && $ip2 >= 16 && $ip2 <= 31) || #172.16.0.0/12 (172.16/12) + ($ip1 == 192 && $ip2 == 168) || #192.168.0.0/16 (192.168/16) + $quad eq '127.0.0.1' # localhost + ) { + # toss the RFC1918 specified privates + return undef; + } elsif ( + ($ip1 <= 1 || $ip1 > 254) || + ($ip2 < 0 || $ip2 > 255) || + ($ip3 < 0 || $ip3 > 255) || + ($ip4 < 0 || $ip4 > 255) + ) { + #invalid oct, toss it; + return undef; + } + my $revquad = $ip4 . "." . $ip3 . "." . $ip2 . "." . $ip1; + return $revquad; + } else { # invalid quad + return undef; + } +} + sub read_clients_whitelists($) { my ($self) = @_; @@ -361,6 +394,25 @@ sub smtpd_access_policy($$) } } + # whitelist clients in dnswl.org + my $revip = reverseDottedQuad($attr->{client_address}); + if ($revip) { # valid IP / plausibly in DNSWL + my $answer = $dns_resolver->send($revip . '.list.dnswl.org'); + if ($answer && scalar($answer->answer) > 0) { + my @rrs = $answer->answer; + if ($rrs[0]->type eq 'A' && $rrs[0]->address ne '127.0.0.255') { + # Address appears in DNSWL. (127.0.0.255 means we were rate-limited.) + my $code = $rrs[0]->address; + if ($code =~ /^127.0.(\d+)\.([0-3])$/) { + my %dnswltrust = (0 => 'legitimate', 1 => 'occasional spam', 2 => 'rare spam', 3 => 'highly unlikely to send spam'); + $code = $2 . '/' . $dnswltrust{$2}; + } + $self->mylog_action($attr, 'pass', 'client whitelisted by dnswl.org (' . $code . ')'); + return 'DUNNO'; + } + } + } + # auto whitelist clients (see below for explanation) my ($cawl_db, $cawl_key, $cawl_count, $cawl_last); if($self->{postgrey}{awl_clients}) {