[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-relays] new ansible-tor features: automatic instance configuration + automatic MyFamily generation (PATCH)



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Hi David,

thanks for creating ansible-tor. I added two features that are crucial
to me and maybe useful for others as well. If you like it, feel free
to merge - this is my first ansible experience and it is lightly tested.

Example:
lets say you have added a new server to your inventory. The server has
3 public IP addresses (1.1.1.1, 2.2.2.2, 3.3.3.3). After running
ansible-tor with the new changes you will have the following 6 tor
instances/ORPorts running (without manually specifying IP addresses
first):

1.1.1.1:80
1.1.1.1:443
2.2.2.2:80
2.2.2.2:443
3.3.3.3:80
3.3.3.3:443

including MyFamily configuration across all servers/instances.

regards,
Nusenu

changes
=======

- - auto instance deployment without manual IP/ORPort configuration (new)
	starts 2 tor instances per available IP address by default
	makes manually specifying IP addresses and ORPorts via
	proc_instances obsolete
	ORPorts default to 80 and 443 (DirPort not added yet)	
	replace "single.yml" + "instances.yml" -> instance.yml only
	(handles both cases dynamically)
	
- - MyFamily autogeneration (new)
	Keeping all relay fingerprints in sync is probably one
	of the most annoying tasks for a relay operator
	managing multiple relays, now ansible takes care of this
	(all relays need to be in the 'relays' group)	

- - directory structure (changed)
	defaults:
	configs -> /etc/tor/<ip>_<orport>.torrc
	log dir -> /var/log/tor/<ip>_<orport>.log
	datadir -> /var/lib/tor/<ip>_<orport>/
	pid dir -> /var/run/tor/<ip>_<orport>.pid

	(previously everything was located in /etc)

- - added torrc sanity check (tor --verify-config ) (new)

- - torrc files are owned by root (previously owned by $tor_user)

- - the pid file check has been removed since the file is not required
to exist
(it will be created when tor starts)


open
- -----
- - it does not take care of instance removals yet
(in case IPs are no longer available or amount of ORPorts have been
reduced)
- - allow opt-out -> only 1 tor instance per host
(even if there are more IPs available)
- - DirPort support
- - detect RFC1918 IPs (opt-in)
-----BEGIN PGP SIGNATURE-----

iQIcBAEBCgAGBQJU4i+CAAoJEFv7XvVCELh0y+kP/i4Mn/XClgXYloGdgWU9UPR+
Y8yZv97FvJOMPI40tccPKcNPcLQFRvGFYkR96sAOGoMfbJT/tQeH2dOxwAEF31mv
afFkLsVPAOpNzlyO2qP1mkLtB/aYXtZ6jb2+JtpAhVBLKOVFBN2nNRiwdgFYZFGy
f0ZIp7xyR9XcAhXo4nc0hlETREAnbMOgFGM6vqqIpJfimF3liE6va5HNw2CD+7Zd
MmeIOuVNvQh09SiYf48AJpBeBRoybOvmFIPphtXEYlC/y6cd/IyUIYdOBuaLa5td
vQnrQOC7TUgp74uarl0yaatOYOEagl0lrNeN6+Vgy5e0e12TgVccWW5ZosM1PBXG
VH2FTfjHXUO+VN0p4xn6AS0dhWTRKb7isj3jpznTMsiq0AcvXM6DZjkzkcCPChVz
jptdUbNvgpdP7j5X11iZniGpxVe7aFo2wCzgZORY1xMysiigJsL4M/nonr4YO4G9
w7kyNcco9gStklJSvOJXbfX4HrOCuWdq8hp4xubyON+5jpEUgMmG1o/v5NJANV4C
CLzlz4kf9l9o351Z7DJQzilxzDEwe6oZwSWnsq+yB65Mgj5sUJnchi40iPLOHSUr
DaVSSUxoZ8VVNYqqvGYb2fysYa7DsCgofsF/eXP4QyJp1WFNwc0ft6qIhyAGIDwx
RfwQHrA+Lg95mdXDyr0B
=QHkD
-----END PGP SIGNATURE-----
diff --git a/defaults/main.yml b/defaults/main.yml
index ca5ad28..5f1f92c 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -1,14 +1,32 @@
 ---
 
-tor_instance_parent_dir: /etc/tor/instances
 tor_user: debian-tor
-tor_DataDirectory: /var/lib/tor
-tor_PidFile: /var/run/tor/tor.pid
+tor_ConfDir: /etc/tor
+
+# Attention: we will run chown tor_user on these folders
+tor_PidDir: /var/run/tor
+tor_LogDir: /var/log/tor
+tor_DataDir: /var/lib/tor
+
+tor_LogLevel: notice
 tor_RunAsDaemon: 1
-tor_Log: "notice file /var/log/tor/log"
 tor_hidden_services_parent_dir: /var/lib/tor/services
 tor_wait_for_hidden_services: no
 
