-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmx-geoip.pl
executable file
·189 lines (156 loc) · 3.88 KB
/
mx-geoip.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
use Pod::Usage;
use Getopt::Long;
use Net::DNS;
use Geo::IP;
# global program parameters
my $DEBUG = 0; # set to true if you want some debug output
my $filename;
my $country = 'SE'; # default home country, ISO 3166-1
# global resolver
my $res = Net::DNS::Resolver->new;
$res->nameservers('127.0.0.1');
$res->recurse(1);
$res->cdflag(0);
$res->udppacketsize(4096);
$res->tcp_timeout(10);
$res->udp_timeout(10);
# geoip configuration
my $gi = Geo::IP->open("./GeoLiteCity.dat", GEOIP_MEMORY_CACHE);
die "No GeoLiteCity.dat file available, get from http://dev.maxmind.com/geoip/legacy/geolite/" unless defined $gi;
# fetch all data we need for a domain name, returns with an array
sub readA
{
my $name = shift;
my @a;
print "Quering A for $name\n" if $DEBUG;
my $answer = $res->send($name,'A');
return if not defined $answer;
foreach my $data ($answer->answer)
{
if ($data->type eq 'A') {
push @a, $data->address;
}
}
return @a;
}
# fetch all data we need for a domain name, returns with an array
sub readMX
{
my $name = shift;
my @mx;
print "Quering MX for $name\n" if $DEBUG;
my $answer = $res->send($name,'MX');
return if not defined $answer;
foreach my $data ($answer->answer)
{
if ($data->type eq 'MX') {
push @mx, $data->exchange;
}
}
return @mx;
}
sub readGeoIP {
my $ip = shift;
print "Querying geo for $ip\n" if $DEBUG;
my $record = $gi->record_by_addr($ip);
return $record->country_code;
}
sub runQueue
{
open FILE, "$filename" or die "Cannot read file $filename: $!";
my $homecount = 0;
my $allhomecount = 0;
my $foreigncount = 0;
my $totalcount = 0;
my $missingmx = 0;
while ( <FILE> ) {
chomp;
my $name = $_;
my (@ip, @mx, @cc);
# Lookup all data
@mx = readMX($_); # Lookup MX from name
push @ip, map { readA($_); } @mx; # Lookup IP from MX
push @cc, map { readGeoIP($_); } @ip; # Lookup GeoIP from IP
# Output all collected data
print "$name:";
map { print " $_"; } @cc, @mx, @ip;
print "\n";
# Counters
$totalcount++;
if ($country ~~ @cc)
{
$homecount++;
} else
{
$foreigncount++;
}
$missingmx++ if $#mx == -1; # if no MX at all
# all home counter
my $hc = 0; my $fc = 0;
foreach (@cc)
{
if ($_ eq $country)
{
$hc++; # home
} else
{
$fc++; #foreign
}
}
if ($hc > 1 and $fc == 0)
{
$allhomecount++;
}
}
print "Total with only MX in $country: $allhomecount\n";
print "Total with some MX in $country: $homecount\n";
print "Total with MX outside of $country: $foreigncount\n";
print "Total missing MX: $missingmx\n";
print "All names: $totalcount\n";
close FILE;
return;
}
sub main() {
# non-global program parameters
my $help = 0;
my $name;
GetOptions('help|?' => \$help,
'name|n=s' => \$name,
'file|f=s' => \$filename,
'country|c=s' => \$country,
'debug' => \$DEBUG,
)
or pod2usage(2);
pod2usage(1) if($help);
pod2usage(1) if(not defined $name and not defined $filename);
if (defined $name) {
my (@ip, @mx, @cc);
@mx = readMX($name);
push @ip, map { readA($_); } @mx; # Lookup IP from MX
push @cc, map { readGeoIP($_); } @ip; # Lookup GeoIP from IP
# Output all collected data
print "$name:";
map { print " $_"; } @cc, @mx, @ip;
print "\n";
} elsif (defined $filename) {
runQueue($filename);
}
}
main;
=head1 NAME
collect
=head1 SYNOPSIS
collect.pl -n domain
-n domain specify name
-f file.txt read list of names from file
-h country specify "home" country (default SE) in ISO 3166-1
--debug debug mode
=head1 DESCRIPTION
gets countries, hostnames and IP addresses of the MX of all input domain names
=head1 AUTHOR
Patrik Wallstrom <[email protected]>
=cut