Add tests for Vanguards setup

pull/67/head
Christophe Mehay 4 years ago
parent 0334d7eb6b
commit 5b6e87c6e3

@ -45,8 +45,6 @@ COPY assets/vanguards.conf.tpl /var/local/tor/vanguards.conf.tpl
ENV VANGUARDS_CONFIG /etc/tor/vanguards.conf
RUN apk add socat
VOLUME ["/var/lib/tor/hidden_service/"]
ENTRYPOINT ["pyentrypoint"]

@ -192,9 +192,6 @@ Use these environment variables to enable control port
For critical hidden services, it's possible to increase security with [`Vanguards`](https://github.com/mikeperry-tor/vanguards) tool.
#### Settings
It's not possible yet to custom all the settings using environment variable, but it's possible to mount configuration file to `/etc/tor/vanguards.conf` to custom `vanguards` settings.
### Run in the same container
@ -213,6 +210,22 @@ Use the same environment variable as `tor` to configure `vangards` (see upper).
* `TOR_CONTROL_PORT`
* `TOR_CONTROL_PASSWORD`
##### more settings
Use `VANGUARDS_EXTRA_OPTIONS` environment variable to change any settings.
The following settings cannot me changer with this variable:
- `control_ip`:
- use `TOR_CONTROL_PORT`
- `control_port`:
- use `TOR_CONTROL_PORT`
- `control_socket`:
- use `TOR_CONTROL_PORT`
- `control_pass`:
- use `TOR_CONTROL_PASSWORD`
- `state_file`:
- use `VANGUARDS_STATE_FILE`
# Legacy deprecated doc
> **WARNING**: ALL THE DOC BELLOW IS LEGACY, IT'S STILL WORKING BUT IT'S NOT RECOMMENDED ANYMORE AND COULD BE DROPPED IN FUTURE RELEASES.

@ -29,7 +29,7 @@ ExitRelay 0
{% if onion.enable_control_port %}
{% if onion.control_socket %}
ControlPort unix:{{onion.control_socket}}
ControlPort {{onion.control_socket}}
{% endif %}
{% if not onion.control_socket %}
{% if onion.control_ip_binding.version() == 4 %}

