From e79db1fca9ba2d316e6aa3f3d099332bb8d74d49 Mon Sep 17 00:00:00 2001 From: nusenu Date: Tue, 24 Apr 2018 21:56:52 +0000 Subject: [PATCH] support multiple IP addresses for use with OutboundBindAddressExit before this commit we used a single IP address for all tor instances on a server for exiting if tor_dedicatedExitIP was enabled, with this commit multiple exit IP addresses are used. By distributing the traffic across multiple source IP addresses this should help reduce the negative effects of bad traffic spoiling the source IP for many tor users. There are two cases to consider: - user runs one tor instance per IP (tor_ports has one entry): "loop_idx" can be directly used as an index to the tor_available_public_ipv4/6 arrays - user runs two tor instances per IP (tor_ports has two entries): in this case we need to mangle "loop_idx" before we used it as an index to the IP address arrays This change includes also the kitchen test suites for this feature: t-exit-6publicIPs-dedicatedExitIP-2instPerIP t-exit-6publicIPs-dedicatedExitIP-singleInstPerIP --- .kitchen.yml | 22 ++++++++++++++++ README.md | 9 +++---- tasks/configure.yml | 2 ++ tasks/main.yml | 6 ++--- templates/torrc | 26 ++++++++++++------- ...s-dedicatedExitIP-2instPerIP-exit-node.yml | 10 +++++++ ...icatedExitIP-singleInstPerIP-exit-node.yml | 13 ++++++++++ 7 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 test/integration/default/6publicIPs-dedicatedExitIP-2instPerIP-exit-node.yml create mode 100644 test/integration/default/6publicIPs-dedicatedExitIP-singleInstPerIP-exit-node.yml diff --git a/.kitchen.yml b/.kitchen.yml index e66060e..fb0540b 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -59,3 +59,25 @@ suites: - ["private_network", {ip: "198.51.100.10"}] provisioner: playbook: "test/integration/default/2publicIPs-exit-node.yml" + - name: t-exit-6publicIPs-dedicatedExitIP-2instPerIP + driver: + network: + - ["private_network", {ip: "192.0.2.10"}] + - ["private_network", {ip: "198.51.100.10"}] + - ["private_network", {ip: "198.51.100.11"}] + - ["private_network", {ip: "198.51.100.12"}] + - ["private_network", {ip: "198.51.100.13"}] + - ["private_network", {ip: "198.51.100.14"}] + provisioner: + playbook: "test/integration/default/6publicIPs-dedicatedExitIP-2instPerIP-exit-node.yml" + - name: t-exit-6publicIPs-dedicatedExitIP-singleInstPerIP + driver: + network: + - ["private_network", {ip: "192.0.2.10"}] + - ["private_network", {ip: "198.51.100.10"}] + - ["private_network", {ip: "198.51.100.11"}] + - ["private_network", {ip: "198.51.100.12"}] + - ["private_network", {ip: "198.51.100.13"}] + - ["private_network", {ip: "198.51.100.14"}] + provisioner: + playbook: "test/integration/default/6publicIPs-dedicatedExitIP-singleInstPerIP-exit-node.yml" diff --git a/README.md b/README.md index 29b99a3..3814fcb 100644 --- a/README.md +++ b/README.md @@ -204,15 +204,14 @@ All variables mentioned here are optional. - default: True (unlike tor's default) * `tor_dedicatedExitIP` boolean - - this feature **requires** tor version >= v0.3.0.3-alpha - - only relevant for exit relays - - automatically configures the [OutboundBindAddressExit](https://www.torproject.org/docs/tor-manual.html.en#OutboundBindAddressExit) tor feature (does not require you to manually specify the IP address to use) - - we will use the public IPv4/IPv6 address with the highest numerical value available on the system as the `OutboundBindAddressExit` + - on exit relays only: use a distinct source IP address for traffic leaving the tor network (exit traffic) - this means tor will establish outbound exit connections on a separate IP(v4/v6) address (different from the IP announced in the consensus) + - automatically configures the [OutboundBindAddressExit](https://www.torproject.org/docs/tor-manual.html.en#OutboundBindAddressExit) tor feature (does not require you to manually specify the IP address to use) + - we will use the public IPv4/IPv6 address(es) available directly after the IP addresses we use for tor ORPorts for `OutboundBindAddressExit` - to make use of this feature you need more public IPv4 or IPv6 addresses than `tor_maxPublicIPs` - if this condition is not met we will abort - - all instances on a host will use the same `OutboundBindAddressExit` address - manually specifying the IP address used by `OutboundBindAddressExit` is not supported + - this feature **requires** tor version >= v0.3.0.3-alpha (on the target system) - default: False * `tor_enableControlSocket` diff --git a/tasks/configure.yml b/tasks/configure.yml index 578aae3..672f725 100644 --- a/tasks/configure.yml +++ b/tasks/configure.yml @@ -211,6 +211,8 @@ - "{{ tor_ips }}" - "{{ tor_ports }}" register: tor_instances_tmp + loop_control: + index_var: loop_idx notify: - Ensure Tor instances are reloaded if its torrc changed (FreeBSD) - Ensure Tor instances are reloaded if its torrc changed (Linux) diff --git a/tasks/main.yml b/tasks/main.yml index 6542a3f..337dd91 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -28,14 +28,14 @@ tags: - always -- name: Ensure preconditions for tor_dedicatedExitIP are met (number of public IPv4 or IPv6 addresses must be bigger than tor_maxPublicIPs) +- name: Ensure preconditions for tor_dedicatedExitIP are met (enough public IP addresses on the system) assert: that: - - "tor_available_public_ipv4s|length > tor_maxPublicIPs or tor_available_public_ipv6s|length > tor_maxPublicIPs" + - "tor_available_public_ipv4s|length >= tor_maxPublicIPs*2 or tor_available_public_ipv6s|length >= tor_maxPublicIPs*2" - "tor_ExitRelay == True" - "tor_IPv6Exit == True" - "tor_IPv6 == True" - msg: "You have to few public IPv4 or IPv6 addresses for the tor_dedicatedExitIP feature (or you did not enable exiting)" + msg: "You have to few public IPv4 and IPv6 addresses for the tor_dedicatedExitIP feature (or you did not enable exiting)" when: tor_dedicatedExitIP == True tags: - always diff --git a/templates/torrc b/templates/torrc index 68230de..bd279fb 100644 --- a/templates/torrc +++ b/templates/torrc @@ -14,15 +14,6 @@ ORPort [{{item.0.ipv6}}]:{{item.1.orport}} OutboundBindAddress {{item.0.ipv6}} {% endif %} -{% if tor_dedicatedExitIP == True and tor_ExitRelay == True %} -{% if tor_available_public_ipv4s|length > tor_maxPublicIPs %} -OutboundBindAddressExit {{ tor_available_public_ipv4s[-1] }} -{% endif %} -{% if tor_available_public_ipv6s|length > tor_maxPublicIPs and tor_IPv6 == True and tor_IPv6Exit == True %} -OutboundBindAddressExit {{ tor_available_public_ipv6s[-1] }} -{% endif %} -{% endif %} - {% if item.1.dirport != 0 %} DirPort {{ item.0.ipv4 }}:{{ item.1.dirport }} {% endif %} @@ -72,6 +63,23 @@ IPv6Exit 1 DirPortFrontPage {{ tor_ConfDir }}/tor-exit-notice.html {% endif %} +{% if tor_dedicatedExitIP == True and tor_ExitRelay == True %} +{% if tor_available_public_ipv4s|length >= tor_maxPublicIPs*2 %} +{% if tor_ports|length == 2 %} +OutboundBindAddressExit {{ tor_available_public_ipv4s[(loop_idx/2)|round(0,'floor')|int + tor_maxPublicIPs]}} +{% elif tor_ports|length == 1 %} +OutboundBindAddressExit {{ tor_available_public_ipv4s[loop_idx + tor_maxPublicIPs]}} +{% endif %} +{% endif %} +{% if tor_available_public_ipv6s|length >= tor_maxPublicIPs*2 and tor_IPv6 == True and tor_IPv6Exit == True %} +{% if tor_ports|length == 2 %} +OutboundBindAddressExit {{ tor_available_public_ipv6s[(loop_idx/2)|round(0,'floor')|int + tor_maxPublicIPs]}} +{% elif tor_ports|length == 1 %} +OutboundBindAddressExit{{ tor_available_public_ipv6s[loop_idx + tor_maxPublicIPs]}} +{% endif %} +{% endif %} +{% endif %} + {% for entry in tor_ExitPolicy %} ExitPolicy {{entry}} {% endfor %} diff --git a/test/integration/default/6publicIPs-dedicatedExitIP-2instPerIP-exit-node.yml b/test/integration/default/6publicIPs-dedicatedExitIP-2instPerIP-exit-node.yml new file mode 100644 index 0000000..2737915 --- /dev/null +++ b/test/integration/default/6publicIPs-dedicatedExitIP-2instPerIP-exit-node.yml @@ -0,0 +1,10 @@ +--- +- hosts: all + vars_files: + - vars/dry-run-vars.yml + vars: + - tor_maxPublicIPs: 3 + - tor_dedicatedExitIP: True + - tor_ExitRelay: True + roles: + - ansible-relayor diff --git a/test/integration/default/6publicIPs-dedicatedExitIP-singleInstPerIP-exit-node.yml b/test/integration/default/6publicIPs-dedicatedExitIP-singleInstPerIP-exit-node.yml new file mode 100644 index 0000000..3afab63 --- /dev/null +++ b/test/integration/default/6publicIPs-dedicatedExitIP-singleInstPerIP-exit-node.yml @@ -0,0 +1,13 @@ +--- +- hosts: all + vars_files: + - vars/dry-run-vars.yml + vars: + - tor_maxPublicIPs: 3 + - tor_dedicatedExitIP: True + - tor_ExitRelay: True + - tor_ports: + - orport: 9000 + dirport: 9001 + roles: + - ansible-relayor