ASN lookups now work

This commit is contained in:
Matt Simerson 2014-11-05 13:50:19 -08:00
parent 4eba2a39bc
commit f2eda74074
3 changed files with 113 additions and 54 deletions

View File

@ -39,4 +39,11 @@ sub is_valid_ip {
return;
}
sub is_ipv6 {
my ($self, $ip) = @_;
return if !$ip;
return 1 if Net::IP::ip_is_ipv6($ip);
return;
};
1;

View File

@ -102,6 +102,8 @@ data source: http://software77.net/geo-ip/
=head1 ACKNOWLEDGEMENTS
MaxMind - the packager and distributor of the free GeoIP data
Stevan Bajic, the DSPAM author, who suggested SNARE, which describes using
geodesic distance to determine spam probability. The research paper on SNARE
can be found here:
@ -126,27 +128,12 @@ sub register {
$self->{_args} = {@args};
$self->{_args}{db_dir} ||= '/usr/local/share/GeoIP';
eval 'use GeoIP2::Database::Reader';
if (!$@) {
warn "using GeoIP2";
$self->log(LOGINFO, "using GeoIP2");
$self->load_geoip2() and return;
$self->load_geoip1();
}
eval {
$self->{_geoip2_city} = GeoIP2::Database::Reader->new(
file => $self->{_args}{db_dir} . '/GeoLite2-City.mmdb',
);
};
eval {
$self->{_geoip2_country} = GeoIP2::Database::Reader->new(
file => $self->{_args}{db_dir} . '/GeoLite2-Country.mmdb',
);
};
$self->register_hook('connect', 'geoip2_lookup');
return;
}
warn "could not load GeoIP2";
$self->log(LOGERROR, "could not load GeoIP2");
sub load_geoip1 {
my $self = shift;
eval 'use Geo::IP';
if ($@) {
@ -166,6 +153,43 @@ sub register {
$self->register_hook('connect', 'geoip_lookup');
}
sub load_geoip2 {
my $self = shift;
eval 'use GeoIP2::Database::Reader';
if ($@) {
$self->log(LOGERROR, "could not load GeoIP2");
return;
}
$self->log(LOGINFO, "GeoIP2 loaded");
eval {
$self->{_geoip2_city} = GeoIP2::Database::Reader->new(
file => $self->{_args}{db_dir} . '/GeoLite2-City.mmdb',
);
};
if ($@) {
$self->log(LOGERROR, "unable to load GeoLite2-City.mmdb");
}
eval {
$self->{_geoip2_country} = GeoIP2::Database::Reader->new(
file => $self->{_args}{db_dir} . '/GeoLite2-Country.mmdb',
);
};
if ($@) {
$self->log(LOGERROR, "unable to load GeoLite2-Country.mmdb");
}
if ($self->{_geoip2_city} || $self->{_geoip2_country}) {
$self->register_hook('connect', 'geoip2_lookup');
return 1;
}
return;
}
sub geoip2_lookup {
my $self = shift;
@ -246,14 +270,18 @@ sub open_geoip_db {
my $db_dir = $self->{_args}{db_dir};
foreach my $db (qw/ GeoIPCity GeoLiteCity /) {
next if !-f "$db_dir/$db.dat";
$self->log(LOGDEBUG, "using db $db");
$self->log(LOGINFO, "using db $db");
$self->{_geoip_city} = Geo::IP->open("$db_dir/$db.dat");
}
foreach my $db (qw/ GeoIPASNum GeoIPASNumv6 /) {
next if !-f "$db_dir/$db.dat";
$self->log(LOGDEBUG, "using db $db");
$self->{$db} = Geo::IP->open("$db_dir/$db.dat");
if (-f "$db_dir/GeoIPASNum.dat") {
$self->log(LOGINFO, "using GeoIPASNum");
$self->{GeoIPASNum} = Geo::IP->open("$db_dir/GeoIPASNum.dat");
}
if (-f "$db_dir/GeoIPASNumv6.dat") {
$self->log(LOGINFO, "using GeoIPASNumv6");
$self->{GeoIPASNumv6} = Geo::IP->open("$db_dir/GeoIPASNumv6.dat");
}
# can't think of a good reason to load country if city data is present
@ -338,23 +366,28 @@ sub get_continent_gc {
}
sub set_asn {
my ($self) = @_;
my $remote_ip = $self->qp->connection->remote_ip;
my ($self, $ip) = @_;
$ip ||= $self->qp->connection->remote_ip;
if (Qpsmtpd::Base->is_ipv6($ip)) {
return $self->set_asn_ipv6($ip);
}
return if ! $self->{GeoIPASNum};
my $asn = $self->{GeoIPASNum}
? $self->get_asn_gc($remote_ip)
: $self->{_geoip}->asn_by_addr($remote_ip);
$asn or return;
my $asn = $self->{GeoIPASNum}->name_by_addr($ip) or return;
$self->qp->connection->notes('geoip_asn', $asn);
return $asn;
}
sub get_asn_gc {
my $self = shift;
return if !$self->{GeoIPASNum};
return $self->{GeoIPASNum}->asn_by_addr();
sub set_asn_ipv6 {
my ($self, $ip) = @_;
$ip ||= $self->qp->connection->remote_ip;
return if ! $self->{GeoIPASNumv6};
my $asn = $self->{GeoIPASNumv6}->name_by_addr_v6($ip) or return;
$self->qp->connection->notes('geoip_asn', $asn);
return $asn;
}
sub set_city_gc {

View File

@ -13,14 +13,11 @@ sub register_tests {
if ( !$@ ) {
warn "using GeoIP2\n";
$self->register_test('test_geoip2_lookup');
return;
}
eval 'use Geo::IP';
if ( $@ ) {
warn "could not load Geo::IP\n";
return;
};
if ( !$@ ) {
warn "loaded Geo::IP\n";
$self->register_test('test_geoip_lookup');
$self->register_test('test_geoip_load_db');
@ -29,19 +26,24 @@ sub register_tests {
$self->register_test('test_set_country_name');
$self->register_test('test_set_continent');
$self->register_test('test_set_distance');
$self->register_test('test_set_isp');
$self->register_test('test_set_asn');
};
};
sub test_geoip2_lookup {
my $self = shift;
$self->qp->connection->remote_ip('24.24.24.24');
cmp_ok( $self->geoip2_lookup(), '==', DECLINED, "exit code");
cmp_ok( $self->geoip2_lookup(), '==', DECLINED, "exit code DECLINED");
cmp_ok( $self->connection->notes('geoip_country'), 'eq', 'US', "24.24.24.24 is in the US");
cmp_ok( $self->connection->notes('geoip_country_name'), 'eq', 'United States', "24.24.24.24 is in the United States");
cmp_ok( $self->connection->notes('geoip_continent'), 'eq', 'NA', "24.24.24.24 is in NA");
cmp_ok( $self->connection->notes('geoip_city'), 'eq', 'Deer Park', "24.24.24.24 is in Deer Park");
if (!$self->load_geoip2()) {
warn "failed to load GeoIP2\n";
}
cmp_ok( $self->connection->notes('geoip_country'), 'eq', 'US', "24.24.24.24 is in country US");
cmp_ok( $self->connection->notes('geoip_country_name'), 'eq', 'United States', "24.24.24.24 is in country United States");
cmp_ok( $self->connection->notes('geoip_continent'), 'eq', 'NA', "24.24.24.24 is in continent NA");
cmp_ok( $self->connection->notes('geoip_city'), 'eq', 'Deer Park', "24.24.24.24 is in city of Deer Park");
};
sub test_geoip_lookup {
@ -164,3 +166,20 @@ sub test_set_distance {
ok( 1, "no distance data");
}
};
sub test_set_asn {
my $self = shift;
$self->qp->connection->remote_ip('');
$self->set_asn();
my $asn = $self->set_asn();
ok( ! $asn, "undef") or warn "$asn\n";
$self->qp->connection->remote_ip('24.24.24.24');
$asn = $self->set_asn();
ok( $self->connection->notes('geoip_asn') =~ /^AS11351/, "note has: $asn");
$self->qp->connection->remote_ip('66.128.51.163');
$asn = $self->set_asn();
ok( $self->connection->notes('geoip_asn') =~ /^AS7819/, "note has: $asn");
};