aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xfiles/munin/tor_connections162
-rwxr-xr-xfiles/munin/tor_routers151
-rwxr-xr-xfiles/munin/tor_traffic154
-rw-r--r--manifests/daemon.pp24
-rw-r--r--manifests/init.pp9
-rw-r--r--templates/torrc.exit_policy.erb3
-rw-r--r--templates/torrc.relay.erb3
7 files changed, 493 insertions, 13 deletions
diff --git a/files/munin/tor_connections b/files/munin/tor_connections
new file mode 100755
index 0000000..c1d0a92
--- /dev/null
+++ b/files/munin/tor_connections
@@ -0,0 +1,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
diff --git a/files/munin/tor_routers b/files/munin/tor_routers
new file mode 100755
index 0000000..b977f9a
--- /dev/null
+++ b/files/munin/tor_routers
@@ -0,0 +1,151 @@
+#!/usr/bin/perl -w
+#
+# Munin plugin to monitor Tor routers
+#
+# Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>, based on a plugin by 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;
+}
+
+if ($ARGV[0] and $ARGV[0] eq "config") {
+ print "graph_title Routers\n";
+ print "graph_args -l 0\n";
+ print "graph_vlabel routers\n";
+ print "graph_category Tor\n";
+ print "graph_info This graph shows the number of known Tor ORs.\n";
+
+ print "ors.label routers\n";
+ print "ors.type GAUGE\n";
+ print "ors.info The number of known Tor ORs (onion routers)\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 ns/all\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";
+}
+
+my $count;
+while (! (($replyline = <$socket>) =~ /^\.\s*$/)) {
+ my @reply = split(/\s+/, $replyline);
+ $count++ if $reply[0] eq 'r';
+}
+$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);
+
+print "ors.value $count\n";
+
+exit 0;
+
+# vim:syntax=perl
diff --git a/files/munin/tor_traffic b/files/munin/tor_traffic
new file mode 100755
index 0000000..a72e7d7
--- /dev/null
+++ b/files/munin/tor_traffic
@@ -0,0 +1,154 @@
+#!/usr/bin/perl -w
+#
+# Munin plugin to monitor Tor traffic
+#
+# 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;
+}
+
+if ($ARGV[0] and $ARGV[0] eq "config") {
+ print "graph_title Traffic\n";
+ print "graph_vlabel bytes per \${graph_period} read (-) / written (+)\n";
+ print "graph_category Tor\n";
+ print "graph_info This graph shows the bandwidth used by Tor.\n";
+
+ print "read.label byte/s\n";
+ print "read.type GAUGE\n";
+ print "read.graph no\n";
+ print "read.max 10000000\n";
+ print "write.label byte/s\n";
+ print "write.type GAUGE\n";
+ print "write.negative read\n";
+ print "write.max 10000000\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 "SETEVENTS bw\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";
+}
+
+$replyline = <$socket>;
+if (substr($replyline, 0, 1) != '6') {
+ print $socket "QUIT\r\n";
+ close($socket);
+ $replyline =~ s/\s*$//;
+ die "Failed to get bw: $replyline\n";
+}
+my @reply = split(/\s+/, $replyline);
+
+print $socket "SETEVENTS\r\n";
+$replyline = <$socket>;
+print $socket "QUIT\r\n";
+close($socket);
+
+print "read.value $reply[2]\n";
+print "write.value $reply[3]\n";
+
+exit 0;
+
+# vim:syntax=perl
diff --git a/manifests/daemon.pp b/manifests/daemon.pp
index 5f4e064..6d8c315 100644
--- a/manifests/daemon.pp
+++ b/manifests/daemon.pp
@@ -98,17 +98,18 @@ class tor::daemon inherits tor {
}
# relay definition
- define relay( $port = 0,
- $listen_addresses = [],
- $bandwidth_rate = 0, # KB/s, 0 for no limit.
- $bandwidth_burst = 0, # KB/s, 0 for no limit.
- $accounting_max = 0, # GB, 0 for no limit.
- $accounting_start = [],
- $contact_info = '',
- $my_family = '', # TODO: autofill with other relays
- $address = "tor.${domain}",
- $bridge_relay = 0,
- $ensure = present ) {
+ define relay( $port = 0,
+ $listen_addresses = [],
+ $outbound_bindaddresses = $listen_addresses,
+ $bandwidth_rate = 0, # KB/s, 0 for no limit.
+ $bandwidth_burst = 0, # KB/s, 0 for no limit.
+ $accounting_max = 0, # GB, 0 for no limit.
+ $accounting_start = [],
+ $contact_info = '',
+ $my_family = '', # TODO: autofill with other relays
+ $address = "tor.${domain}",
+ $bridge_relay = 0,
+ $ensure = present ) {
$nickname = $name
concatenated_file_part { '03.relay':
@@ -173,6 +174,7 @@ class tor::daemon inherits tor {
# exit policies
define exit_policy( $accept = [],
$reject = [],
+ $reject_private = 1,
$ensure = present ) {
concatenated_file_part { "07.exit_policy.${name}":
diff --git a/manifests/init.pp b/manifests/init.pp
index a998d48..0c38073 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -1,11 +1,16 @@
class tor {
if !$tor_ensure_version { $tor_ensure_version = 'installed' }
-
- package { [ "tor", "tor-geoip", "torsocks" ]:
+ if !$torsocks_ensure_version { $torsocks_ensure_version = 'installed'}
+
+ package { [ "tor", "tor-geoipdb" ]:
ensure => $tor_ensure_version,
}
+ package { "torsocks":
+ ensure => $torsocks_ensure_version,
+ }
+
service { 'tor':
ensure => running,
enable => true,
diff --git a/templates/torrc.exit_policy.erb b/templates/torrc.exit_policy.erb
index 4732ad6..92367c2 100644
--- a/templates/torrc.exit_policy.erb
+++ b/templates/torrc.exit_policy.erb
@@ -1,4 +1,7 @@
# exit policies: <%= name %>
+<%- if reject_private != 1 then -%>
+ExitPolicyRejectPrivate <%= reject_private %>
+<%- end -%>
<%- for policy in accept -%>
ExitPolicy accept <%= policy %>
<%- end -%>
diff --git a/templates/torrc.relay.erb b/templates/torrc.relay.erb
index 4754859..2ab34bf 100644
--- a/templates/torrc.relay.erb
+++ b/templates/torrc.relay.erb
@@ -4,6 +4,9 @@ ORPort <%= port %>
<%- for listen_address in listen_addresses -%>
ORListenAddress <%= listen_address %>
<%- end -%>
+<%- for outbound_bindaddress in outbound_bindaddresses -%>
+OutboundBindAddress <%= outbound_bindaddress %>
+<%- end -%>
<%- if nickname != '' then -%>
Nickname <%= nickname %>
<%- end -%>