summaryrefslogtreecommitdiff
path: root/files/munin/tor_connections
blob: c1d0a92894a1eddb605e46d269325a85dcc82b31 (plain)
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
#!/usr/bin/perl -w
#
# Munin plugin to monitor Tor
#
# Author: Ge van Geldorp <ge@gse.nl>
#
# Parameters understood:
#
# 	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)
#	cookiefile - Name of the file containing the control channel cookie
#	             (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.
#
# Usage: place in /etc/munin/node.d/ (or link it there using ln -s)
#
# Parameters understood:
# 	config   (required)
# 	autoconf (optional - used by munin-config)
#
#
# Magic markers - optional - used by installation scripts and
# munin-config:
#
#%# family=contrib
#%# capabilities=autoconf

use strict;
use IO::Socket::INET;

# Config
our $address = $ENV{host}  || "localhost";	# Default: localhost
our $port    = $ENV{port}  || 9051;		# Default: 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";
	}

	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;

	if ($failed) {
		print "no (failed to connect to $address port $port)\n";
		exit 1;
	}

	my $msg = Authenticate($socket);
	if (defined($msg)) {
		print $socket "QUIT\r\n";
		close($socket);
		print "no ($msg)\n";
		exit 1;
	}

	print $socket "QUIT\r\n";
	close($socket);
	print "yes\n";
	exit 0;
}

my %connections = ("new",       0,
                   "launched",  0,
                   "connected", 0,
                   "failed",    0,
                   "closed",    0);

if ($ARGV[0] and $ARGV[0] eq "config") {
	print "graph_title Connections\n";
	print "graph_args -l 0 --base 1000\n";
	print "graph_vlabel connections\n";
	print "graph_category Tor\n";
	print "graph_period second\n";
	print "graph_info This graph shows the number of Tor OR connections.\n";

	foreach my $status (keys %connections) {
		print "$status.label $status\n";
		print "$status.type GAUGE\n";
		print "$status.max 50000\n";
		print "$status.min 0\n";
	}
	
        exit 0;
}

my $socket = IO::Socket::INET->new("$address:$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";
}

print $socket "GETINFO orconn-status\r\n";
my $replyline = <$socket>;
if (substr($replyline, 0, 1) != '2') {
	print $socket "QUIT\r\n";
	close($socket);
	$replyline =~ s/\s*$//;
	die "Failed to get orconn-status info: $replyline\n";
}

while (! (($replyline = <$socket>) =~ /^\.\s*$/)) {
	my @reply = split(/\s+/, $replyline);
	$connections{lc($reply[1])}++;
}
$replyline = <$socket>;
if (substr($replyline, 0, 1) != '2') {
	print $socket "QUIT\r\n";
	close($socket);
	$replyline =~ s/\s*$//;
	die "Failed to authenticate: $replyline\n";
}

print $socket "QUIT\r\n";
close($socket);

while (my ($status, $count) = each(%connections)) {
	print "$status.value $count\n";
}

exit 0;

# vim:syntax=perl