File Coverage

blib/lib/Metabrik/Server/Tor.pm
Criterion Covered Total %
statement 9 64 14.0
branch 0 30 0.0
condition 0 8 0.0
subroutine 3 10 30.0
pod 2 7 28.5
total 14 119 11.7


line stmt bran cond sub pod time code
1             #
2             # $Id$
3             #
4             # server::tor Brik
5             #
6             package Metabrik::Server::Tor;
7 1     1   804 use strict;
  1         2  
  1         29  
8 1     1   5 use warnings;
  1         2  
  1         29  
9              
10 1     1   4 use base qw(Metabrik::Shell::Command Metabrik::System::Package);
  1         2  
  1         989  
11              
12             sub brik_properties {
13             return {
14 0     0 1   revision => '$Revision$',
15             tags => [ qw(unstable) ],
16             author => 'GomoR ',
17             license => 'http://opensource.org/licenses/BSD-3-Clause',
18             attributes => {
19             datadir => [ qw(datadir) ],
20             tor_port => [ qw(port) ],
21             tor_listen => [ qw(address) ],
22             dns_port => [ qw(port) ],
23             dns_listen => [ qw(address) ],
24             virtual_network => [ qw(subnet) ],
25             user => [ qw(user) ],
26             conf => [ qw(file) ],
27             pidfile => [ qw(file) ],
28             },
29             attributes_default => {
30             tor_port => 9051,
31             tor_listen => '127.0.0.1',
32             dns_port => 9061,
33             dns_listen => '127.0.0.1',
34             virtual_network => '10.20.0.0/255.255.0.0',
35             conf => 'torrc',
36             pidfile => 'tor.pid',
37             },
38             commands => {
39             install => [ ], # Inherited
40             generate_conf => [ qw(file|OPTIONAL) ],
41             start => [ qw(conf_file|OPTIONAL) ],
42             stop => [ ],
43             status => [ ],
44             list_exit_nodes => [ ],
45             },
46             require_modules => {
47             'Metabrik::File::Text' => [ ],
48             'Metabrik::System::File' => [ ],
49             'Metabrik::System::Process' => [ ],
50             },
51             require_binaries => {
52             tor => [ ],
53             },
54             need_packages => {
55             ubuntu => [ qw(tor) ],
56             debian => [ qw(tor) ],
57             kali => [ qw(tor) ],
58             },
59             };
60             }
61              
62             sub brik_use_properties {
63 0     0 1   my $self = shift;
64              
65             return {
66 0   0       attributes_default => {
67             user => defined($self->global) && $self->global->username || 'username',
68             },
69             };
70             }
71              
72             #
73             # Inspired by https://github.com/HeitorG/nipe/blob/master/nipe.pl
74             #
75             sub generate_conf {
76 0     0 0   my $self = shift;
77 0           my ($conf) = @_;
78              
79 0   0       $conf ||= $self->conf;
80 0           my $datadir = $self->datadir;
81             # If it does not start with a /, we put it in $datadir
82 0 0         if ($conf !~ m{^/}) {
83 0           $conf = $datadir.'/'.$conf;
84             }
85              
86 0 0         $self->brik_help_run_undef_arg('generate_conf', $conf) or return;
87              
88 0           my $user = $self->user;
89 0           my $pidfile = $self->pidfile;
90 0           my $tor_port = $self->tor_port;
91 0           my $tor_listen = $self->tor_listen;
92 0           my $dns_port = $self->dns_port;
93 0           my $dns_listen = $self->dns_listen;
94 0           my $virtual_network = $self->virtual_network;
95              
96 0 0         my $sf = Metabrik::System::File->new_from_brik_init($self) or return;
97 0           $sf->remove($conf);
98              
99 0           my $data =<
100             DataDirectory $datadir
101             PidFile $datadir/$pidfile
102             RunAsDaemon 1
103             ClientOnly 1
104             User $user
105              
106             ControlSocket $datadir/control
107             ControlSocketsGroupWritable 1
108              
109             CookieAuthentication 1
110             CookieAuthFileGroupReadable 1
111             CookieAuthFile $datadir/control.authcookie
112              
113             Log notice file $datadir/tor.log
114              
115             TransPort $tor_port
116             TransListenAddress $tor_listen
117             DNSPort $dns_port
118             DNSListenAddress $dns_listen
119              
120             VirtualAddrNetwork $virtual_network
121             AutomapHostsOnResolve 1
122             EOF
123             ;
124              
125 0 0         my $ft = Metabrik::File::Text->new_from_brik_init($self) or return;
126 0 0         $ft->write($data, $conf) or return;
127 0           $ft->close;
128              
129 0 0         $sf->chmod($datadir, "0700") or return;
130              
131 0           return $conf;
132             }
133              
134             sub start {
135 0     0 0   my $self = shift;
136 0           my ($conf) = @_;
137              
138 0   0       $conf ||= $self->conf;
139 0 0         $self->brik_help_run_undef_arg('start', $conf) or return;
140              
141 0           my $datadir = $self->datadir;
142              
143             # If it does not start with a /, we put it in $datadir
144 0 0         if ($conf !~ m{^/}) {
145 0           $conf = $datadir.'/'.$conf;
146             }
147              
148 0           my $cmd = "tor -f \"$conf\"";
149              
150 0           return $self->sudo_system($cmd);
151             }
152              
153             sub stop {
154 0     0 0   my $self = shift;
155              
156 0           my $datadir = $self->datadir;
157 0           my $pidfile = $self->pidfile;
158              
159 0 0         if ($pidfile !~ m{^/}) {
160 0           $pidfile = $datadir.'/'.$pidfile;
161             }
162              
163 0 0         my $sp = Metabrik::System::Process->new_from_brik_init($self) or return;
164 0 0         $sp->kill_from_pidfile($pidfile) or return;
165              
166 0           return 1;
167             }
168              
169             sub status {
170 0     0 0   my $self = shift;
171              
172 0           my $datadir = $self->datadir;
173 0           my $pidfile = $self->pidfile;
174              
175 0 0         if ($pidfile !~ m{^/}) {
176 0           $pidfile = $datadir.'/'.$pidfile;
177             }
178              
179 0 0         my $sp = Metabrik::System::Process->new_from_brik_init($self) or return;
180 0           return $sp->is_running_from_pidfile($pidfile);
181             }
182              
183             #
184             # Alternatives URLs:
185             # https://www.dan.me.uk/torlist/
186             # https://check.torproject.org/exit-addresses
187             # https://www.dan.me.uk/torcheck?ip=2.100.184.78
188             # https://globe.torproject.org/
189             # https://atlas.torproject.org/
190             #
191             sub list_exit_nodes {
192 0     0 0   my $self = shift;
193              
194 0 0         my $cw = Metabrik::Client::Www->new_from_brik_init($self) or return;
195 0 0         my $get = $cw->get('http://torstatus.blutmagie.de/ip_list_exit.php/Tor_ip_list_EXIT.csv')
196             or return;
197              
198 0           my $content = $get->{content};
199 0           my @ip_list = split(/\n/, $content);
200              
201 0           return \@ip_list;
202             }
203              
204             1;
205              
206             __END__