@ -1,12 +1,7 @@
## Example vanguards configuration file
#
# The values in this file are the defaults. You do not need to specify
# options in your config file unless you wish to change the defaults.
## Global options
[Global]
{% if env.get('TOR_CONTROL_PORT', '').startswith('unix:') %}
{% if (env.get('TOR_CONTROL_PORT', '')).startswith('unix:') %}
{% set _, unix_path = env['TOR_CONTROL_PORT'].split(':', 1) %}
{% elif ':' in env.get('TOR_CONTROL_PORT', '') %}
{% set host, port = env['TOR_CONTROL_PORT'].split(':', 1) %}
@ -14,18 +9,34 @@
{% set host = env.get('TOR_CONTROL_PORT') %}
{% endif %}
# IP address that the Tor control port is listening on:
control_ip = {{ host or '' }}
# TCP port the control port is listening on:
control_port = {{ port or 9051 }}
# If set, use this filesystem control socket instead of IP+Port:
control_socket = {{ unix_path or '' }}
# If set, use this as the control port password:
control_pass = {{ env.get('TOR_CONTROL_PASSWORD', '') }}
state_file = {{ env.get('VANGUARDS_STATE_FILE', '/run/tor/data/vanguards.state') }}
{% if 'VANGUARDS_EXTRA_OPTIONS' in env %}
{% set extra_conf = ConfigParser().read_string(env['VANGUARDS_EXTRA_OPTIONS']) %}
{% if 'Global' in extra_conf %}
{% for key, val in extra_conf['Global'].items() %}
{{key}} = {{val}}
{% endfor %}
{% set _ = extra_conf.pop('Global') %}
{% endif %}
{{ extra_conf.to_string() }}
{% endif %}
{#
## Example vanguards configuration file
#
# All values below are default values and won't appear in final config file
# Original here: https://github.com/mikeperry-tor/vanguards/blob/master/vanguards-example.conf
#
# Enable/disable active vanguard update of layer2 and layer3 guards
enable_vanguards = True
@ -33,7 +44,7 @@ enable_vanguards = True
enable_bandguards = True
# Enable/disable circuit build timeout analysis (informational only):
enable_cbtverify = True
enable_cbtverify = False
# Enable/disable checks on Rendezvous Point overuse attacks:
enable_rendguard = True
@ -51,10 +62,6 @@ loglevel = NOTICE
# If specified, log to this file instead of stdout:
logfile =
# Name of state file (with absolute path, or relative to current directory):
state_file = {{ env.get('VANGUARDS_STATE_FILE', '/run/tor/data/vanguards.state') }}
## Vanguards: layer1, layer2, and layer3 rotation params.
[Vanguards]
@ -135,3 +142,4 @@ rend_use_relay_start_count = 100
# Divide all relay counts by two once the total circuit count hits this many:
rend_use_scale_at_count = 20000
#}

@ -12,6 +12,12 @@ services:
# Set controle port password (optionnal)
TOR_CONTROL_PASSWORD: something_secret
# You can change any options here, excepted control_* ones and state_file
VANGUARDS_EXTRA_OPTIONS: |
[Global]
enable_cbtverify = True
loglevel = DEBUG
HELLO_TOR_SERVICE_HOSTS: '80:hello:80'
HELLO_TOR_SERVICE_VERSION: '3'

@ -6,7 +6,15 @@ services:
tor:
image: goldy/tor-hidden-service:$CUR_TAG
environment:
# Enable Vanguards like this
TOR_ENABLE_VANGUARDS: 'true'
# You can change any options here, excepted control_* ones
VANGUARDS_EXTRA_OPTIONS: |
[Global]
enable_cbtverify = True
loglevel = DEBUG
HELLO_TOR_SERVICE_HOSTS: '80:hello:80'
HELLO_TOR_SERVICE_VERSION: '3'

@ -14,6 +14,7 @@ from jinja2 import Environment
from jinja2 import FileSystemLoader
from pyentrypoint import DockerLinks
from pyentrypoint.config import envtobool
from pyentrypoint.configparser import ConfigParser
from .Service import Service
from .Service import ServicesGroup
@ -64,7 +65,7 @@ class Setup(object):
control_port = os.environ['TOR_CONTROL_PORT']
try:
if control_port.startswith('unix:'):
_, self.control_socket = control_port.split(':')
self.control_socket = control_port
return
self.control_socket = None
if ':' in control_port:
@ -97,7 +98,7 @@ class Setup(object):
return
self.enable_control_port = True
self.enable_vanguards = True
os.environ['TOR_CONTROL_PORT'] = self.control_socket
os.environ.setdefault('TOR_CONTROL_PORT', self.control_socket)
self.kill_tor_on_vanguard_exit = envtobool(
'VANGUARD_KILL_TOR_ON_EXIT',
True
@ -300,6 +301,7 @@ class Setup(object):
temp = env.get_template(self.vanguards_template)
with open(self.vanguards_conf, mode='w') as f:
f.write(temp.render(env=os.environ,
ConfigParser=ConfigParser,
envtobool=envtobool))
def run_vanguards(self):

93
poetry.lock generated

@ -12,7 +12,7 @@ description = "An abstract syntax tree for Python with inference support."
name = "astroid"
optional = false
python-versions = ">=3.5"
version = "2.4.1"
version = "2.4.2"
[package.dependencies]
lazy-object-proxy = ">=1.4.0,<1.5.0"
@ -275,7 +275,7 @@ description = "More routines for operating on iterables, beyond itertools"
name = "more-itertools"
optional = false
python-versions = ">=3.5"
version = "8.3.0"
version = "8.4.0"
[[package]]
category = "dev"
@ -346,7 +346,7 @@ description = "A framework for managing and maintaining multi-language pre-commi
name = "pre-commit"
optional = false
python-versions = ">=3.6.1"
version = "2.4.0"
version = "2.5.1"
[package.dependencies]
cfgv = ">=2.0.0"
@ -426,13 +426,14 @@ description = "pyentrypoint manages entrypoints in Docker containers."
name = "pyentrypoint"
optional = false
python-versions = ">=3.6.1,<4.0.0"
version = "0.7.3"
version = "0.7.4"
[package.dependencies]
colorlog = ">=4.1,<5.0"
jinja2 = ">=2.11,<3.0"
pyyaml = ">=5.3,<6.0"
six = ">=1.14,<2.0"
toml = ">=0.10.1,<0.11.0"
watchdog = ">=0.10,<0.11"
[[package]]
@ -457,7 +458,7 @@ description = "python code static checker"
name = "pylint"
optional = false
python-versions = ">=3.5.*"
version = "2.5.2"
version = "2.5.3"
[package.dependencies]
astroid = ">=2.4.0,<=2.5"
@ -525,7 +526,7 @@ description = "Alternative regular expression module, to replace re."
name = "regex"
optional = false
python-versions = "*"
version = "2020.6.7"
version = "2020.6.8"
[[package]]
category = "main"
@ -544,7 +545,7 @@ python-versions = "*"
version = "1.8.0"
[[package]]
category = "dev"
category = "main"
description = "Python Library for Tom's Obvious, Minimal Language"
name = "toml"
optional = false
@ -604,7 +605,7 @@ description = "Virtual Python Environment builder"
name = "virtualenv"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
version = "20.0.21"
version = "20.0.23"
[package.dependencies]
appdirs = ">=1.4.3,<2"
@ -618,7 +619,7 @@ version = ">=0.12,<2"
[package.extras]
docs = ["sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)", "proselint (>=0.10.2)"]
testing = ["pytest (>=4)", "coverage (>=5)", "coverage-enable-subprocess (>=1)", "pytest-xdist (>=1.31.0)", "pytest-mock (>=2)", "pytest-env (>=0.6.2)", "pytest-randomly (>=1)", "pytest-timeout", "packaging (>=20.0)", "xonsh (>=0.9.16)"]
testing = ["pytest (>=4)", "coverage (>=5)", "coverage-enable-subprocess (>=1)", "pytest-xdist (>=1.31.0)", "pytest-mock (>=2)", "pytest-env (>=0.6.2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "flaky (>=3)", "packaging (>=20.0)", "xonsh (>=0.9.16)"]
[[package]]
category = "main"
@ -640,7 +641,7 @@ description = "Measures the displayed width of unicode strings in a terminal"
name = "wcwidth"
optional = false
python-versions = "*"
version = "0.2.3"
version = "0.2.4"
[[package]]
category = "dev"
@ -663,7 +664,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["jaraco.itertools", "func-timeout"]
[metadata]
content-hash = "097415d9c723c691882ffa440af8e248746a278f758745d2ce75ffab1bdac90d"
content-hash = "044c9aa2965d6dc97970237a0a1e5e02fdd37609ff58cf58f2e68b0a5edecf2a"
python-versions = ">= 3.7, < 3.8"
[metadata.files]
@ -672,8 +673,8 @@ appdirs = [
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
]
astroid = [
{file = "astroid-2.4.1-py3-none-any.whl", hash = "sha256:d8506842a3faf734b81599c8b98dcc423de863adcc1999248480b18bd31a0f38"},
{file = "astroid-2.4.1.tar.gz", hash = "sha256:4c17cea3e592c21b6e222f673868961bad77e1f985cb1694ed077475a89229c1"},
{file = "astroid-2.4.2-py3-none-any.whl", hash = "sha256:bc58d83eb610252fd8de6363e39d4f1d0619c894b0ed24603b881c02e64c7386"},
{file = "astroid-2.4.2.tar.gz", hash = "sha256:2f4078c2a41bf377eea06d71c9d2ba4eb8f6b1af2135bec27bbbb7d8f12bb703"},
]
atomicwrites = [
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
@ -854,8 +855,8 @@ mccabe = [
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
]
more-itertools = [
{file = "more-itertools-8.3.0.tar.gz", hash = "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be"},
{file = "more_itertools-8.3.0-py3-none-any.whl", hash = "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982"},
{file = "more-itertools-8.4.0.tar.gz", hash = "sha256:68c70cc7167bdf5c7c9d8f6954a7837089c6a36bf565383919bb595efb8a17e5"},
{file = "more_itertools-8.4.0-py3-none-any.whl", hash = "sha256:b78134b2063dd214000685165d81c154522c3ee0a1c0d4d113c80361c234c5a2"},
]
nodeenv = [
{file = "nodeenv-1.4.0-py2.py3-none-any.whl", hash = "sha256:4b0b77afa3ba9b54f4b6396e60b0c83f59eaeb2d63dc3cc7a70f7f4af96c82bc"},
@ -880,8 +881,8 @@ pluggy = [
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
]
pre-commit = [
{file = "pre_commit-2.4.0-py2.py3-none-any.whl", hash = "sha256:5559e09afcac7808933951ffaf4ff9aac524f31efbc3f24d021540b6c579813c"},
{file = "pre_commit-2.4.0.tar.gz", hash = "sha256:703e2e34cbe0eedb0d319eff9f7b83e2022bb5a3ab5289a6a8841441076514d0"},
{file = "pre_commit-2.5.1-py2.py3-none-any.whl", hash = "sha256:c5c8fd4d0e1c363723aaf0a8f9cba0f434c160b48c4028f4bae6d219177945b3"},
{file = "pre_commit-2.5.1.tar.gz", hash = "sha256:da463cf8f0e257f9af49047ba514f6b90dbd9b4f92f4c8847a3ccd36834874c7"},
]
prompt-toolkit = [
{file = "prompt_toolkit-3.0.5-py3-none-any.whl", hash = "sha256:df7e9e63aea609b1da3a65641ceaf5bc7d05e0a04de5bd45d05dbeffbabf9e04"},
@ -938,8 +939,8 @@ pycryptodome = [
{file = "pycryptodome-3.9.4.tar.gz", hash = "sha256:a168e73879619b467072509a223282a02c8047d932a48b74fbd498f27224aa04"},
]
pyentrypoint = [
{file = "pyentrypoint-0.7.3-py3-none-any.whl", hash = "sha256:aa4b3016466b398d379a974e01c363ed12618652adbe6a193ced43ed0fcefacc"},
{file = "pyentrypoint-0.7.3.tar.gz", hash = "sha256:59c02957ec82e9ca53997e66f75d0f375f1a1b39373074d790307d6a159a1e06"},
{file = "pyentrypoint-0.7.4-py3-none-any.whl", hash = "sha256:90dd03052f8e2a7fe4cf7781b6a16711d9ad247607e02d861c5870eff917ad58"},
{file = "pyentrypoint-0.7.4.tar.gz", hash = "sha256:ec1d974dc7ca9cc77ffde31937121c04830060825081a9cfbf25712459c844d9"},
]
pyfakefs = [
{file = "pyfakefs-4.0.2-py3-none-any.whl", hash = "sha256:42cf165adc821fc9e205d3fc14033d45e0b8224e1d2fea4f67b487c6b7b3230e"},
@ -950,8 +951,8 @@ pygments = [
{file = "Pygments-2.6.1.tar.gz", hash = "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44"},
]
pylint = [
{file = "pylint-2.5.2-py3-none-any.whl", hash = "sha256:dd506acce0427e9e08fb87274bcaa953d38b50a58207170dbf5b36cf3e16957b"},
{file = "pylint-2.5.2.tar.gz", hash = "sha256:b95e31850f3af163c2283ed40432f053acbc8fc6eba6a069cb518d9dbf71848c"},
{file = "pylint-2.5.3-py3-none-any.whl", hash = "sha256:d0ece7d223fe422088b0e8f13fa0a1e8eb745ebffcb8ed53d3e95394b6101a1c"},
{file = "pylint-2.5.3.tar.gz", hash = "sha256:7dd78437f2d8d019717dbf287772d0b2dbdfd13fc016aa7faa08d67bccc46adc"},
]
pyparsing = [
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
@ -978,27 +979,27 @@ pyyaml = [
{file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
]
regex = [
{file = "regex-2020.6.7-cp27-cp27m-win32.whl", hash = "sha256:8d9bb2d90e23c51aacbc58c1a11320f49b335cd67a91986cdbebcc3e843e4de8"},
{file = "regex-2020.6.7-cp27-cp27m-win_amd64.whl", hash = "sha256:dcda6d4e1bbfc939b177c237aee41c9678eaaf71df482688f8986e8251e12345"},
{file = "regex-2020.6.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:af7209b2fcc79ee2b0ad4ea080d70bb748450ec4f282cc9e864861e469b1072e"},
{file = "regex-2020.6.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5735f26cacdb50b3d6d35ebf8fdeb504bd8b381e2d079d2d9f12ce534fc14ecd"},
{file = "regex-2020.6.7-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f6c8c3f56fef719180464855346e6e80971b86dfd9e5a0e356664b5baca53072"},
{file = "regex-2020.6.7-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:21fc17cb868c4264f0813f992f46f9ae6fc8c309d4741091de4153bd1f6a6176"},
{file = "regex-2020.6.7-cp36-cp36m-win32.whl", hash = "sha256:150125da109fccdcc8fec3b0b386b2a5d6ca7cff076f8b622486d1ca868b0c10"},
{file = "regex-2020.6.7-cp36-cp36m-win_amd64.whl", hash = "sha256:c0849b0864ff451f04c8afb5fc28e9ed592262e03debdd227cf0f53e04a55dcd"},
{file = "regex-2020.6.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:8d1ee3796795e609ef7a3a5a35eaf4728038d986aa12c06b3fd1b92ee81911f4"},
{file = "regex-2020.6.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7606dba82435429641efe4fbc580574942f89cf2b9c5c1f8bc1eab2bacbf7e8b"},
{file = "regex-2020.6.7-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:6edc5c190248d3b612f2cca45448cf8ebc3621d41afcd1c5708853cbb1dbb3b3"},
{file = "regex-2020.6.7-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:2c928bc8e0c453d73dffa3193a6e37ee752ea36df0dd4601e21024d98274dfad"},
{file = "regex-2020.6.7-cp37-cp37m-win32.whl", hash = "sha256:97d414c41f19fd2362e493810caa8445c05e0a2d63a14081c972aad66284a8d2"},
{file = "regex-2020.6.7-cp37-cp37m-win_amd64.whl", hash = "sha256:9e37502817225ee99d91d8418f5119e98c380b00e772d06915690c05290f32ee"},
{file = "regex-2020.6.7-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c4ac9215650688e78dea29b46adbdafb7b85058eebe92ef6ea848e14466c915f"},
{file = "regex-2020.6.7-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:20c513893ff80bdbe4b4ce11ea2e93d49481f05b270595d82af69ffc402010a6"},
{file = "regex-2020.6.7-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:163bc0805e46acfa098dfc8c0b07f371577d505f603e48afc425ff475cdac3a5"},
{file = "regex-2020.6.7-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:2d9beca70e36f9c60d679e108c5fe49f3d4da79d13a13f91e5e759443bd954f9"},
{file = "regex-2020.6.7-cp38-cp38-win32.whl", hash = "sha256:ec0e509ed1877ff1cbc6f0864689bb60384a303502c4d72d9a635f8a4676fd3f"},
{file = "regex-2020.6.7-cp38-cp38-win_amd64.whl", hash = "sha256:dd8501b8d9ea1aba53c4bc7d47bc72933f9b4213d534cf400f16c1431f51c8ba"},
{file = "regex-2020.6.7.tar.gz", hash = "sha256:ffd4f80602490a309064cf2b203e220d581c51660e01055c64bf5da450485ee6"},
{file = "regex-2020.6.8-cp27-cp27m-win32.whl", hash = "sha256:fbff901c54c22425a5b809b914a3bfaf4b9570eee0e5ce8186ac71eb2025191c"},
{file = "regex-2020.6.8-cp27-cp27m-win_amd64.whl", hash = "sha256:112e34adf95e45158c597feea65d06a8124898bdeac975c9087fe71b572bd938"},
{file = "regex-2020.6.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:92d8a043a4241a710c1cf7593f5577fbb832cf6c3a00ff3fc1ff2052aff5dd89"},
{file = "regex-2020.6.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bae83f2a56ab30d5353b47f9b2a33e4aac4de9401fb582b55c42b132a8ac3868"},
{file = "regex-2020.6.8-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:b2ba0f78b3ef375114856cbdaa30559914d081c416b431f2437f83ce4f8b7f2f"},
{file = "regex-2020.6.8-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:95fa7726d073c87141f7bbfb04c284901f8328e2d430eeb71b8ffdd5742a5ded"},
{file = "regex-2020.6.8-cp36-cp36m-win32.whl", hash = "sha256:e3cdc9423808f7e1bb9c2e0bdb1c9dc37b0607b30d646ff6faf0d4e41ee8fee3"},
{file = "regex-2020.6.8-cp36-cp36m-win_amd64.whl", hash = "sha256:c78e66a922de1c95a208e4ec02e2e5cf0bb83a36ceececc10a72841e53fbf2bd"},
{file = "regex-2020.6.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:08997a37b221a3e27d68ffb601e45abfb0093d39ee770e4257bd2f5115e8cb0a"},
{file = "regex-2020.6.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2f6f211633ee8d3f7706953e9d3edc7ce63a1d6aad0be5dcee1ece127eea13ae"},
{file = "regex-2020.6.8-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:55b4c25cbb3b29f8d5e63aeed27b49fa0f8476b0d4e1b3171d85db891938cc3a"},
{file = "regex-2020.6.8-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:89cda1a5d3e33ec9e231ece7307afc101b5217523d55ef4dc7fb2abd6de71ba3"},
{file = "regex-2020.6.8-cp37-cp37m-win32.whl", hash = "sha256:690f858d9a94d903cf5cada62ce069b5d93b313d7d05456dbcd99420856562d9"},
{file = "regex-2020.6.8-cp37-cp37m-win_amd64.whl", hash = "sha256:1700419d8a18c26ff396b3b06ace315b5f2a6e780dad387e4c48717a12a22c29"},
{file = "regex-2020.6.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:654cb773b2792e50151f0e22be0f2b6e1c3a04c5328ff1d9d59c0398d37ef610"},
{file = "regex-2020.6.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:52e1b4bef02f4040b2fd547357a170fc1146e60ab310cdbdd098db86e929b387"},
{file = "regex-2020.6.8-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:cf59bbf282b627130f5ba68b7fa3abdb96372b24b66bdf72a4920e8153fc7910"},
{file = "regex-2020.6.8-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:5aaa5928b039ae440d775acea11d01e42ff26e1561c0ffcd3d805750973c6baf"},
{file = "regex-2020.6.8-cp38-cp38-win32.whl", hash = "sha256:97712e0d0af05febd8ab63d2ef0ab2d0cd9deddf4476f7aa153f76feef4b2754"},
{file = "regex-2020.6.8-cp38-cp38-win_amd64.whl", hash = "sha256:6ad8663c17db4c5ef438141f99e291c4d4edfeaacc0ce28b5bba2b0bf273d9b5"},
{file = "regex-2020.6.8.tar.gz", hash = "sha256:e9b64e609d37438f7d6e68c2546d2cb8062f3adb27e6336bc129b51be20773ac"},
]
six = [
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
@ -1043,15 +1044,15 @@ vanguards = [
{file = "vanguards-0.3.1.tar.gz", hash = "sha256:04049fafd433bb747fbe27b404413ce09b441d5e0e6cc5d81debaac2192567b7"},
]
virtualenv = [
{file = "virtualenv-20.0.21-py2.py3-none-any.whl", hash = "sha256:a730548b27366c5e6cbdf6f97406d861cccece2e22275e8e1a757aeff5e00c70"},
{file = "virtualenv-20.0.21.tar.gz", hash = "sha256:a116629d4e7f4d03433b8afa27f43deba09d48bc48f5ecefa4f015a178efb6cf"},
{file = "virtualenv-20.0.23-py2.py3-none-any.whl", hash = "sha256:ccfb8e1e05a1174f7bd4c163700277ba730496094fe1a58bea9d4ac140a207c8"},
{file = "virtualenv-20.0.23.tar.gz", hash = "sha256:5102fbf1ec57e80671ef40ed98a84e980a71194cedf30c87c2b25c3a9e0b0107"},
]
watchdog = [
{file = "watchdog-0.10.2.tar.gz", hash = "sha256:c560efb643faed5ef28784b2245cf8874f939569717a4a12826a173ac644456b"},
]
wcwidth = [
{file = "wcwidth-0.2.3-py2.py3-none-any.whl", hash = "sha256:980fbf4f3c196c0f329cdcd1e84c554d6a211f18e252e525a0cf4223154a41d6"},
{file = "wcwidth-0.2.3.tar.gz", hash = "sha256:edbc2b718b4db6cdf393eefe3a420183947d6aa312505ce6754516f458ff8830"},
{file = "wcwidth-0.2.4-py2.py3-none-any.whl", hash = "sha256:79375666b9954d4a1a10739315816324c3e73110af9d0e102d906fdb0aec009f"},
{file = "wcwidth-0.2.4.tar.gz", hash = "sha256:8c6b5b6ee1360b842645f336d9e5d68c55817c26d3050f46b235ef2bc650e48f"},
]
wrapt = [
{file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"},

@ -1,6 +1,6 @@
[tool.poetry]
name = "docker-tor-hidden-service"
version = "0.6.0"
version = "0.6.1"
description = "Display onion sites hosted"
authors = ["Christophe Mehay <cmehay@nospam.student.42.fr>"]
license = "WTFPL"
@ -26,7 +26,7 @@ onions = "onions:main"
python = ">= 3.7, < 3.8"
pytor = "^0.1.5"
Jinja2 = "^2.10"
pyentrypoint = "^0.7.3"
pyentrypoint = "^0.7.4"
importlib_metadata = "^1.6.0"
vanguards = "^0.3.1"
ipy = "^1.00"

@ -1,3 +1,4 @@
import configparser
import json
import os
import re
@ -13,7 +14,9 @@ from onions import Onions
def get_key_and_onion(version=2):
key = {}
key[2] = '''
key[
2
] = """
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCsMP4gl6g1Q313miPhb1GnDr56ZxIWGsO2PwHM1infkbhlBakR
6DGQfpE31L1ZKTUxY0OexKbW088v8qCOfjD9Zk1i80JP4xzfWQcwFZ5yM/0fkhm3
@ -29,36 +32,41 @@ l5MQPWBkRKK2pc2Hfj8cdIMi8kJ/1CyCwE6c5l8etR3sbIMRTtZ76nAbXRFkmsRv
La/7Syrnobngsh/vX90CQB+PSSBqiPSsK2yPz6Gsd6OLCQ9sdy2oRwFTasH8sZyl
bhJ3M9WzP/EMkAzyW8mVs1moFp3hRcfQlZHl6g1U9D8=
-----END RSA PRIVATE KEY-----
'''
"""
onion = {}
pub = {}
onion[2] = b32encode(
sha1(
RSA.importKey(
key[2].strip()
).publickey().exportKey(
"DER"
)[22:]
).digest()[:10]
).decode().lower() + '.onion'
key[3] = '''
onion[2] = (
b32encode(
sha1(
RSA.importKey(key[2].strip()).publickey().exportKey("DER")[22:]
).digest()[:10]
)
.decode()
.lower()
+ ".onion"
)
key[
3
] = """
PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAACArobDQYyZAWXei4QZwr++j96H1X/gq14N
wLRZ2O5DXuL0EzYKkdhZSILY85q+kfwZH8z4ceqe7u1F+0pQi/sM
'''
"""
pub[3] = '''
pub[
3
] = """
PT0gZWQyNTUxOXYxLXB1YmxpYzogdHlwZTAgPT0AAAC9kzftiea/kb+TWlCEVNpfUJLVk+rFIoMG
m9/hW13isA==
'''
"""
onion[3] = 'xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion'
onion[3] = "xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion"
return key[version].strip(), onion[version]
def get_torrc_template():
return r'''
return r"""
{% for service_group in onion.services %}
HiddenServiceDir {{service_group.hidden_service_dir}}
{% if service_group.version == 3 %}
@ -90,7 +98,7 @@ ExitRelay 0
{% if onion.enable_control_port %}
{% if onion.control_socket %}
ControlPort unix:{{onion.control_socket}}
ControlPort {{onion.control_socket}}
{% endif %}
{% if not onion.control_socket %}
{% if onion.control_ip_binding.version() == 4 %}
@ -111,17 +119,20 @@ HashedControlPassword {{ onion.control_hashed_password }}
{% endif %}
# useless line for Jinja bug
'''.strip()
# useless line for Jinja bug
""".strip()
def test_ports(monkeypatch):
env = {
'SERVICE1_PORTS': '80:80',
'SERVICE2_PORTS': '80:80,81:8000',
'SERVICE3_PORTS': '80:unix://unix.socket',
"SERVICE1_PORTS": "80:80",
"SERVICE2_PORTS": "80:80,81:8000",
"SERVICE3_PORTS": "80:unix://unix.socket",
}
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
@ -131,24 +142,24 @@ def test_ports(monkeypatch):
for service_group in onion.services:
assert len(service_group.services) == 1
service = service_group.services[0]
if service.host == 'service1':
if service.host == "service1":
check += 1
assert len(service.ports) == 1
assert service.ports[0].port_from == 80
assert service.ports[0].dest == 80
assert not service.ports[0].is_socket
if service.host == 'service2':
if service.host == "service2":
check += 3
assert len(service.ports) == 2
assert service.ports[0].port_from == 80
assert service.ports[0].dest == 80
assert service.ports[1].port_from == 81
assert service.ports[1].dest == 8000
if service.host == 'service3':
if service.host == "service3":
check += 6
assert len(service.ports) == 1
assert service.ports[0].port_from == 80
assert service.ports[0].dest == 'unix://unix.socket'
assert service.ports[0].dest == "unix://unix.socket"
assert service.ports[0].is_socket
assert check == 10
@ -157,40 +168,40 @@ def test_ports(monkeypatch):
def test_docker_links(fs, monkeypatch):
env = {
'HOSTNAME': 'test_env',
'COMPOSE_SERVICE1_1_PORT': 'tcp://172.17.0.2:80',
'COMPOSE_SERVICE1_1_PORT_80_TCP': 'tcp://172.17.0.2:80',
'COMPOSE_SERVICE1_1_PORT_80_TCP_ADDR': '172.17.0.2',
'COMPOSE_SERVICE1_1_PORT_80_TCP_PORT': '80',
'COMPOSE_SERVICE1_1_PORT_80_TCP_PROTO': 'tcp',
'COMPOSE_SERVICE1_1_PORT_8000_TCP': 'tcp://172.17.0.2:8000',
'COMPOSE_SERVICE1_1_PORT_8000_TCP_ADDR': '172.17.0.2',
'COMPOSE_SERVICE1_1_PORT_8000_TCP_PORT': '8000',
'COMPOSE_SERVICE1_1_PORT_8000_TCP_PROTO': 'tcp',
'COMPOSE_SERVICE1_1_NAME': '/compose_env_1/compose_service1_1',
'SERVICE1_PORT': 'tcp://172.17.0.2:80',
'SERVICE1_PORT_80_TCP': 'tcp://172.17.0.2:80',
'SERVICE1_PORT_80_TCP_ADDR': '172.17.0.2',
'SERVICE1_PORT_80_TCP_PORT': '80',
'SERVICE1_PORT_80_TCP_PROTO': 'tcp',
'SERVICE1_PORT_8000_TCP': 'tcp://172.17.0.2:8000',
'SERVICE1_PORT_8000_TCP_ADDR': '172.17.0.2',
'SERVICE1_PORT_8000_TCP_PORT': '8000',
'SERVICE1_PORT_8000_TCP_PROTO': 'tcp',
'SERVICE1_NAME': '/compose_env_1/service1',
'SERVICE1_1_PORT': 'tcp://172.17.0.2:80',
'SERVICE1_1_PORT_80_TCP': 'tcp://172.17.0.2:80',
'SERVICE1_1_PORT_80_TCP_ADDR': '172.17.0.2',
'SERVICE1_1_PORT_80_TCP_PORT': '80',
'SERVICE1_1_PORT_80_TCP_PROTO': 'tcp',
'SERVICE1_1_PORT_8000_TCP': 'tcp://172.17.0.2:8000',
'SERVICE1_1_PORT_8000_TCP_ADDR': '172.17.0.2',
'SERVICE1_1_PORT_8000_TCP_PORT': '8000',
'SERVICE1_1_PORT_8000_TCP_PROTO': 'tcp',
'SERVICE1_1_NAME': '/compose_env_1/service1_1',
"HOSTNAME": "test_env",
"COMPOSE_SERVICE1_1_PORT": "tcp://172.17.0.2:80",
"COMPOSE_SERVICE1_1_PORT_80_TCP": "tcp://172.17.0.2:80",
"COMPOSE_SERVICE1_1_PORT_80_TCP_ADDR": "172.17.0.2",
"COMPOSE_SERVICE1_1_PORT_80_TCP_PORT": "80",
"COMPOSE_SERVICE1_1_PORT_80_TCP_PROTO": "tcp",
"COMPOSE_SERVICE1_1_PORT_8000_TCP": "tcp://172.17.0.2:8000",
"COMPOSE_SERVICE1_1_PORT_8000_TCP_ADDR": "172.17.0.2",
"COMPOSE_SERVICE1_1_PORT_8000_TCP_PORT": "8000",
"COMPOSE_SERVICE1_1_PORT_8000_TCP_PROTO": "tcp",
"COMPOSE_SERVICE1_1_NAME": "/compose_env_1/compose_service1_1",
"SERVICE1_PORT": "tcp://172.17.0.2:80",
"SERVICE1_PORT_80_TCP": "tcp://172.17.0.2:80",
"SERVICE1_PORT_80_TCP_ADDR": "172.17.0.2",
"SERVICE1_PORT_80_TCP_PORT": "80",
"SERVICE1_PORT_80_TCP_PROTO": "tcp",
"SERVICE1_PORT_8000_TCP": "tcp://172.17.0.2:8000",
"SERVICE1_PORT_8000_TCP_ADDR": "172.17.0.2",
"SERVICE1_PORT_8000_TCP_PORT": "8000",
"SERVICE1_PORT_8000_TCP_PROTO": "tcp",
"SERVICE1_NAME": "/compose_env_1/service1",
"SERVICE1_1_PORT": "tcp://172.17.0.2:80",
"SERVICE1_1_PORT_80_TCP": "tcp://172.17.0.2:80",
"SERVICE1_1_PORT_80_TCP_ADDR": "172.17.0.2",
"SERVICE1_1_PORT_80_TCP_PORT": "80",
"SERVICE1_1_PORT_80_TCP_PROTO": "tcp",
"SERVICE1_1_PORT_8000_TCP": "tcp://172.17.0.2:8000",
"SERVICE1_1_PORT_8000_TCP_ADDR": "172.17.0.2",
"SERVICE1_1_PORT_8000_TCP_PORT": "8000",
"SERVICE1_1_PORT_8000_TCP_PROTO": "tcp",
"SERVICE1_1_NAME": "/compose_env_1/service1_1",
}
etc_host = '''
etc_host = """
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
@ -200,11 +211,11 @@ ff02::2 ip6-allrouters
172.17.0.2 service1 bf447f22cdba compose_service1_1
172.17.0.2 service1_1 bf447f22cdba compose_service1_1
172.17.0.2 compose_service1_1 bf447f22cdba
'''.strip()
""".strip()
fs.create_file('/etc/hosts', contents=etc_host)
fs.create_file("/etc/hosts", contents=etc_host)
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_links()
@ -214,19 +225,17 @@ ff02::2 ip6-allrouters
assert len(group.services) == 1
service = group.services[0]
assert len(service.ports) == 2
assert set(
(port.port_from, port.dest) for port in service.ports
) == set([(80, 80), (8000, 8000)])
assert set((port.port_from, port.dest) for port in service.ports) == set(
[(80, 80), (8000, 8000)]
)
def test_key(monkeypatch):
key, onion_url = get_key_and_onion()
env = {
'SERVICE1_KEY': key
}
env = {"SERVICE1_KEY": key}
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
@ -239,17 +248,20 @@ def test_key(monkeypatch):
def test_key_v2(monkeypatch):
key, onion_url = get_key_and_onion(version=2)
envs = [{
'GROUP1_TOR_SERVICE_HOSTS': '80:service1:80,81:service2:80',
'GROUP1_TOR_SERVICE_VERSION': '2',
'GROUP1_TOR_SERVICE_KEY': key,
}, {
'GROUP1_TOR_SERVICE_HOSTS': '80:service1:80,81:service2:80',
'GROUP1_TOR_SERVICE_KEY': key,
}]
envs = [
{
"GROUP1_TOR_SERVICE_HOSTS": "80:service1:80,81:service2:80",
"GROUP1_TOR_SERVICE_VERSION": "2",
"GROUP1_TOR_SERVICE_KEY": key,
},
{
"GROUP1_TOR_SERVICE_HOSTS": "80:service1:80,81:service2:80",
"GROUP1_TOR_SERVICE_KEY": key,
},
]
for env in envs:
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
@ -264,12 +276,12 @@ def test_key_v2(monkeypatch):
def test_key_v3(monkeypatch):
key, onion_url = get_key_and_onion(version=3)
env = {
'GROUP1_TOR_SERVICE_HOSTS': '80:service1:80,81:service2:80',
'GROUP1_TOR_SERVICE_VERSION': '3',
'GROUP1_TOR_SERVICE_KEY': key,
"GROUP1_TOR_SERVICE_HOSTS": "80:service1:80,81:service2:80",
"GROUP1_TOR_SERVICE_VERSION": "3",
"GROUP1_TOR_SERVICE_KEY": key,
}
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
@ -283,27 +295,27 @@ def test_key_v3(monkeypatch):
def test_key_in_secret(fs, monkeypatch):
env = {
'GROUP1_TOR_SERVICE_HOSTS': '80:service1:80',
'GROUP2_TOR_SERVICE_HOSTS': '80:service2:80',
'GROUP3_TOR_SERVICE_HOSTS': '80:service3:80',
'GROUP3_TOR_SERVICE_VERSION': '3',
"GROUP1_TOR_SERVICE_HOSTS": "80:service1:80",
"GROUP2_TOR_SERVICE_HOSTS": "80:service2:80",
"GROUP3_TOR_SERVICE_HOSTS": "80:service3:80",
"GROUP3_TOR_SERVICE_VERSION": "3",
}
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
key_v2, onion_url_v2 = get_key_and_onion()
key_v3, onion_url_v3 = get_key_and_onion(version=3)
fs.create_file('/run/secrets/group1', contents=key_v2)
fs.create_file('/run/secrets/group3', contents=b64decode(key_v3))
fs.create_file("/run/secrets/group1", contents=key_v2)
fs.create_file("/run/secrets/group3", contents=b64decode(key_v3))
onion = Onions()
onion._get_setup_from_env()
onion._load_keys_in_services()
group1 = onion.find_group_by_name('group1')
group2 = onion.find_group_by_name('group2')
group3 = onion.find_group_by_name('group3')
group1 = onion.find_group_by_name("group1")
group2 = onion.find_group_by_name("group2")
group3 = onion.find_group_by_name("group3")
assert group1.onion_url == onion_url_v2
assert group2.onion_url not in [onion_url_v2, onion_url_v3]
@ -311,37 +323,37 @@ def test_key_in_secret(fs, monkeypatch):
def test_configuration(fs, monkeypatch, tmpdir):
extra_options = '''
extra_options = """
HiddenServiceNonAnonymousMode 1
HiddenServiceSingleHopMode 1
'''.strip()
""".strip()
env = {
'SERVICE1_SERVICE_NAME': 'group1',
'SERVICE2_SERVICE_NAME': 'group1',
'SERVICE3_SERVICE_NAME': 'group2',
'SERVICE1_PORTS': '80:80',
'SERVICE2_PORTS': '81:80,82:8000',
'SERVICE3_PORTS': '80:unix://unix.socket',
'GROUP3_TOR_SERVICE_VERSION': '2',
'GROUP3_TOR_SERVICE_HOSTS': '80:service4:888,81:service5:8080',
'GROUP4_TOR_SERVICE_VERSION': '3',
'GROUP4_TOR_SERVICE_HOSTS': '81:unix://unix2.sock',
'GROUP3V3_TOR_SERVICE_VERSION': '3',
'GROUP3V3_TOR_SERVICE_HOSTS': '80:service4:888,81:service5:8080',
'SERVICE5_TOR_SERVICE_HOSTS': '80:service5:80',
'TOR_EXTRA_OPTIONS': extra_options,
"SERVICE1_SERVICE_NAME": "group1",
"SERVICE2_SERVICE_NAME": "group1",
"SERVICE3_SERVICE_NAME": "group2",
"SERVICE1_PORTS": "80:80",
"SERVICE2_PORTS": "81:80,82:8000",
"SERVICE3_PORTS": "80:unix://unix.socket",
"GROUP3_TOR_SERVICE_VERSION": "2",
"GROUP3_TOR_SERVICE_HOSTS": "80:service4:888,81:service5:8080",
"GROUP4_TOR_SERVICE_VERSION": "3",
"GROUP4_TOR_SERVICE_HOSTS": "81:unix://unix2.sock",
"GROUP3V3_TOR_SERVICE_VERSION": "3",
"GROUP3V3_TOR_SERVICE_HOSTS": "80:service4:888,81:service5:8080",
"SERVICE5_TOR_SERVICE_HOSTS": "80:service5:80",
"TOR_EXTRA_OPTIONS": extra_options,
}
hidden_dir = '/var/lib/tor/hidden_service'
hidden_dir = "/var/lib/tor/hidden_service"
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, 'fchmod', lambda x, y: None)
monkeypatch.setattr(os, "environ", env)
monkeypatch.setattr(os, "fchmod", lambda x, y: None)
torrc_tpl = get_torrc_template()
fs.create_file('/var/local/tor/torrc.tpl', contents=torrc_tpl)
fs.create_file('/etc/tor/torrc')
fs.create_file("/var/local/tor/torrc.tpl", contents=torrc_tpl)
fs.create_file("/etc/tor/torrc")
fs.create_dir(hidden_dir)
onion = Onions()
@ -351,30 +363,31 @@ HiddenServiceSingleHopMode 1
onions_urls = {}
for dir in os.listdir(hidden_dir):
with open(os.path.join(hidden_dir, dir, 'hostname'), 'r') as f:
with open(os.path.join(hidden_dir, dir, "hostname"), "r") as f:
onions_urls[dir] = f.read().strip()
with open('/etc/tor/torrc', 'r') as f:
with open("/etc/tor/torrc", "r") as f:
torrc = f.read()
print(torrc)
assert 'HiddenServiceDir /var/lib/tor/hidden_service/group1' in torrc
assert 'HiddenServicePort 80 service1:80' in torrc
assert 'HiddenServicePort 81 service2:80' in torrc
assert 'HiddenServicePort 82 service2:8000' in torrc
assert 'HiddenServiceDir /var/lib/tor/hidden_service/group2' in torrc
assert 'HiddenServicePort 80 unix://unix.socket' in torrc
assert 'HiddenServiceDir /var/lib/tor/hidden_service/group3' in torrc
assert 'HiddenServiceDir /var/lib/tor/hidden_service/group4' in torrc
assert 'HiddenServiceDir /var/lib/tor/hidden_service/group3v3' in torrc
assert 'HiddenServiceDir /var/lib/tor/hidden_service/service5' in torrc
assert torrc.count('HiddenServicePort 80 service4:888') == 2
assert torrc.count('HiddenServicePort 81 service5:8080') == 2
assert torrc.count('HiddenServicePort 80 service5:80') == 1
assert torrc.count('HiddenServicePort 81 unix://unix2.sock') == 1
assert torrc.count('HiddenServiceVersion 3') == 2
assert 'HiddenServiceNonAnonymousMode 1\n' in torrc
assert 'HiddenServiceSingleHopMode 1\n' in torrc
assert "HiddenServiceDir /var/lib/tor/hidden_service/group1" in torrc
assert "HiddenServicePort 80 service1:80" in torrc
assert "HiddenServicePort 81 service2:80" in torrc
assert "HiddenServicePort 82 service2:8000" in torrc
assert "HiddenServiceDir /var/lib/tor/hidden_service/group2" in torrc
assert "HiddenServicePort 80 unix://unix.socket" in torrc
assert "HiddenServiceDir /var/lib/tor/hidden_service/group3" in torrc
assert "HiddenServiceDir /var/lib/tor/hidden_service/group4" in torrc
assert "HiddenServiceDir /var/lib/tor/hidden_service/group3v3" in torrc
assert "HiddenServiceDir /var/lib/tor/hidden_service/service5" in torrc
assert torrc.count("HiddenServicePort 80 service4:888") == 2
assert torrc.count("HiddenServicePort 81 service5:8080") == 2
assert torrc.count("HiddenServicePort 80 service5:80") == 1
assert torrc.count("HiddenServicePort 81 unix://unix2.sock") == 1
assert torrc.count("HiddenServiceVersion 3") == 2
assert "HiddenServiceNonAnonymousMode 1\n" in torrc
assert "HiddenServiceSingleHopMode 1\n" in torrc
assert "ControlPort" not in torrc
# Check parser
onion2 = Onions()
@ -383,141 +396,184 @@ HiddenServiceSingleHopMode 1
assert len(onion2.services) == 6
assert set(
group.name for group in onion2.services
group.name
for group in onion2.services
# ) == set(['group1', 'group2'])
) == set(['group1', 'group2', 'group3', 'group4', 'group3v3', 'service5'])
) == set(["group1", "group2", "group3", "group4", "group3v3", "service5"])
for group in onion2.services:
if group.name == 'group1':
if group.name == "group1":
assert len(group.services) == 2
assert group.version == 2
assert group.onion_url == onions_urls[group.name]
assert set(
service.host for service in group.services
) == set(['service1', 'service2'])
assert set(service.host for service in group.services) == set(
["service1", "service2"]
)
for service in group.services:
if service.host == 'service1':
if service.host == "service1":
assert len(service.ports) == 1
assert set(
(port.port_from, port.dest) for port in service.ports
) == set([(80, 80)])
if service.host == 'service2':
if service.host == "service2":
assert len(service.ports) == 2
assert set(
(port.port_from, port.dest) for port in service.ports
) == set([(81, 80), (82, 8000)])
if group.name == 'group2':
if group.name == "group2":
assert len(group.services) == 1
assert group.version == 2
assert group.onion_url == onions_urls[group.name]
assert set(
service.host for service in group.services
) == set(['group2'])
assert set(service.host for service in group.services) == set(
["group2"]
)
service = group.services[0]
assert len(service.ports) == 1
assert set(
(port.port_from, port.dest) for port in service.ports
) == set([(80, 'unix://unix.socket')])
) == set([(80, "unix://unix.socket")])
if group.name in ['group3', 'group3v3']:
if group.name in ["group3", "group3v3"]:
assert len(group.services) == 2
assert group.version == 2 if group.name == 'group3' else 3
assert group.version == 2 if group.name == "group3" else 3
assert group.onion_url == onions_urls[group.name]
assert set(
service.host for service in group.services
) == set(['service4', 'service5'])
assert set(service.host for service in group.services) == set(
["service4", "service5"]
)
for service in group.services:
if service.host == 'service4':
if service.host == "service4":
assert len(service.ports) == 1
assert set(
(port.port_from, port.dest) for port in service.ports
) == set([(80, 888)])
if service.host == 'service5':
if service.host == "service5":
assert len(service.ports) == 1
assert set(
(port.port_from, port.dest) for port in service.ports
) == set([(81, 8080)])
if group.name == 'group4':
if group.name == "group4":
assert len(group.services) == 1
assert group.version == 3
assert group.onion_url == onions_urls[group.name]
assert set(
service.host for service in group.services
) == set(['group4'])
assert set(service.host for service in group.services) == set(
["group4"]
)
for service in group.services:
assert service.host == 'group4'
assert service.host == "group4"
assert len(service.ports) == 1
assert set(
(port.port_from, port.dest) for port in service.ports
) == set([(81, 'unix://unix2.sock')])
) == set([(81, "unix://unix2.sock")])
if group.name == 'service5':
if group.name == "service5":
assert len(group.services) == 1
assert group.version == 2
assert group.onion_url == onions_urls[group.name]
assert set(
service.host for service in group.services
) == set(['service5'])
assert set(service.host for service in group.services) == set(
["service5"]
)
for service in group.services:
assert service.host == 'service5'
assert service.host == "service5"
assert len(service.ports) == 1
assert set(
(port.port_from, port.dest) for port in service.ports
) == set([(80, 80)])
# bug with fakefs, test everything in the same function
env = {
"TOR_CONTROL_PORT": "172.0.1.0:7867",
"TOR_CONTROL_PASSWORD": "secret",
}
def mock_hash(self, password):
self.control_hashed_password = "myhashedpassword"
monkeypatch.setattr(os, "environ", env)
monkeypatch.setattr(Onions, "_hash_control_port_password", mock_hash)
onion = Onions()
onion._setup_control_port()
onion.apply_conf()
with open("/etc/tor/torrc", "r") as f:
torrc = f.read()
print(torrc)
assert "ControlPort 172.0.1.0:7867" in torrc
assert f"HashedControlPassword {onion.control_hashed_password}" in torrc
env = {
"TOR_CONTROL_PORT": "unix:/path/to.socket",
}
monkeypatch.setattr(os, "environ", env)
torrc_tpl = get_torrc_template()
onion = Onions()
onion._setup_control_port()
onion.apply_conf()
with open("/etc/tor/torrc", "r") as f:
torrc = f.read()
print(torrc)
assert "ControlPort unix:/path/to.socket" in torrc
def test_groups(monkeypatch):
env = {
'SERVICE1_SERVICE_NAME': 'group1',
'SERVICE2_SERVICE_NAME': 'group1',
'SERVICE3_SERVICE_NAME': 'group2',
'SERVICE1_PORTS': '80:80',
'SERVICE2_PORTS': '81:80,82:8000',
'SERVICE3_PORTS': '80:unix://unix.socket',
"SERVICE1_SERVICE_NAME": "group1",
"SERVICE2_SERVICE_NAME": "group1",
"SERVICE3_SERVICE_NAME": "group2",
"SERVICE1_PORTS": "80:80",
"SERVICE2_PORTS": "81:80,82:8000",
"SERVICE3_PORTS": "80:unix://unix.socket",
}
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
onion_match = r'^[a-z2-7]{16}.onion$'
onion_match = r"^[a-z2-7]{16}.onion$"
assert len(os.environ) == 6
assert len(onion.services) == 2
assert set(
group.name for group in onion.services
) == set(['group1', 'group2'])
assert set(group.name for group in onion.services) == set(
["group1", "group2"]
)
for group in onion.services:
if group.name == 'group1':
if group.name == "group1":
assert len(group.services) == 2
assert set(
service.host for service in group.services
) == set(['service1', 'service2'])
assert set(service.host for service in group.services) == set(
["service1", "service2"]
)
if group.name == 'group2':
if group.name == "group2":
assert len(group.services) == 1
assert set(
service.host for service in group.services
) == set(['service3'])
assert set(service.host for service in group.services) == set(
["service3"]
)
assert re.match(onion_match, group.onion_url)
def test_json(monkeypatch):
env = {
'SERVICE1_SERVICE_NAME': 'group1',
'SERVICE2_SERVICE_NAME': 'group1',
'SERVICE3_SERVICE_NAME': 'group2',
'SERVICE1_PORTS': '80:80',
'SERVICE2_PORTS': '81:80,82:8000',
'SERVICE3_PORTS': '80:unix://unix.socket',
"SERVICE1_SERVICE_NAME": "group1",
"SERVICE2_SERVICE_NAME": "group1",
"SERVICE3_SERVICE_NAME": "group2",
"SERVICE1_PORTS": "80:80",
"SERVICE2_PORTS": "81:80,82:8000",
"SERVICE3_PORTS": "80:unix://unix.socket",
}
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
@ -526,61 +582,188 @@ def test_json(monkeypatch):
jsn = json.loads(onion.to_json())
assert len(jsn) == 2
assert len(jsn['group1']) == 3
assert len(jsn['group2']) == 1
assert len(jsn["group1"]) == 3
assert len(jsn["group2"]) == 1
def test_output(monkeypatch):
env = {
'SERVICE1_SERVICE_NAME': 'group1',
'SERVICE2_SERVICE_NAME': 'group1',
'SERVICE3_SERVICE_NAME': 'group2',
'SERVICE1_PORTS': '80:80',
'SERVICE2_PORTS': '81:80,82:8000',
'SERVICE3_PORTS': '80:unix://unix.socket',
"SERVICE1_SERVICE_NAME": "group1",
"SERVICE2_SERVICE_NAME": "group1",
"SERVICE3_SERVICE_NAME": "group2",
"SERVICE1_PORTS": "80:80",
"SERVICE2_PORTS": "81:80,82:8000",
"SERVICE3_PORTS": "80:unix://unix.socket",
}
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
for item in ['group1', 'group2', '.onion', ',']:
for item in ["group1", "group2", ".onion", ","]:
assert item in str(onion)
def test_not_valid_share_port(monkeypatch):
env = {
'SERVICE1_SERVICE_NAME': 'group1',
'SERVICE2_SERVICE_NAME': 'group1',
'SERVICE3_SERVICE_NAME': 'group2',
'SERVICE1_PORTS': '80:80',
'SERVICE2_PORTS': '80:80,82:8000',
'SERVICE3_PORTS': '80:unix://unix.socket',
"SERVICE1_SERVICE_NAME": "group1",
"SERVICE2_SERVICE_NAME": "group1",
"SERVICE3_SERVICE_NAME": "group2",
"SERVICE1_PORTS": "80:80",
"SERVICE2_PORTS": "80:80,82:8000",
"SERVICE3_PORTS": "80:unix://unix.socket",
}
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
with pytest.raises(Exception) as excinfo:
onion.check_services()
assert 'Same port for multiple services' in str(excinfo.value)
assert "Same port for multiple services" in str(excinfo.value)
def test_not_valid_no_services(monkeypatch):
env = {
'SERVICE1_SERVICE_NAME': 'group1',
'SERVICE2_SERVICE_NAME': 'group1',
'SERVICE3_SERVICE_NAME': 'group2',
"SERVICE1_SERVICE_NAME": "group1",
"SERVICE2_SERVICE_NAME": "group1",
"SERVICE3_SERVICE_NAME": "group2",
}
monkeypatch.setattr(os, 'environ', env)
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
with pytest.raises(Exception) as excinfo:
onion.check_services()
assert 'has not ports set' in str(excinfo.value)
assert "has not ports set" in str(excinfo.value)
def get_vanguards_template():
return r"""
## Global options
[Global]
{% if env.get('TOR_CONTROL_PORT', '').startswith('unix:') %}
{% set _, unix_path = env['TOR_CONTROL_PORT'].split(':', 1) %}
{% elif ':' in env.get('TOR_CONTROL_PORT', '') %}
{% set host, port = env['TOR_CONTROL_PORT'].split(':', 1) %}
{% else %}
{% set host = env.get('TOR_CONTROL_PORT') %}
{% endif %}
control_ip = {{ host or '' }}
control_port = {{ port or 9051 }}
control_socket = {{ unix_path or '' }}
control_pass = {{ env.get('TOR_CONTROL_PASSWORD', '') }}
state_file = {{ env.get('VANGUARDS_STATE_FILE', '/run/tor/data/vanguards.state') }}
{% if 'VANGUARDS_EXTRA_OPTIONS' in env %}
{% set extra_conf = ConfigParser().read_string(env['VANGUARDS_EXTRA_OPTIONS']) %}
{% if 'Global' in extra_conf %}
{% for key, val in extra_conf['Global'].items() %}
{{key}} = {{val}}
{% endfor %}
{% set _ = extra_conf.pop('Global') %}
{% endif %}
{{ extra_conf.to_string() }}
{% endif %}
""".strip() # noqa
def test_vanguards_configuration_sock(fs, monkeypatch):
extra_options = """
[Global]
enable_cbtverify = True
loglevel = DEBUG
[Rendguard]
rend_use_max_use_to_bw_ratio = 4.0
""".strip()
env = {
"TOR_ENABLE_VANGUARDS": "true",
"TOR_CONTROL_PORT": "unix:/path/to/sock",
"VANGUARDS_EXTRA_OPTIONS": extra_options,
}
monkeypatch.setattr(os, "environ", env)
monkeypatch.setattr(os, "fchmod", lambda x, y: None)
torrc_tpl = get_vanguards_template()
fs.create_file("/var/local/tor/vanguards.conf.tpl", contents=torrc_tpl)
fs.create_file("/etc/tor/vanguards.conf")
onion = Onions()
onion.resolve_control_port()
onion._setup_vanguards()
onion._write_vanguards_conf()
vanguard_conf = configparser.ConfigParser()
with open("/etc/tor/vanguards.conf", "r") as f:
print(f.read())
vanguard_conf.read("/etc/tor/vanguards.conf")
assert vanguard_conf["Global"]
assert not vanguard_conf["Global"]["control_ip"]
assert vanguard_conf["Global"]["control_port"] == "9051"
assert vanguard_conf["Global"]["control_socket"] == "/path/to/sock"
assert not vanguard_conf["Global"]["control_pass"]
assert (
vanguard_conf["Global"]["state_file"]
== "/run/tor/data/vanguards.state"
)
assert vanguard_conf["Global"]["enable_cbtverify"]
assert vanguard_conf["Global"]["loglevel"] == "DEBUG"
assert vanguard_conf["Rendguard"]["rend_use_max_use_to_bw_ratio"] == "4.0"
def test_vanguards_configuration_ip(fs, monkeypatch):
env = {
"TOR_ENABLE_VANGUARDS": "true",
"TOR_CONTROL_PORT": "127.0.0.1:7864",
"TOR_CONTROL_PASSWORD": "secret",
}
monkeypatch.setattr(os, "environ", env)
monkeypatch.setattr(os, "fchmod", lambda x, y: None)
torrc_tpl = get_vanguards_template()
fs.create_file("/var/local/tor/vanguards.conf.tpl", contents=torrc_tpl)
fs.create_file("/etc/tor/vanguards.conf")
onion = Onions()
onion.resolve_control_port()
onion._setup_vanguards()
onion._write_vanguards_conf()
vanguard_conf = configparser.ConfigParser()
with open("/etc/tor/vanguards.conf", "r") as f:
print(f.read())
vanguard_conf.read("/etc/tor/vanguards.conf")
assert vanguard_conf["Global"]
assert vanguard_conf["Global"]["control_ip"] == "127.0.0.1"
assert vanguard_conf["Global"]["control_port"] == "7864"
assert not vanguard_conf["Global"]["control_socket"]
assert vanguard_conf["Global"]["control_pass"] == "secret"
assert (
vanguard_conf["Global"]["state_file"]
== "/run/tor/data/vanguards.state"
)

Loading…
Cancel
Save