0a9f5ba6e034b880c1d62a4c858fe4e735d9ded9
[spider.git] / perl / create_master_badip_files.pl
1 #!/usr/bin/env perl
2 #
3 # Get the TOR exit and relay lists from the net, extract the exit and relay
4 # node ip addresses and store them, one per line, in the standard places
5 # in /spider/local_data. 
6 #
7
8 use 5.16.1;
9
10 # search local then perl directories
11 BEGIN {
12         # root of directory tree for this system
13         $root = "/spider"; 
14         $root = $ENV{'DXSPIDER_ROOT'} if $ENV{'DXSPIDER_ROOT'};
15
16         mkdir "$root/local_data", 02777 unless -d "$root/local_data";
17
18         unshift @INC, "$root/perl";     # this IS the right way round!
19         unshift @INC, "$root/local";
20         $data = "$root/data";
21 }
22
23 use strict;
24 use DXVars;
25 use SysVar;
26
27 use DXDebug;
28 use DXUtil;
29
30 use LWP::Simple;
31 use JSON;
32 use Date::Parse;
33 use File::Copy;
34
35 DXDebug::dbginit();
36
37 $ENV{PERL_JSON_BACKEND} = "JSON::XS,JSON::PP";
38
39
40 my $debug;
41
42 if (@ARGV && $ARGV[0] eq '-x') {
43         shift;
44         $debug = 1;
45 }
46 my $url = "https://onionoo.torproject.org/details";
47 my $relayfn = localdata('badip.torrelay');
48 my $exitfn = localdata('badip.torexit');
49
50 my $last_seen_window = 10800;
51 my $content;
52
53 if (@ARGV) {
54         local $/ = undef;
55         my $fn = shift;
56         open IN, $fn or die "$0 cannot open file $fn, $!";
57         $content = <IN>;
58         close IN;
59 } else {
60         $content = get($url) or die "$0: connect error on $url, $!\n";
61 }
62
63 die "No TOR content available $!\n" unless $content;
64
65 my $l = length $content;
66 my $data = decode_json($content);
67 my $now = time;
68 my $ecount = 0;
69 my $rcount = 0;
70
71 my $rand = rand;
72 open RELAY, ">$relayfn.$rand" or die "$0: cannot open $relayfn $!";
73 open EXIT, ">$exitfn.$rand" or die "$0: cannot open $exitfn $1";
74
75 foreach my $e (@{$data->{relays}}) {
76
77         my $seen = str2time($e->{last_seen});
78         next unless $seen >= $now - $last_seen_window;
79         
80         my @or = clean_addr(@{$e->{or_addresses}}) if exists $e->{or_addresses};
81         my @exit = clean_addr(@{$e->{exit_addresses}}) if exists $e->{exit_addresses} ;
82         my $ors = join ', ', @or;
83         my $es = join ', ', @exit;
84         dbg "$0: $e->{nickname} $e->{last_seen} relays: [$ors] exits: [$es]" if $debug;
85         for (@or) {
86                 print RELAY "$_\n";
87                 ++$rcount;
88         }
89         for (@exit) {
90                 print EXIT "$_\n";
91                 ++$ecount;
92         }
93 }
94
95 close RELAY;
96 close EXIT;
97
98 dbg("$0: $rcount relays $ecount exits found");
99 move "$relayfn.$rand", $relayfn if $rcount;
100 move "$exitfn.$rand", $exitfn if $ecount;
101 unlink "$relayfn.$rand";
102 unlink "$exitfn.$rand";
103
104 exit 0;
105
106 sub clean_addr
107 {
108         my @out;
109         foreach (@_) {
110                 my ($ipv4) = /^((?:\d+\.){3}\d+)/;
111                 if ($ipv4) {
112                         push @out, $ipv4;
113                         next;
114                 }
115                 my ($ipv6) = /^\[([:a-f\d]+)\]/;
116                 push @out, $ipv6 if $ipv6;
117         }
118         return @out;
119 }