+# The tor_ORPort array defines how many instances are created per
+# available IP address. It does not make sense to specify
+# more than two ports. If you want only one instance per IP use
+# tor_ORPorts: 443
+tor_ORPorts: [ 80, 443 ]
+
+#XXX: not implemented yet
+# the number of ORPorts and DirPorts must match
+#tor_DirPorts: [ '8080', '8888' ]
+
+tor_SocksPort: 0
+
+tor_ExitPolicy: "reject *:*"
+
 tor_obfs4proxy_enabled: False
 tor_obfs4proxy_release: sid
 debian_repo: http://ftp.us.debian.org/debian/
diff --git a/tasks/configure_tor_instance.yml b/tasks/configure_tor_instance.yml
index 5a12672..b2fbc0e 100644
--- a/tasks/configure_tor_instance.yml
+++ b/tasks/configure_tor_instance.yml
@@ -1,47 +1,89 @@
 ---
 
-- name: ensure tor instance parent dir exists
+- name: ensure tor DataDir(s) exist
   file: >
-    path={{ tor_instance_parent_dir }}
+    path={{ tor_DataDir }}/{{ item[0] }}_{{ item[1] }}
     state=directory
     owner={{ tor_user }}
+    mode=0700
+  with_nested:
+   - "{{ ansible_all_ipv4_addresses }}"
+   - tor_ORPorts
 
-- name: ensure tor instances data dir exist
+- name: ensure tor log file(s) are not world readable
   file: >
-    path="{{ tor_instance_parent_dir }}/{{ item.name }}/data"
-    state=directory
-    owner={{ tor_user }}
-  with_items: proc_instances
-
-- name: ensure tor instances log file exist
-  file: >
-    path="{{ tor_instance_parent_dir }}/{{ item.name }}/log"
+    path="{{ tor_LogDir }}/{{ item[0] }}_{{ item[1] }}.log"
     state=touch
     owner={{ tor_user }}
-  with_items: proc_instances
+    mode=600
+  with_nested:
+   - "{{ ansible_all_ipv4_addresses }}"
+   - tor_ORPorts
 
-- name: ensure tor instances pid file exist
+- name: ensure tor pidDir is owned by tor_user
   file: >
-    path="{{ tor_instance_parent_dir }}/{{ item.name }}/tor.pid"
-    state=touch
+    path={{ tor_PidDir }}
+    state=directory
     owner={{ tor_user }}
-  with_items: proc_instances
+    mode=2750
 
-- name: ensure instances template torrc
+- name: generating torrc file(s)...
   template: >
     src=torrc
-    dest="{{ tor_instance_parent_dir }}/{{ item.name }}/torrc"
-    owner={{ tor_user }}
+    dest="{{ tor_ConfDir }}/{{ item[0] }}_{{ item[1] }}.torrc"
+    owner=root
     mode=0644
-  with_items: proc_instances
-  register: instances_status
+  with_nested:
+   - "{{ ansible_all_ipv4_addresses }}"
+   - tor_ORPorts
+  register: instances
 
-- name: "ensure tor instances are reloaded if its torrc changed"
-  shell: "kill -HUP `cat {{ tor_instance_parent_dir }}/{{ item.item.name }}/tor.pid`"
+- name: ensure torrc files are sane
+  shell: "tor --verify-config -f {{ tor_ConfDir }}/{{ item[0] }}_{{ item[1] }}.torrc"
+  with_nested:
+   - "{{ ansible_all_ipv4_addresses }}"
+   - tor_ORPorts
+
+- name: ensure tor instances are reloaded if its torrc changed
+  shell: "kill -HUP `cat {{ tor_PidDir }}/{{ item.item[0] }}_{{ item.item[1] }}.pid`"
   ignore_errors: yes
-  with_items: instances_status.results
+  with_items: instances.results
   when: item.changed == True
 
 - name: ensure tor instances are running
