forked from pawal/torrent-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
collect.pl
executable file
·179 lines (156 loc) · 3.99 KB
/
collect.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
#!/usr/bin/perl
use strict;
use warnings;
use URI;
use Net::DNS;
use List::Compare;
use JSON -support_by_pp;
use Fcntl qw(:flock);
use Data::Dumper;
# options
my $file = 'data.json';
my $oldfile = $file.'.old';
my $trackerlist = 'list.txt';
my $resolver = '127.0.0.1';
my $DEBUG = 0;
sub getHosts {
my $file = shift;
open TRACKERS, $file or die "Cannot read trackers list from file $file";
my @trackers = <TRACKERS>;
close TRACKERS;
my @hosts;
foreach (@trackers) {
s/^udp(.*)/http$1/; # udp is not a recognized url
my $url = URI->new($_);
my $domain = $url->host;
push @hosts, $domain;
}
# return a unique array
my %unique;
for (@hosts) { $unique{$_}++; }
@hosts = sort keys %unique;
return \@hosts;
}
sub collectDNS {
my $hosts = shift;
my $res = Net::DNS::Resolver->new;
$res->nameservers($resolver);
$res->recurse(1);
my $answer;
my $result;
# resolve names
foreach my $name (@$hosts) {
# initialize arrays for completeness in later comparisons
$result->{$name}->{'A'} = [];
$result->{$name}->{'AAAA'} = [];
# query for A record
$answer = $res->send($name,'A');
if (defined $answer) {
foreach my $data ($answer->answer)
{
if ($data->type eq 'A') {
print "$name: ".$data->address." (".$data->ttl.")\n" if $DEBUG;
push @{$result->{$name}->{'A'}}, $data->address;
}
}
}
# query for AAAA record
$answer = $res->send($name,'AAAA');
if (defined $answer) {
foreach my $data ($answer->answer)
{
if ($data->type eq 'AAAA') {
print "$name: ".$data->address." (".$data->ttl.")\n" if $DEBUG;
push @{$result->{$name}->{'AAAA'}}, $data->address;
}
}
}
}
return $result;
}
# compare the A and AAAA records for a host and return diff
sub compareHost {
my $old = shift;
my $new = shift;
my @removed;
my @added;
# A
{
my $lc = List::Compare->new($old->{'A'},$new->{'A'});
push @removed, $lc->get_unique;
push @added, $lc->get_complement;
}
# AAAA
{
my $lc = List::Compare->new($old->{'AAAA'},$new->{'AAAA'});
push @removed, $lc->get_unique;
push @added, $lc->get_complement;
}
return \@removed, \@added;
}
# compare the whole set differences for the array of hosts
sub findDifferences {
my $old = shift;
my $new = shift;
my @diff;
foreach my $name ( keys %{$new} ) {
# old name might not exist
if (not defined $old->{$name}) {
$old->{$name}->{'A'} = [];
$old->{$name}->{'AAAA'} = [];
}
my ($removed, $added) = compareHost($old->{$name}, $new->{$name});
# TODO: before adding, maybe do a reverse lookup on the IP?
map { push @diff, "- $name $_" } @$removed;
map { push @diff, "+ $name $_" } @$added;
}
my $result;
map { $result .= "$_\n" } @diff;
return $result;
}
sub getOldFile {
my $file = shift;
my $oldresult = {};
if (not open OLDFILE, $file) {
warn "Cannot read old file: $file";
} else {
my @olddata = <OLDFILE>;
my $olddata = join '', @olddata;
$oldresult = from_json($olddata);
}
close OLDFILE;
return $oldresult;
}
sub sendReport {
my $diff = shift;
my $subject = 'Tracker report';
my $to = 'pawal@iis.se';
my $from = 'pawal@snake.blipp.com';
open(MAIL, "|/usr/sbin/sendmail -t") or die "Cannot send e-mail!";
print MAIL "To: $to\n";
print MAIL "From: $from\n";
print MAIL "Subject: $subject\n\n";
print MAIL $diff;
close(MAIL);
}
sub main {
# this should only run one process at a time
unless (flock(DATA, LOCK_EX|LOCK_NB)) {
print "$0 is already running. Exiting.\n";
exit(1);
}
my $oldresult = getOldFile($file);
my $hosts = getHosts($trackerlist);
my $result = collectDNS($hosts);
rename $file, $oldfile;
open(OUT, '>', $file) or die $!;
print OUT to_json($result, { utf8 => 1 });
close(OUT);
my $diff = findDifferences($oldresult,$result);
if (defined $diff and length($diff) > 0) {
sendReport($diff);
}
}
main();
__DATA__
Data used for locking.