Commits (95)
image: ruby:2.3
# Test job template
.test_template: &test_definition
stage: test
......@@ -8,14 +6,31 @@ image: ruby:2.3
- bundle exec rake tests
- bundle exec rake spec
# Test with version present on Debian stable
test:puppet48:
# Test with version present on Debian Stretch
test:puppet4.8:
image: ruby:2.3
variables:
PUPPET_VERSION: "~> 4.8.2"
FACTER_VERSION: '~> 2.4.6'
HIERA_VERSION: '~> 3.2.0'
<<: *test_definition
# Test with latest Puppet release
test:puppetlatest:
# Test with version present on Debian Buster
test:puppet5.5:
image: ruby:2.5
variables:
PUPPET_VERSION: "~> 5.5.10"
FACTER_VERSION: '~> 3.11.0'
<<: *test_definition
# Build and deploy docs on GitLab Pages
pages:
image: debian:stable
stage: deploy
script:
- apt-get update && apt-get install -y puppet-strings puppet
- puppet strings generate
- mv doc public
artifacts:
paths:
- public
......@@ -2,259 +2,108 @@
#### Table of Contents
* [Overview](#overview)
* [Upgrade Notice](#upgrade-notice)
* [Dependencies](#dependencies)
* [Usage](#usage)
* [Installing tor](#installing-tor)
* [Configuring SOCKS](#configuring-socks)
* [Installing torsocks](#installing-torsocks)
* [Configuring relays](#configuring-relays)
* [Configuring the control](#configuring-control)
* [Configuring onion services](#configuring-onion-services)
* [Configuring directories](#configuring-directories)
* [Configuring exit policies](#configuring-exit-policies)
* [Configuring transport plugins](#configuring-transport-plugins)
* [Functions](#functions)
* [Polipo](#polipo)
* [Munin](#munin)
# Overview<a name="overview"></a>
This module tries to manage tor, making sure it is installed, running, has
munin graphs if desired and allows for configuration of relays, onion services,
exit policies, etc.
## Upgrade Notice<a name="upgrade-notice"></a>
* All of the `listen_address` variables have been deprecated, since they have
been deprecated in tor since 0.2.3.x-alpha. Please read the new tor man page
if you were using those variables.
* Previously, if you did not set the `$outbound_bindaddress` variable, it was
being automatically set to the `$listen_address variable`. Now this is not
being done and instead you will need to set the `$outbound_bindaddress`
explicitly for it to be set.
* The `tor::relay{}` variables `$bandwidth_rate` and `$bandwidth_burst` were
previously used for the tor configuration variables `RelayBandwidthRate` and
`RelayBandwidthBurst`, these have been renamed to `$relay_bandwidth_rate`
and `$relay_bandwidth_burst`. If you were using these, please rename your
variables in your configuration.
* The variables `$bandwidth_rate` and `$bandwidth_burst` are now used for the
tor configuration variables `BandwidthRate` and `BandwidthBurst`. If you
used `$bandwidth_rate` or `$bandwidth_burst` please be aware that these
values have changed and adjust your configuration as necessary.
* The `$tor_ensure_version` was converted to a parameter for the tor and
`tor::daemon` classes.
* The `$torsocks_ensure_version` was converted to a parameter for the
`tor::torsocks` class.
* The options that used to be settable with the `tor::daemon::global_opts`
define now are parameters for the `tor::daemon class`, and
`tor::daemon::global_opts` was removed accordingly.
# Dependencies<a name="dependencies"></a>
1. [Description](#description)
2. [Setup](#setup)
* [Setup requirements](#setup-requirements)
* [Getting started](#getting-started)
3. [Functions](#reference)
* [onion_address](#onion_address)
* [generate_onion_key](#generate_onion_key)
4. [Facts](#reference)
* [tor_hidden_services](#tor_hidden_services)
5. [Reference](#reference)
6. [Development](#development)
## Description
This module manages tor and is mainly geared towards people running it on
servers. With this module, you should be able to manage most, if not all of
the functionalities provided by tor, such as:
* relays
* bridges and exit nodes
* onion services
* exit policies
* transport plugins
## Setup
### Setup Requirements
This module needs:
* the [concat module](https://github.com/puppetlabs/puppetlabs-concat.git)
* the [stdlib module](https://github.com/puppetlabs/puppetlabs-stdlib.git)
* the [apt module](https://github.com/puppetlabs/puppetlabs-apt.git)
# Usage<a name="usage"></a>
Explicit dependencies can be found in the project's metadata.json file.
## Installing tor<a name="installing-tor"></a>
This module has been extensively re-written for the 2.0 version. Even though
most things should work as they did before, we urge you to read the new
documentation and treat this as a new module.
To install tor, simply include the 'tor' class in your manifests:
### Getting started
class { 'tor': }
`class { 'tor': }` will install tor with a default configuration. Chances are
you will want to configure Tor in a certain way. This is accomplished declaring
one or more of the `tor::daemon` defined types.
You can specify the `$version` class parameter to get a specific version installed.
For example, this will configure a tor bridge relay running on port 8080:
However, if you want to make configuration changes to your tor daemon, you will
want to instead include the `tor::daemon` class in your manifests, which will
inherit the `tor` class from above:
``` puppet
tor::daemon::relay {
'MyNickname':
bridge_relay => true,
port => 8080,
address => '1.1.1.1',
bandwidth_rate => 12500,
bandwidth_burst => 12500,
contact_info => 'Foo Bar <foo@bar.com>',
}
```
class { '::tor::daemon': }
# Functions
You have the following class parameters that you can specify:
This module comes with 2 functions specific to tor support. They require the
base32 gem to be installed on the master or wherever they are executed.
data_dir (default: '/var/lib/tor')
config_file (default: '/etc/tor/torrc')
use_bridges (default: 0)
automap_hosts_on_resolve (default: 0)
log_rules (default: ['notice file /var/log/tor/notices.log'])
The `data_dir` will be used for the tor user's `$HOME`, and the tor
`DataDirectory` value.
The `config_file` will be managed and the daemon restarted when it changed.
`use_bridges` and `automap_hosts_on_resolve` are used to set the `UseBridges`
and `AutomapHostsOnResolve` torrc settings.
The `log_rules` can be an array of different Log lines, each will be added to
the config, for example the following will use syslog:
class { '::tor::daemon':
log_rules => [ 'notice syslog' ],
}
If you want to set specific options for the tor class, you may pass them
directly to the tor::daemon in your manifests, e.g.:
class { '::tor::daemon':
use_munin => true,
automap_hosts_on_resolve => 1,
}
## Configuring SOCKS<a name="configuring-socks"></a>
To configure tor socks support, you can do the following:
tor::daemon::socks { "listen_locally":
port => 0,
policies => 'your super policy';
}
## Installing torsocks<a name="installing-torsocks"></a>
To install torsocks, simply include the `torsocks` class in your manifests:
class { 'tor::torsocks': }
You can specify the `$version` class parameter to get a specific version installed.
# Configuring relays<a name="configuring-relays"></a>
An example relay configuration:
tor::daemon::relay { "foobar":
port => '9001',
address => '192.168.0.1',
bandwidth_rate => '256',
bandwidth_burst => '256',
contact_info => "Foo <collective at example dot com>",
my_family => '<long family string here>';
}
You have the following options that can be passed to a relay, with the defaults
shown:
$port = 0,
$portforwarding = 0, # PortForwarding 0|1, set for opening ports at the router via UPnP.
# Requires 'tor-fw-helper' binary present.
$bandwidth_rate = '', # KB/s, defaulting to using tor's default: 5120KB/s
$bandwidth_burst = '', # KB/s, defaulting to using tor's default: 10240KB/s
$relay_bandwidth_rate = 0, # KB/s, 0 for no limit.
$relay_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
## Configuring the control<a name="configuring-control"></a>
To pass parameters to configure the `ControlPort` and the
`HashedControlPassword`, you would do something like this:
tor::daemon::control { "foo-control":
port => '80',
hashed_control_password => '<somehash>',
ensure => present;
}
Note: you must pass a hashed password to the control port, if you are going to
use it.
## Configuring onion services<a name="configuring-onion-services"></a>
To configure a tor onion service you can do something like the following:
tor::daemon::onion_service { "onion_ssh":
ports => 22;
}
The `HiddenServiceDir` is set to the `${data_dir}/${name}`, but you can override
it with the parameter `datadir`.
If you wish to enable v3-style onion services to correspond with the v2-style
onion services (the same configuration will be applied to both), you can pass
the parameter `v3 => true`. The default is `false`.
If you wish to enable single-hop onion addresses, you can enable them by
passing `single_hop => true`. The default is `false`.
Onion services used to be called hidden services, so an old interface
`tor::daemon::hidden_service` is still available, with the feature
set of that time.
## Configuring directories<a name="configuring-directories"></a>
An example directory configuration:
tor::daemon::directory { 'ssh_directory':
port => '80',
port_front_page => '/etc/tor/tor.html';
}
## Configuring exit policies<a name="configuring-exit-policies"></a>
To configure exit policies, you can do the following:
tor::daemon::exit_policy { "ssh_exit_policy":
accept => "192.168.0.1:22",
reject => "*:*";
}
## Configuring transport plugins<a name="configuring-transport-plugins"></a>
To configure transport plugins, you can do the following:
## onion_address
tor::daemon::transport_plugins { "obfs4":
ext_port => '80',
servertransport_plugin => 'obfs4 exec /usr/bin/obfs4proxy',
}
This function takes a 1024bit RSA private key as an argument and returns the
onion address for an onion service for that key.
If you wish to use `obfs4proxy`, you will also need to install the required
Debian package, as the puppet module will not do it for you.
At the moment, this function does not support v3 onions.
Other options for transport plugins are also available but not defined by
default:
## generate_onion_key
$servertransport_listenaddr #Set a different address for the transport plugin mechanism
$servertransport_options #Pass a k=v parameters to the transport proxy
This function takes a path (on the puppet master!) and an identifier for a key
and returns an array containing the matching onion address and the private key.
The private key either exists under the supplied `path/key_identifier` or is
being generated on the fly and stored under that path for the next execution.
# Functions<a name="functions"></a>
At the moment, this function does not support v3 onions.
This module comes with 2 functions specific to tor support. They require the base32 gem to be installed on the master or wherever they are executed.
# Facts
## onion_address
## tor_hidden_services
This function takes a 1024bit RSA private key as an argument and returns the onion address for an onion service for that key.
This fact gives you a list of the hidden services you are running.
## generate_onion_key
# Reference
This function takes a path (on the puppetmaster!) and an identifier for a key and returns an array containing the matching onion address and the private key. The private key either exists under the supplied `path/key_identifier` or is being generated on the fly and stored under that path for the next execution.
The full reference documentation for this module may be found at on
[GitLab Pages][pages].
# Polipo<a name="polipo"></a>
Alternatively, you may build yourself the documentation using the
`puppet strings generate` command. See the documentation for
[Puppet Strings][strings] for more information.
Polipo support can be enabled by doing:
[pages]: https://shared-puppet-modules-group.gitlab.io/tor
[strings]: https://puppet.com/blog/using-puppet-strings-generate-great-documentation-puppet-modules
include tor::polipo
## Development
This will inherit the `tor` class by default, remove `privoxy` if it's
installed, and install `polipo`, making sure it is running.
# Munin<a name="munin"></a>
This module's development is tracked on GitLab. Please submit issues and merge
requests on the [shared-puppet-modules-group/tor][smash] project page.
If you are using `munin`, and have the puppet munin module installed, you can
set the `use_munin` parameter to `true` when defining the `tor::daemon` class
to have graphs setup for you.
[smash]: https://gitlab.com/shared-puppet-modules-group/tor/
#!/usr/bin/perl -w
# https://lists.torproject.org/pipermail/tor-talk/2006-June/010486.html
use strict;
# Script to monitor the amount of FDs used by
# the Tor process (var/run/tor/tor.pid)
if ($ARGV[0] and $ARGV[0] =~ /^\s*config\s*$/i)
{
print "graph_title Open file descriptors for Tor\n";
print "graph_args --base 1000 -l 0\n";
print "graph_vlabel open FDs\n";
print "graph_category Tor\n";
print "count.label TorFDs\n";
exit 0;
}
my $pidfile = "/var/run/tor/tor.pid";
my $pid = '';
if (-e $pidfile) {
open (PID, $pidfile) or exit 1;
$pid = <PID>;
close PID;
} else {
$pid = `pidof tor`;
}
chomp $pid;
$pid =~ /^[0-9]+$/ or exit 1;
opendir (FDS, "/proc/$pid/fd") or exit 1;
my @fds = readdir(FDS);
closedir FDS;
my $count = scalar @fds - 2;
print "count.value $count\n";
#!/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
#!/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
# Polipo Configuration from https://svn.torproject.org/svn/torbrowser/trunk/build-scripts/config/polipo.conf
# Managed by puppet.
### Basic configuration
### *******************
# Uncomment one of these if you want to allow remote clients to
# connect:
# proxyAddress = "::0" # both IPv4 and IPv6
# proxyAddress = "0.0.0.0" # IPv4 only
proxyAddress = "127.0.0.1"
proxyPort = 8118
# If you do that, you'll want to restrict the set of hosts allowed to
# connect:
# allowedClients = "127.0.0.1, 134.157.168.57"
# allowedClients = "127.0.0.1, 134.157.168.0/24"
allowedClients = 127.0.0.1
allowedPorts = 1-65535
# Uncomment this if you want your Polipo to identify itself by
# something else than the host name:
proxyName = "localhost"
# Uncomment this if there's only one user using this instance of Polipo:
cacheIsShared = false
# Uncomment this if you want to use a parent proxy:
# parentProxy = "squid.example.org:3128"
# Uncomment this if you want to use a parent SOCKS proxy:
socksParentProxy = "localhost:9050"
socksProxyType = socks5
### Memory
### ******
# Uncomment this if you want Polipo to use a ridiculously small amount
# of memory (a hundred C-64 worth or so):
# chunkHighMark = 819200
# objectHighMark = 128
# Uncomment this if you've got plenty of memory:
# chunkHighMark = 50331648
# objectHighMark = 16384
chunkHighMark = 67108864
### On-disk data
### ************
# Uncomment this if you want to disable the on-disk cache:
diskCacheRoot = ""
# Uncomment this if you want to put the on-disk cache in a
# non-standard location:
# diskCacheRoot = "~/.polipo-cache/"
# Uncomment this if you want to disable the local web server:
localDocumentRoot = ""
# Uncomment this if you want to enable the pages under /polipo/index?
# and /polipo/servers?. This is a serious privacy leak if your proxy
# is shared.
# disableIndexing = false
# disableServersList = false
disableLocalInterface = true
disableConfiguration = true
### Domain Name System
### ******************
# Uncomment this if you want to contact IPv4 hosts only (and make DNS
# queries somewhat faster):
#
# dnsQueryIPv6 = no
# Uncomment this if you want Polipo to prefer IPv4 to IPv6 for
# double-stack hosts:
#
# dnsQueryIPv6 = reluctantly
# Uncomment this to disable Polipo's DNS resolver and use the system's
# default resolver instead. If you do that, Polipo will freeze during
# every DNS query:
dnsUseGethostbyname = yes
### HTTP
### ****
# Uncomment this if you want to enable detection of proxy loops.
# This will cause your hostname (or whatever you put into proxyName
# above) to be included in every request:
disableVia = true
# Uncomment this if you want to slightly reduce the amount of
# information that you leak about yourself:
# censoredHeaders = from, accept-language
# censorReferer = maybe
censoredHeaders = from,accept-language,x-pad,link
censorReferer = maybe
# Uncomment this if you're paranoid. This will break a lot of sites,
# though:
# censoredHeaders = set-cookie, cookie, cookie2, from, accept-language
# censorReferer = true
# Uncomment this if you want to use Poor Man's Multiplexing; increase
# the sizes if you're on a fast line. They should each amount to a few
# seconds' worth of transfer; if pmmSize is small, you'll want
# pmmFirstSize to be larger.
# Note that PMM is somewhat unreliable.
# pmmFirstSize = 16384
# pmmSize = 8192
# Uncomment this if your user-agent does something reasonable with
# Warning headers (most don't):
# relaxTransparency = maybe
# Uncomment this if you never want to revalidate instances for which
# data is available (this is not a good idea):
# relaxTransparency = yes
# Uncomment this if you have no network:
# proxyOffline = yes
# Uncomment this if you want to avoid revalidating instances with a
# Vary header (this is not a good idea):
# mindlesslyCacheVary = true
# Suggestions from Incognito configuration
maxConnectionAge = 5m
maxConnectionRequests = 120
serverMaxSlots = 8
serverSlots = 2
tunnelAllowedPorts = 1-65535
# manage tor-arm
class tor::arm (
$version = 'installed'
){
include ::tor
package{'tor-arm':
ensure => $version,
}
}
# basic management of resources for tor
class tor::base {
package {'tor':
ensure => $tor::version,
}
if $facts['osfamily'] == 'Debian' {
package {'tor-geoipdb':
ensure => $tor::version,
before => Service['tor'],
}
}
service { 'tor':
ensure => running,
enable => true,
hasrestart => true,
hasstatus => true,
require => Package['tor'],
}
}
# manage a complete tor
# installation with all the basics
class tor::compact {
include ::tor
include tor::torsocks
if $facts['osfamily'] == 'Debian' {
include tor::polipo
}
}
# manage a snippet based tor installation
class tor::daemon (
$use_munin = false,
$data_dir = '/var/lib/tor',
$config_file = '/etc/tor/torrc',
$use_bridges = 0,
$automap_hosts_on_resolve = 0,
$log_rules = [ 'notice file /var/log/tor/notices.log' ],
$safe_logging = 1,
) {
include ::tor
include ::tor::daemon::base
if $use_munin {
include ::tor::munin
}
}
# extend basic tor things with a snippet based daemon configuration
class tor::daemon::base inherits tor::base {
include ::tor::daemon::params
# @summary Extend basic Tor configuration with a snippet based configuration.
# Base module.
#
# @param user
# Unix user for the tor process.
#
# @param group
# Unix group for the tor process.
#
# @param manage_user
# If Puppet should manage the tor process unix user and group
#
# @param data_dir_mode
# Unix mode for the tor data directory.
#
class tor::daemon::base (
String $user = $tor::daemon::params::user,
String $group = $tor::daemon::params::group,
Boolean $manage_user = $tor::daemon::params::manage_user,
Stdlib::Filemode $data_dir_mode = $tor::daemon::params::data_dir_mode
) inherits tor::daemon::params {
if $tor::daemon::params::manage_user {
group { $tor::daemon::params::group:
......@@ -13,7 +30,7 @@ class tor::daemon::base inherits tor::base {
ensure => present,
allowdupe => false,
comment => 'tor user,,,',
home => $tor::daemon::data_dir,
home => $tor::data_dir,
shell => '/bin/false',
gid => $tor::daemon::params::group,
require => Group[$tor::daemon::params::group],
......@@ -21,7 +38,7 @@ class tor::daemon::base inherits tor::base {
}
# directories
file { $tor::daemon::data_dir:
file { $tor::data_dir:
ensure => directory,
mode => $tor::daemon::params::data_dir_mode,
owner => $tor::daemon::params::user,
......@@ -38,7 +55,7 @@ class tor::daemon::base inherits tor::base {
}
# tor configuration file
concat { $tor::daemon::config_file:
concat { $tor::config_file:
mode => '0640',
owner => 'root',
group => $tor::daemon::params::group,
......@@ -48,15 +65,21 @@ class tor::daemon::base inherits tor::base {
# config file headers
concat::fragment { '00.header':
content => template('tor/torrc.header.erb'),
content => epp('tor/torrc/00_header.epp'),
order => '00',
target => $tor::daemon::config_file,
target => $tor::config_file,
}
# global configurations
concat::fragment { '01.global':
content => template('tor/torrc.global.erb'),
content => epp('tor/torrc/01_global.epp', {
'automap_hosts_on_resolve' => $tor::automap_hosts_on_resolve,
'data_dir' => $tor::data_dir,
'log_rules' => $tor::log_rules,
'safe_logging' => $tor::safe_logging,
'use_bridges' => $tor::use_bridges,
}),
order => '01',
target => $tor::daemon::config_file,
target => $tor::config_file,
}
}
# Bridge definition
# @summary Extend basic Tor configuration with a snippet based configuration.
# Use a Tor Bridge to connect to Tor.
#
# @param ensure
# Whether this module should be used or not.
#
# @param ip
# The IP address of the bridge that will be used.
#
# @param port
# The IP port of the bridge that will be used.
#
# @param fingerprint
# Fingerprint of the Tor Bridge to verify that the relay running at that
# location has the right fingerprint.
#
# @param transport
# What pluggable transport’s proxy to use to transfer data to the bridge.
#
define tor::daemon::bridge(
$ip,
$port,
$fingerprint = false,
$ensure = 'present',
Enum['present', 'absent'] $ensure = 'present',
Optional[Stdlib::IP::Address] $ip = undef,
Optional[Stdlib::Port] $port = undef,
Optional[String] $fingerprint = undef ,
Optional[String] $transport = undef ,
) {
unless $ip or $port {
fail('You need to specify an IP address ($tor::daemon::bridge::ip) AND a port number ($tor::daemon::bridge::port)')
}
if $ensure == 'present' {
concat::fragment { "10.bridge.${name}":
content => template('tor/torrc.bridge.erb'),
order => '10',
target => $tor::daemon::config_file,
concat::fragment { "11.bridge.${name}":
content => epp('tor/torrc/11_bridge.epp', {
'name' => $name,
'ip' => $ip,
'port' => $port,
'fingerprint' => $fingerprint,
'transport' => $transport,
}),
order => '11',
target => $tor::config_file,
}
}
}
......
# control definition
# @summary Extend basic Tor configuration with a snippet based configuration.
# Tor Control module.
#
# @example Use port 80 as the Tor Control port and authenticate to it using
# a hashed password.
# tor::daemon::control { 'foo-control':
# port => 80,
# hashed_control_password => '<somehash>',
# ensure => present;
# }
#
# @param ensure
# Whether this module should be used or not.
#
# @param port
# The Tor Control port to manage your Tor instance remotely.
#
# @param cookie_authentication
# Whether Cookie Authentication to the Tor Control port should be allowed.
#
# @param cookie_auth_file
# Path to the Cookie Authentication file for the Tor Control port.
#
# @param cookie_auth_file_group_readable
# Whether to allow the unix group running the tor process to read the cookie
# file.
#
# @param hashed_control_password
# Hashed password to authenticate to the Tor Control port.
#
define tor::daemon::control(
$ensure = 'present',
$port = 0,
$hashed_control_password = '',
$cookie_authentication = 0,
$cookie_auth_file = '',
$cookie_auth_file_group_readable = '',
Enum['present', 'absent'] $ensure = 'present',
Optional[Stdlib::Port] $port = undef,
Boolean $cookie_authentication = false,
Optional[Stdlib::Unixpath] $cookie_auth_file = undef,
Boolean $cookie_auth_file_group_readable = false,
Optional[String] $hashed_control_password = undef,
) {
if $ensure == 'present' {
if $cookie_authentication == '0' and $hashed_control_password == '' {
if $cookie_authentication == false and $hashed_control_password == undef {
fail('You need to define the tor control password')
}
if $cookie_authentication == 0 and ($cookie_auth_file != '' or $cookie_auth_file_group_readable != '') { # lint:ignore:80chars
if !$cookie_authentication and ($cookie_auth_file or $cookie_auth_file_group_readable) { # lint:ignore:80chars
notice('You set a tor cookie authentication option, but do not have cookie_authentication on') # lint:ignore:80chars
}
concat::fragment { '04.control':
content => template('tor/torrc.control.erb'),
content => epp('tor/torrc/04_control.epp', {
'port' => $port,
'cookie_authentication' => $cookie_authentication,
'cookie_auth_file' => $cookie_auth_file,
'cookie_auth_file_group_readable' => $cookie_auth_file_group_readable,
'hashed_control_password' => $hashed_control_password,
}),
order => '04',
target => $tor::daemon::config_file,
target => $tor::config_file,
}
}
}