diff --git a/plugins/other/tor-bandwidth-usage b/plugins/other/tor-bandwidth-usage index 26a5f070..316d57ca 100755 --- a/plugins/other/tor-bandwidth-usage +++ b/plugins/other/tor-bandwidth-usage @@ -1,6 +1,6 @@ #!/usr/bin/perl -w # -# tor_bandwidth_acct - munin plugin to monitor Tor routers traffic +# tor-bandwidth-usage - munin plugin to monitor Tor traffic # # To use this plugin you need the following: # o Enable accounting on torrc configuration file (even if you dont want to limit bandwidth usage, @@ -9,145 +9,144 @@ # AccountingStart day 12:00 # AccountingMax 100 GB # o Enable CookieAuthentication (CookieAuthentication 1 in torrc) or define a HashedControlPassword +# o Add something like the following to /etc/munin/plugin-conf.d/munin-node: +# [tor-bandwidth-usage] +# user debian-tor +# env.cookiefile /var/run/tor/control.authcookie # -# tested with Tor releases: 0.2.1.28, 0.2.1.29 # -# Author: tazoi , based on a plugin by Ævar Arnfjörð Bjarmason , based on a plugin by Ævar Arnfjörð Bjarmason # # Parameters understood (defined in file /etc/munin/plugin-conf.d/munin-node or in environment) -# host - Change which host to graph (default localhost) -# port - Change which port to connect to (default 9051) +# host - Change which host to graph (default localhost) +# port - Change which port to connect to (default 9051) # password - Plain-text control channel password (see torrc -# HashedControlPassword parameter) +# HashedControlPassword parameter) # cookiefile - Name of the file containing the control channel cookie -# (see torrc CookieAuthentication parameter) +# (see torrc CookieAuthentication parameter) # -# Using HashedControlPassword authentication has the problem that you must -# include the plain-text password in the munin config file. To have any -# effect, that file shouldn't be world-readable. -# If you're using CookieAuthentication, you should run this plugin as a user -# which has read access to the tor datafiles. Also note that bugs in versions -# upto and including 0.1.1.20 prevent CookieAuthentication from working. +# Using HashedControlPassword authentication has the problem that you +# must include the plain-text password in the munin config file. To +# have any effect, that file shouldn't be world-readable. # -# Usage: place in /etc/munin/node.d/ or in /etc/munin/plugins (or link it there using ln -s) +# If you're using CookieAuthentication, you should run this plugin as +# a user which has read access to the tor datafiles. Also note that +# bugs in versions upto and including 0.1.1.20 prevent +# CookieAuthentication from working. # -# Parameters understood: -# config (required) -# autoconf (optional - used by munin-config) -# -# todo: -# try using "graph_period" option "to make graph_sums usable" -# -# Magic markers - optional - used by installation scripts and -# munin-config: +# Usage: place in /etc/munin/plugins (or link it there using ln -s) # #%# family=contrib #%# capabilities=autoconf use strict; +use feature ':5.10'; use IO::Socket::INET; +use Munin::Plugin; # Config -our $address = $ENV{host} || "localhost"; # Default: localhost -our $port = $ENV{port} || 9051; # Default: 9051 +my $address = $ENV{host} || "localhost"; +my $port = $ENV{port} || 9051; # Don't edit below this line sub Authenticate { - my ($socket) = @_; - my $authline = "AUTHENTICATE"; - if (defined($ENV{cookiefile})) { - if (open(COOKIE, "<$ENV{cookiefile}")) { - binmode COOKIE; - my $cookie; - $authline .= " "; - while (read(COOKIE, $cookie, 32)) { - foreach my $byte (unpack "C*", $cookie) { - $authline .= sprintf "%02x", $byte; - } - } - close COOKIE; - } - } elsif (defined($ENV{password})) { - $authline .= ' "' . $ENV{password} . '"'; - } - print $socket "$authline\r\n"; - my $replyline = <$socket>; - if (substr($replyline, 0, 1) != '2') { - $replyline =~ s/\s*$//; - return "Failed to authenticate: $replyline"; - } + my ($socket) = @_; + my $authline = "AUTHENTICATE"; + if (defined($ENV{cookiefile})) { + if (open(COOKIE, "<$ENV{cookiefile}")) { + my $cookie; + binmode COOKIE; + read(COOKIE, $cookie, 32); + close COOKIE; + $authline .= ' "' . $cookie . '"'; + } + } elsif (defined($ENV{password})) { + $authline .= ' "' . $ENV{password} . '"'; + } + say $socket "$authline"; + my $replyline = <$socket>; + if (substr($replyline, 0, 1) != '2') { + $replyline =~ s/\s*$//; + return "Failed to authenticate: $replyline"; + } - return; + return; } if ($ARGV[0] and $ARGV[0] eq "autoconf") { - # Try to connect to the daemon - my $socket = IO::Socket::INET->new("$address:$port") - or my $failed = 1; + # Try to connect to the daemon + my $socket = IO::Socket::INET->new("$address:$port") or my $failed = 1; - if ($failed) { - print "no (failed to connect to $address port $port)\n"; - exit 1; - } + if ($failed) { + say "no (failed to connect to $address port $port)"; + exit 1; + } - my $msg = Authenticate($socket); - if (defined($msg)) { - print $socket "QUIT\r\n"; - close($socket); - print "no ($msg)\n"; - exit 1; - } + my $msg = Authenticate($socket); + if (defined($msg)) { + say $socket "QUIT"; + close($socket); + say "no ($msg)"; + exit 1; + } - print $socket "QUIT\r\n"; - close($socket); - print "yes\n"; - exit 0; + say $socket "QUIT"; + close($socket); + say "yes"; + exit 0; } if ($ARGV[0] and $ARGV[0] eq "config") { - print "graph_title Tor bandwidth usage (in/out)\n"; - print "graph_args --base 1000\n"; - print "graph_vlabel bytes/sec\n"; - print "graph_category Tor\n"; - print "graph_info This graph shows the flowing incoming/outgoing bytes on a Tor node\n"; - print "down.label Download\n"; - print "down.type DERIVE\n"; - print "down.min 0\n"; - print "up.label Upload\n"; - print "up.type DERIVE\n"; - print "up.min 0\n"; + say "graph_order down up"; + say "graph_title Tor traffic"; + say "graph_args --base 1000"; + say "graph_vlabel bits in (-) / out (+) per \${graph_period}"; + say "graph_category network"; + say "graph_info This graph shows the traffic through this Tor node."; + say "down.label received"; + say "down.type DERIVE"; + say 'down.graph no'; + say "down.cdef down,8,*"; + say "down.min 0"; + say "up.label b/s"; + say "up.type DERIVE"; + say "up.negative down"; + say "up.cdef up,8,*"; + say "up.min 0"; - exit 0; + exit 0; } my $socket = IO::Socket::INET->new("$address:$port") - or die("Couldn't connect to $address port $port: $!"); + or die("Couldn't connect to $address port $port: $!"); my $msg = Authenticate($socket); if (defined($msg)) { - print $socket "QUIT\r\n"; - close($socket); - die "$msg\n"; + say $socket "QUIT"; + close($socket); + die "$msg\n"; } -print $socket "GETINFO accounting/bytes\r\n"; +say $socket "GETINFO accounting/bytes"; my $down = 0; my $up = 0; my $replyline = <$socket>; chomp($replyline); -if ( $replyline =~ /^250-accounting\/bytes=(\d+)\s(\d+)\r$/ ) { - $down = $1; - $up = $2; +if ($replyline =~ /^250-accounting\/bytes=(\d+)\s(\d+)/) { + $down = $1; + $up = $2; } else { - die "Failed to get accounting info: $replyline\n"; + die "Failed to get accounting info: $replyline\n"; } -print $socket "QUIT\r\n"; +say $socket "QUIT"; close($socket); -print "down.value $down\n"; -print "up.value $up\n"; +say "down.value $down"; +say "up.value $up"; exit 0;