From 94d1d4ab12b1a9f7ba56402e2cc1d4fc1e2a249c Mon Sep 17 00:00:00 2001 From: dakkar Date: Thu, 27 Dec 2007 18:49:47 +0000 Subject: r3320@rfc-1918: dakkar | 2007-12-27 19:49:40 +0100 branched Net::DNSBLLookup for ease of customization --- lib/DAKKAR/Graylister.pm | 85 +------------- lib/DAKKAR/Net/DNSBLLookup.pm | 209 +++++++++++++++++++++++++++++++++++ lib/DAKKAR/Net/DNSBLLookup/Result.pm | 144 ++++++++++++++++++++++++ 3 files changed, 356 insertions(+), 82 deletions(-) create mode 100644 lib/DAKKAR/Net/DNSBLLookup.pm create mode 100644 lib/DAKKAR/Net/DNSBLLookup/Result.pm diff --git a/lib/DAKKAR/Graylister.pm b/lib/DAKKAR/Graylister.pm index 9ee9be0..bd07e6d 100644 --- a/lib/DAKKAR/Graylister.pm +++ b/lib/DAKKAR/Graylister.pm @@ -1,88 +1,9 @@ package DAKKAR::Graylister; use strict; use warnings; -use Net::DNSBLLookup; +use DAKKAR::Net::DNSBLLookup; use DBI; -{ - %Net::DNSBLLookup::dns_servers=( - 'dnsbl.sorbs.net' => { - '127.0.0.2' => Net::DNSBLLookup::DNSBLLOOKUP_OPEN_PROXY_HTTP, - '127.0.0.3' => Net::DNSBLLookup::DNSBLLOOKUP_OPEN_PROXY_SOCKS, - '127.0.0.4' => Net::DNSBLLookup::DNSBLLOOKUP_OPEN_PROXY_MISC, - '127.0.0.5' => Net::DNSBLLookup::DNSBLLOOKUP_OPEN_RELAY, - '127.0.0.6' => Net::DNSBLLookup::DNSBLLOOKUP_SPAMHOUSE, - '127.0.0.7' => Net::DNSBLLookup::DNSBLLOOKUP_FORMMAIL, - '127.0.0.8' => Net::DNSBLLookup::DNSBLLOOKUP_CONFIRMED_SPAM, - '127.0.0.9' => Net::DNSBLLookup::DNSBLLOOKUP_HIJACKED, - '127.0.0.10' => Net::DNSBLLookup::DNSBLLOOKUP_DYNAMIC_IP, - }, - 'dnsbl.njabl.org' => { - '127.0.0.2' => Net::DNSBLLookup::DNSBLLOOKUP_OPEN_RELAY, - '127.0.0.3' => Net::DNSBLLookup::DNSBLLOOKUP_DYNAMIC_IP, - '127.0.0.4' => Net::DNSBLLookup::DNSBLLOOKUP_SPAMHOUSE, - '127.0.0.5' => Net::DNSBLLookup::DNSBLLOOKUP_MULTI_OPEN_RELAY, - '127.0.0.8' => Net::DNSBLLookup::DNSBLLOOKUP_FORMMAIL, - '127.0.0.9' => Net::DNSBLLookup::DNSBLLOOKUP_OPEN_PROXY, - }, - 'bl.spamcop.net' => { - '127.0.0.2' => Net::DNSBLLookup::DNSBLLOOKUP_UNKNOWN, - }, - 'unconfirmed.dsbl.org' => { - '127.0.0.2' => Net::DNSBLLookup::DNSBLLOOKUP_UNKNOWN, - }, - 'list.dsbl.org' => { - '127.0.0.2' => Net::DNSBLLookup::DNSBLLOOKUP_UNKNOWN, - }, - 'sbl.spamhaus.org' => { - '127.0.0.2' => Net::DNSBLLookup::DNSBLLOOKUP_SPAMHOUSE, - }, - 'pbl.spamhaus.org' => { - '127.0.0.10' => Net::DNSBLLookup::DNSBLLOOKUP_DYNAMIC_IP, - '127.0.0.11' => Net::DNSBLLookup::DNSBLLOOKUP_DYNAMIC_IP, - }, - 'cbl.abuseat.org' => { - '127.0.0.2' => Net::DNSBLLookup::DNSBLLOOKUP_OPEN_PROXY, - }, - 'psbl.surriel.com' => { - '127.0.0.2' => Net::DNSBLLookup::DNSBLLOOKUP_OPEN_PROXY, - }, - ); - - use Net::DNSBLLookup::Result; - {package Net::DNSBLLookup::Result; - our %result_type; - no warnings 'redefine'; - sub breakdown { - my ($self)=@_; - my ($total_spam, $total_proxy, $total_unknown, $total_dyn) = (0,0,0); - return unless exists $self->{results}; - while (my ($dnsbl, $v) = each %{$self->{results}}) { - my ($is_spam, $is_proxy, $is_unknown, $is_dyn) = (0,0,0,0); - for my $retval (@$v) { - my $result_type = $result_type{$retval}; - if ($result_type == DNSBLLOOKUP_RESULT_OPEN_PROXY) { - $is_proxy = 1; - } elsif ($result_type == DNSBLLOOKUP_RESULT_SPAM) { - $is_spam = 1; - } elsif ($result_type == DNSBLLOOKUP_RESULT_UNKNOWN) { - $is_unknown = 1; - } elsif ($result_type == DNSBLLOOKUP_RESULT_DYNAMIC_IP) { - $is_dyn = 1; - } - } - $total_proxy += $is_proxy; - $total_spam += $is_spam; - $total_dyn += $is_dyn; - unless ($is_proxy || $is_spam || $is_dyn) { - $total_unknown += $is_unknown; - } - } - return ($total_proxy, $total_spam, $total_dyn, $total_unknown); - } -} -} - my $DBNAME; sub get_from_env { @@ -191,7 +112,7 @@ sub check { {},time(),$host,$from,$to); } else { - # prbobaly a bounce + # probably a bounce my $ret=$dbh->do('DELETE FROM attempts WHERE host=? AND smtpfrom=? AND smtprcpt=?', {},$host,$from,$to); } @@ -207,7 +128,7 @@ sub check { sub is_blacklisted { my ($host)=@_; - my $look=Net::DNSBLLookup->new(); + my $look=DAKKAR::Net::DNSBLLookup->new(); my $ret=$look->lookup($host); my ($proxy, $spam, $dyn, $unknown) = $ret->breakdown; return ($proxy+$spam+$dyn+$unknown > 0); diff --git a/lib/DAKKAR/Net/DNSBLLookup.pm b/lib/DAKKAR/Net/DNSBLLookup.pm new file mode 100644 index 0000000..9b03cbb --- /dev/null +++ b/lib/DAKKAR/Net/DNSBLLookup.pm @@ -0,0 +1,209 @@ +package DAKKAR::Net::DNSBLLookup; + +# copied from Net::DNSBLLookup v0.03 + +use 5.005; +use strict; + +require Exporter; +use AutoLoader qw(AUTOLOAD); +use vars qw($VERSION @EXPORT @ISA); +use Net::DNS; +use IO::Select; +$VERSION = '0.04'; +@ISA = qw(Exporter); + +@EXPORT = qw(DNSBLLOOKUP_OPEN_RELAY DNSBLLOOKUP_DYNAMIC_IP + DNSBLLOOKUP_CONFIRMED_SPAM DNSBLLOOKUP_SMARTHOST DNSBLLOOKUP_SPAMHOUSE DNSBLLOOKUP_LISTSERVER + DNSBLLOOKUP_FORMMAIL DNSBLLOOKUP_OPEN_PROXY DNSBLLOOKUP_OPEN_PROXY_HTTP DNSBLLOOKUP_OPEN_PROXY_SOCKS + DNSBLLOOKUP_OPEN_PROXY_MISC DNSBLLOOKUP_HIJACKED DNSBLLOOKUP_MULTI_OPEN_RELAY DNSBLLOOKUP_UNKNOWN); + +use constant DNSBLLOOKUP_OPEN_RELAY => 1; +use constant DNSBLLOOKUP_DYNAMIC_IP => 2; +use constant DNSBLLOOKUP_CONFIRMED_SPAM => 3; +use constant DNSBLLOOKUP_SMARTHOST => 4; +use constant DNSBLLOOKUP_SPAMHOUSE => 5; +use constant DNSBLLOOKUP_LISTSERVER => 6; +use constant DNSBLLOOKUP_FORMMAIL => 7; +use constant DNSBLLOOKUP_OPEN_PROXY => 8; +use constant DNSBLLOOKUP_OPEN_PROXY_HTTP => 9; +use constant DNSBLLOOKUP_OPEN_PROXY_SOCKS => 10; +use constant DNSBLLOOKUP_OPEN_PROXY_MISC => 11; +use constant DNSBLLOOKUP_HIJACKED => 12; +use constant DNSBLLOOKUP_MULTI_OPEN_RELAY => 13; +use constant DNSBLLOOKUP_UNKNOWN => 14; + +require DAKKAR::Net::DNSBLLookup::Result; + +# updated DNSBL lists + +our %dns_servers = ( + 'dnsbl.sorbs.net' => { + '127.0.0.2' => DNSBLLOOKUP_OPEN_PROXY_HTTP, + '127.0.0.3' => DNSBLLOOKUP_OPEN_PROXY_SOCKS, + '127.0.0.4' => DNSBLLOOKUP_OPEN_PROXY_MISC, + '127.0.0.5' => DNSBLLOOKUP_OPEN_RELAY, + '127.0.0.6' => DNSBLLOOKUP_SPAMHOUSE, + '127.0.0.7' => DNSBLLOOKUP_FORMMAIL, + '127.0.0.8' => DNSBLLOOKUP_CONFIRMED_SPAM, + '127.0.0.9' => DNSBLLOOKUP_HIJACKED, + '127.0.0.10' => DNSBLLOOKUP_DYNAMIC_IP, + }, + 'dnsbl.njabl.org' => { + '127.0.0.2' => DNSBLLOOKUP_OPEN_RELAY, + '127.0.0.3' => DNSBLLOOKUP_DYNAMIC_IP, + '127.0.0.4' => DNSBLLOOKUP_SPAMHOUSE, + '127.0.0.5' => DNSBLLOOKUP_MULTI_OPEN_RELAY, + '127.0.0.8' => DNSBLLOOKUP_FORMMAIL, + '127.0.0.9' => DNSBLLOOKUP_OPEN_PROXY, + }, + 'bl.spamcop.net' => { + '127.0.0.2' => DNSBLLOOKUP_UNKNOWN, + }, + 'unconfirmed.dsbl.org' => { + '127.0.0.2' => DNSBLLOOKUP_UNKNOWN, + }, + 'list.dsbl.org' => { + '127.0.0.2' => DNSBLLOOKUP_UNKNOWN, + }, + 'sbl.spamhaus.org' => { + '127.0.0.2' => DNSBLLOOKUP_SPAMHOUSE, + }, + 'pbl.spamhaus.org' => { + '127.0.0.10' => DNSBLLOOKUP_DYNAMIC_IP, + '127.0.0.11' => DNSBLLOOKUP_DYNAMIC_IP, + }, + 'cbl.abuseat.org' => { + '127.0.0.2' => DNSBLLOOKUP_OPEN_PROXY, + }, + 'psbl.surriel.com' => { + '127.0.0.2' => DNSBLLOOKUP_OPEN_PROXY, + }, +); + +sub new { + my ($class) = shift; + my $self = { @_ }; + bless $self, $class; + unless (exists $self->{zones}) { + @{$self->{zones}} = grep !/^relays.osirusoft.com$/, keys %dns_servers; + } + $self->{timeout} ||= 5; + return $self; +} + +sub lookup { + my ($self, $ip) = @_; + + my $res = Net::DNS::Resolver->new; + my $sel = IO::Select->new; + my @sockets; + + my $result = DAKKAR::Net::DNSBLLookup::Result->new(); + + my $reverse_ip = join('.',reverse split('\.',$ip)); + + for my $zone (@{$self->{zones}}) { + my $host = join('.',$reverse_ip,$zone); + my $socket = $res->bgsend($host); + $sel->add($socket); + undef $socket; + } + + while ($sel->count > 0) { + my @ready = $sel->can_read($self->{timeout}); + last unless @ready; + foreach my $sock (@ready) { + my $packet = $res->bgread($sock); + my ($question) = $packet->question; + next unless $question; + my $qname = $question->qname; + (my $dnsbl = $qname) =~ s!^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\.!!; + $result->add_dnsbl($dnsbl); + foreach my $rr ($packet->answer) { + next unless $rr->type eq "A"; + $result->add($dnsbl, $rr->address); + } + $sel->remove($sock); + $sock = undef; + } + } + return $result; +} + +1; +__END__ + +=head1 NAME + +Net::DNSBLLookup - Lookup IP Address in Open Proxy and SPAM DNS Blocklists + +=head1 SYNOPSIS + + use Net::DNSBLLookup; + my $dnsbl = Net::DNSBLLookup->new(timeout => 5); + my $res = $dnsbl->lookup($ip_addr); + my ($proxy, $spam, $unknown) = $res->breakdown; + my $num_responded = $res->num_proxies_responded; + +=head1 ABSTRACT + +This module queries the major Open Proxy DNS Blocklists, including Sorbs, +Easynet, NJABL, DSBL, Blitzed, CBL and PSBL. Open Proxies are servers that allow +hackers to mask their true IP address. Some of these blocklists also contain +hosts that have been known to send spam. This module distinguishes the +results between Open Proxy and Spam/Open Relay servers. + +=head1 DESCRIPTION + +This module can be used to block or flag Internet connections coming from +Open Proxy or Spam servers. Why would you want to do this? Hackers often +use Open Proxy servers to hide their true IP address when doing "bad" stuff. +This includes using purchasing stuff with stolen credit cards, and getting +around IP Address based restrictions + +=head1 METHODS + +=over 4 + +=item new + +Calls C to create a new DNSBLLookup object: + + $dnsbl = new Net::DNSBLLookup(timeout => 5); + +Takes timeout as an argument, defaults to 5 seconds if not specified. The module +waits C seconds before giving up on a slow DNS host. + +=item lookup + +This sends out a lookup to the major DNS Blocklists, and waits up to C +seconds then returns the results: + + $res = $dnsbl->lookup($ip_addr); + +=back + +=head1 SEE ALSO + +L + +There is a free credit card fraud prevention service that +uses this module located at +L + +=head1 AUTHOR + +TJ Mather, Etjmather@maxmind.comE + +Paid support is available from directly from the author of this package. +Please see L for more details. + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Maxmind LLC + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/DAKKAR/Net/DNSBLLookup/Result.pm b/lib/DAKKAR/Net/DNSBLLookup/Result.pm new file mode 100644 index 0000000..1c57e8f --- /dev/null +++ b/lib/DAKKAR/Net/DNSBLLookup/Result.pm @@ -0,0 +1,144 @@ +package DAKKAR::Net::DNSBLLookup::Result; + +# copied from Net::DNSBLLookup v0.03 + +use DAKKAR::Net::DNSBLLookup; + +use strict; + +use constant DNSBLLOOKUP_RESULT_OPEN_PROXY => 1; +use constant DNSBLLOOKUP_RESULT_SPAM => 2; +use constant DNSBLLOOKUP_RESULT_UNKNOWN => 3; +use constant DNSBLLOOKUP_RESULT_DYNAMIC_IP => 4; + +my %result_type = ( + DNSBLLOOKUP_OPEN_RELAY() => DNSBLLOOKUP_RESULT_SPAM, + DNSBLLOOKUP_DYNAMIC_IP() => DNSBLLOOKUP_RESULT_DYNAMIC_IP, + DNSBLLOOKUP_CONFIRMED_SPAM() => DNSBLLOOKUP_RESULT_SPAM, + DNSBLLOOKUP_SMARTHOST() => DNSBLLOOKUP_RESULT_SPAM, + DNSBLLOOKUP_SPAMHOUSE() => DNSBLLOOKUP_RESULT_SPAM, + DNSBLLOOKUP_LISTSERVER() => DNSBLLOOKUP_RESULT_SPAM, + DNSBLLOOKUP_FORMMAIL() => DNSBLLOOKUP_RESULT_SPAM, + DNSBLLOOKUP_OPEN_PROXY() => DNSBLLOOKUP_RESULT_OPEN_PROXY, + DNSBLLOOKUP_OPEN_PROXY_HTTP() => DNSBLLOOKUP_RESULT_OPEN_PROXY, + DNSBLLOOKUP_OPEN_PROXY_SOCKS() => DNSBLLOOKUP_RESULT_OPEN_PROXY, + DNSBLLOOKUP_OPEN_PROXY_MISC() => DNSBLLOOKUP_RESULT_OPEN_PROXY, + DNSBLLOOKUP_HIJACKED() => DNSBLLOOKUP_RESULT_SPAM, + DNSBLLOOKUP_MULTI_OPEN_RELAY() => DNSBLLOOKUP_RESULT_SPAM, + DNSBLLOOKUP_UNKNOWN() => DNSBLLOOKUP_RESULT_UNKNOWN, + ); + +sub new { + my ($class) = @_; + my $self = bless {}, $class; + $self->{results} = {}; + return $self; +} + +sub add { + my ($self, $dnsbl, $address) = @_; + my $address_lookup = $Net::DNSBLLookup::dns_servers{$dnsbl}; + if (ref($address_lookup) eq 'HASH') { + push @{$self->{results}->{$dnsbl}}, $address_lookup->{$address}; + } elsif (ref($address_lookup) eq 'CODE') { + push @{$self->{results}->{$dnsbl}}, &$address_lookup($address); + } +} + +sub add_dnsbl { + my ($self, $dnsbl) = @_; + $self->{dnsbl_responded}->{$dnsbl} = 1; +} + +sub num_proxies_responded { + my ($self) = @_; + return scalar(keys %{$self->{dnsbl_responded}}); +} + +sub breakdown { + my ($self) = @_; + my ($total_spam, $total_proxy, $total_dyn, $total_unknown) = (0,0,0,0); + return unless exists $self->{results}; + while (my ($dnsbl, $v) = each %{$self->{results}}) { + my ($is_spam, $is_proxy, $is_dyn, $is_unknown) = (0,0,0,0); + for my $retval (@$v) { + my $result_type = $result_type{$retval}; + if ($result_type == DNSBLLOOKUP_RESULT_OPEN_PROXY) { + $is_proxy = 1; + } elsif ($result_type == DNSBLLOOKUP_RESULT_SPAM) { + $is_spam = 1; + } elsif ($result_type == DNSBLLOOKUP_RESULT_DYNAMIC_IP) { + $is_dyn = 1; + } elsif ($result_type == DNSBLLOOKUP_RESULT_UNKNOWN) { + $is_unknown = 1; + } + } + $total_proxy += $is_proxy; + $total_spam += $is_spam; + $total_dyn += $is_dyn; + unless ($is_proxy || $is_spam || $is_dyn) { + $total_unknown += $is_unknown; + } + } + return ($total_proxy, $total_spam, $total_dyn, $total_unknown); +} + +1; + +__END__ + +=head1 NAME + +Net::DNSBLLookup::Result - Analyze the DNS Blocklist lookup results + +=head1 SYNOPSIS + + use Net::DNSBLLookup; + my $dnsbl = Net::DNSBLLookup->new(timeout => 5); + my $res = $dnsbl->lookup($ip_addr); + my ($proxy, $spam, $unknown) = $res->breakdown; + my $num_responded = $res->num_proxies_responded; + +=head1 DESCRIPTION + +The class represents objects returned by the lookup method of L. +Currently it supports the breakdown between the number of Open Proxy and Spam hosts, as +well as the number of DNS Blocklist servers that actually responded. + +=head1 METHODS + +=over 4 + +=item breakdown + +Returns the breakdown between the number of Open Proxy and Spam/Open Relay hosts. +It also returns the number of hits that are unknown - for example the DSBL blocklist +lumps all Open Proxy and Spam results into one code. + + ($proxy, $spam, $unknown) = $res->breakdown; + +=item num_responded + +Returns the total number of DNS Blocklists that responded to our queries within +C seconds or less. + + $num_responded = $res->num_proxies_responded; + +=back + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +TJ Mather, Etjmather@maxmind.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by MaxMind LLC + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut -- cgit v1.2.3