-  shell: "kill -0 `cat {{ tor_instance_parent_dir }}/{{ item.name }}/tor.pid` || tor -f {{ tor_instance_parent_dir }}/{{ item.name }}/torrc"
-  with_items: proc_instances
+  shell: "kill -0 `cat {{ tor_PidDir }}/{{ item[0] }}_{{ item[1] }}.pid` || tor -f {{ tor_ConfDir }}/{{ item[0] }}_{{ item[1] }}.torrc"
+  with_nested:
+   - "{{ ansible_all_ipv4_addresses }}"
+   - tor_ORPorts
+
+# each tor instance has been started at least once
+# now we can collect tor fingerprints
+- name: gather relay fingerprints (for MyFamily)
+  shell: "cut -d' ' -f2 {{ tor_DataDir }}/{{ item[0] }}_{{ item[1] }}/fingerprint"
+  with_nested:
+   - "{{ ansible_all_ipv4_addresses }}"
+   - tor_ORPorts
+  register: tor_fingerprints
+
+- name: generating torrc file(s) - this time with MyFamily...
+  template: >
+    src=torrc
+    dest="{{ tor_ConfDir }}/{{ item[0] }}_{{ item[1] }}.torrc"
+    owner=root
+    mode=0644
+  with_nested:
+   - "{{ ansible_all_ipv4_addresses }}"
+   - tor_ORPorts
+  register: instances
+
+- name: ensure torrc files are still sane (after adding MyFamily)
+  shell: "tor --verify-config -f {{ tor_ConfDir }}/{{ item[0] }}_{{ item[1] }}.torrc"
+  with_nested:
+   - "{{ ansible_all_ipv4_addresses }}"
+   - tor_ORPorts
+
+- name: ensure tor instances are reloaded if its torrc changed
+  shell: "kill -HUP `cat {{ tor_PidDir }}/{{ item.item[0] }}_{{ item.item[1] }}.pid`"
+  ignore_errors: yes
+  with_items: instances.results
+  when: item.changed == True
diff --git a/tasks/main.yml b/tasks/main.yml
index 54aceb1..e639115 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -20,11 +20,7 @@
 - include: hidden_services.yml
   when: tor_hidden_services is defined
 
-- include: configure_apt_single.yml
-  when: proc_instances is not defined
-
 - include: configure_tor_instance.yml
-  when: proc_instances is defined
 
 ## wait for hidden services
 - include: wait_for_hidden_services.yml
diff --git a/templates/torrc b/templates/torrc
index a5cdca3..10fa10f 100644
--- a/templates/torrc
+++ b/templates/torrc
@@ -1,31 +1,32 @@
 # ansible generated torrc
-{% if proc_instances is defined and item is defined %}
-RunAsDaemon 1
-User {{ tor_user }}
-PidFile {{ tor_instance_parent_dir }}/{{ item.name }}/tor.pid
-Log warn file {{ tor_instance_parent_dir }}/{{ item.name }}/log
-DataDirectory {{ tor_instance_parent_dir }}/{{ item.name }}/data
-{% else %}
-DataDirectory {{ tor_DataDirectory }}
-PidFile {{ tor_PidFile }}
 RunAsDaemon {{ tor_RunAsDaemon }}
-Log {{ tor_Log }}
-{% endif %}
-{% if tor_Syslog is defined %}
-Log {{ tor_Syslog }} syslog
+User {{ tor_user }}
+
+PidFile {{ tor_PidDir }}/{{ item[0] }}_{{ item[1] }}.pid
+Log {{ tor_LogLevel }} file {{ tor_LogDir }}/{{ item[0] }}_{{ item[1] }}.log
+DataDirectory {{ tor_DataDir }}/{{ item[0] }}_{{ item[1] }}
+
+Address {{ item[0] }}
+ORPort {{ item[1] }}
+ORListenAddress {{ item[0] }}
+OutboundBindAddress {{ item[0] }}
+SocksPort {{ tor_SocksPort }}
+
+{% if tor_ContactInfo is defined %}
+ContactInfo {{ tor_ContactInfo }}
 {% endif %}
 {% if tor_Nickname is defined %}
 Nickname {{ tor_Nickname }}
 {% endif %}
-{% if tor_ContactInfo is defined %}
-ContactInfo {{ tor_ContactInfo }}
-{% endif %}
-{% if tor_ExitPolicy is defined %}
+
 ExitPolicy {{ tor_ExitPolicy }}
+
+{% if tor_fingerprints is defined %}
+MyFamily {% for host in groups['relays'] %}{% for item in hostvars[host]['tor_fingerprints']['results'] -%}${{ item.stdout }},{%- endfor %}{% endfor %}
 {% endif %}
-{% if tor_ORPort is defined %}
-ORPort {{ tor_ORPort }}
-{% endif %}
+
+
+
 {% if tor_ExtORPort is defined %}
 ExtORPort {{ tor_ExtORPort }}
 {% endif %}
@@ -47,18 +48,12 @@ ServerTransportPlugin {{ tor_ServerTransportPlugin }}
 {% if tor_ServerTransportOptions is defined %}
 ServerTransportOptions {{ tor_ServerTransportOptions }}
 {% endif %}
-{% if tor_MyFamily is defined %}
-MyFamily {{ tor_MyFamily }}
-{% endif %}
 {% if tor_ReachableAddresses is defined %}
 ReachableAddresses {{ tor_ReachableAddresses }}
 {% endif %}
 {% if tor_SafeLogging is defined %}
 SafeLogging {{ tor_SafeLogging }}
 {% endif %}
-{% if tor_SocksPort is defined %}
-SocksPort {{ tor_SocksPort }}
-{% endif %}
 {% if tor_hidden_services is defined %}
 {% for service in tor_hidden_services %}
 HiddenServiceDir {{ tor_hidden_services_parent_dir }}/{{ service.dir }}

Attachment: ansible-tor.patch.sig
Description: PGP signature

_______________________________________________
tor-relays mailing list
tor-relays@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-relays