Compare commits

..

No commits in common. "master" and "v0.4.6.7-d0dd287" have entirely different histories.

19 changed files with 1185 additions and 921 deletions

View file

@ -2,5 +2,3 @@ keys/
*.egg-info
.tox/
__cache__
__pycache__
*/__pycache__

View file

@ -1,4 +1,4 @@
FROM python:3.10-alpine
FROM python:3.8-alpine
# if omitted, the versions are determined from the git tags
ARG tor_version

View file

@ -34,6 +34,8 @@ rebuild:
docker-compose -f docker-compose.build.yml build --no-cache --pull
run: build
docker-compose -f docker-compose.v1.yml up --force-recreate
run-v2: build
docker-compose -f docker-compose.v2.yml up --force-recreate
run-v2-socket: build
@ -53,8 +55,3 @@ run-vanguards: build
run-vanguards-network: build
docker-compose -f docker-compose.vanguards-network.yml up --force-recreate
publish: build
docker tag goldy/tor-hidden-service:$(CUR_TAG) goldy/tor-hidden-service:latest
docker push goldy/tor-hidden-service:$(CUR_TAG)
docker push goldy/tor-hidden-service:latest

215
README.md
View file

@ -2,20 +2,6 @@
[![Build Status](https://travis-ci.org/cmehay/docker-tor-hidden-service.svg?branch=master)](https://travis-ci.org/cmehay/docker-tor-hidden-service)
## Changelog
* 26 jul 2022
* Update `onions` tool to v0.7.1:
* Fix an issue when restarting a container with control port enabled
* Updated to python 3.10
* Fix a typo in `docker-compose.vanguards-network.yml`, it works now
* Update `tor` to `0.4.7.8`
* 23 dec 2021
* Update `onions` tool to v0.7.0:
* Drop support of onion v2 adresses as tor network does not accept them anymore
* Update `tor` to `0.4.6.9`
## Setup
### Setup hosts
@ -33,34 +19,60 @@ services:
- world
- again
environment:
# Set mapping ports
SERVICE1_TOR_SERVICE_HOSTS: 80:hello:80,800:hello:80,8888:hello:80
# Set private key
SERVICE1_TOR_SERVICE_KEY: |
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
dnFnHEcsllSEqD1hPAAvMUWwSMJaNmBEFtl8DUMS9tPX5fWGX4w5Xx8dZwIDAQAB
AoGBAMb20jMHxaZHWg2qTRYYJa8LdHgS0BZxkWYefnBUbZn7dOz7mM+tddpX6raK
8OSqyQu3Tc1tB9GjPLtnVr9KfVwhUVM7YXC/wOZo+u72bv9+4OMrEK/R8xy30XWj
GePXEu95yArE4NucYphxBLWMMu2E4RodjyJpczsl0Lohcn4BAkEA+XPaEKnNA3AL
1DXRpSpaa0ukGUY/zM7HNUFMW3UP00nxNCpWLSBmrQ56Suy7iSy91oa6HWkDD/4C
k0HslnMW5wJBANdz4ehByMJZmJu/b5y8wnFSqep2jmJ1InMvd18BfVoBTQJwGMAr
+qwSwNXXK2YYl9VJmCPCfgN0o7h1AEzvdYECQAM5UxUqDKNBvHVmqKn4zShb1ugY
t1RfS8XNbT41WhoB96MT9P8qTwlniX8UZiwUrvNp1Ffy9n4raz8Z+APNwvsCQQC9
AuaOsReEmMFu8VTjNh2G+TQjgvqKmaQtVNjuOgpUKYv7tYehH3P7/T+62dcy7CRX
cwbLaFbQhUUUD2DCHdkBAkB6CbB+qhu67oE4nnBCXllI9EXktXgFyXv/cScNvM9Y
FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
-----END RSA PRIVATE KEY-----
# hello and again will share the same onion v3 address
SERVICE1_TOR_SERVICE_HOSTS: 88:hello:80,8000:world:80
# Optional as tor version 2 is not supported anymore
SERVICE1_TOR_SERVICE_VERSION: '3'
SERVICE2_TOR_SERVICE_HOSTS: 88:again:80,8000:world:80
SERVICE2_TOR_SERVICE_VERSION: '3'
# tor v3 address private key base 64 encoded
SERVICE1_TOR_SERVICE_KEY: |
SERVICE2_TOR_SERVICE_KEY: |
PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAACArobDQYyZAWXei4QZwr++
j96H1X/gq14NwLRZ2O5DXuL0EzYKkdhZSILY85q+kfwZH8z4ceqe7u1F+0pQi/sM
hello:
image: tutum/hello-world
hostname: hello
world:
image: tutum/hello-world
hostname: world
hello:
again:
image: tutum/hello-world
hostname: hello
hostname: again
```
This configuration will output:
```
service1: xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:88, xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:8000
service2: xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:88, xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:8000
service1: 5azvyr7dvvr4cldn.onion:80, 5azvyr7dvvr4cldn.onion:800, 5azvyr7dvvr4cldn.onion:8888
```
`xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:88` will hit `again:80`.
`xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:8000` will hit `wold:80`.
`5azvyr7dvvr4cldn.onion:80` will hit `hello:80`.
`5azvyr7dvvr4cldn.onion:800` will hit `hello:80` too.
`5azvyr7dvvr4cldn.onion:8888` will hit `hello:80` again.
#### Environment variables
@ -78,17 +90,34 @@ You can concatenate services using comas.
##### `{SERVICE}_TOR_SERVICE_VERSION`
Optionnal now, can only be `3`. Set the tor address type.
Can be `2` or `3`. Set the tor address type.
> **WARNING**: Version 2 is not supported anymore by tor network
`2` was giving short addresses `5azvyr7dvvr4cldn.onion` and `3` gives long addresses `xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion`
`2` gives short addresses `5azvyr7dvvr4cldn.onion` and `3` long addresses `xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion`
##### `{SERVICE}_TOR_SERVICE_KEY`
You can set the private key for the current service.
Tor v2 addresses uses RSA PEM keys like:
```
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
dnFnHEcsllSEqD1hPAAvMUWwSMJaNmBEFtl8DUMS9tPX5fWGX4w5Xx8dZwIDAQAB
AoGBAMb20jMHxaZHWg2qTRYYJa8LdHgS0BZxkWYefnBUbZn7dOz7mM+tddpX6raK
8OSqyQu3Tc1tB9GjPLtnVr9KfVwhUVM7YXC/wOZo+u72bv9+4OMrEK/R8xy30XWj
GePXEu95yArE4NucYphxBLWMMu2E4RodjyJpczsl0Lohcn4BAkEA+XPaEKnNA3AL
1DXRpSpaa0ukGUY/zM7HNUFMW3UP00nxNCpWLSBmrQ56Suy7iSy91oa6HWkDD/4C
k0HslnMW5wJBANdz4ehByMJZmJu/b5y8wnFSqep2jmJ1InMvd18BfVoBTQJwGMAr
+qwSwNXXK2YYl9VJmCPCfgN0o7h1AEzvdYECQAM5UxUqDKNBvHVmqKn4zShb1ugY
t1RfS8XNbT41WhoB96MT9P8qTwlniX8UZiwUrvNp1Ffy9n4raz8Z+APNwvsCQQC9
AuaOsReEmMFu8VTjNh2G+TQjgvqKmaQtVNjuOgpUKYv7tYehH3P7/T+62dcy7CRX
cwbLaFbQhUUUD2DCHdkBAkB6CbB+qhu67oE4nnBCXllI9EXktXgFyXv/cScNvM9Y
FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
-----END RSA PRIVATE KEY-----
```
Tor v3 addresses uses ed25519 binary keys. It should be base64 encoded:
```
PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAACArobDQYyZAWXei4QZwr++j96H1X/gq14NwLRZ2O5DXuL0EzYKkdhZSILY85q+kfwZH8z4ceqe7u1F+0pQi/sM
@ -124,12 +153,12 @@ A command line tool `onions` is available in container to get `.onion` url when
```sh
# Get services
$ docker exec -ti torhiddenproxy_tor_1 onions
hello: xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:80
world: ootceq7skq7qpvvwf2tajeboxovalco7z3ka44vxbtfdr2tfvx5ld7ad.onion:80
hello: vegm3d7q64gutl75.onion:80
world: b2sflntvdne63amj.onion:80
# Get json
$ docker exec -ti torhiddenproxy_tor_1 onions --json
{"hello": ["xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:80"], "world": ["ootceq7skq7qpvvwf2tajeboxovalco7z3ka44vxbtfdr2tfvx5ld7ad.onion:80"]}
{"hello": ["b2sflntvdne63amj.onion:80"], "world": ["vegm3d7q64gutl75.onion:80"]}
```
### Auto reload
@ -146,6 +175,8 @@ Container version will follow tor release versions.
This container uses [`pyentrypoint`](https://github.com/cmehay/pyentrypoint) to generate its setup.
If you need to use the legacy version, please checkout the `legacy` branch or pull `goldy/tor-hidden-service:legacy`.
### pytor
This containner uses [`pytor`](https://github.com/cmehay/pytor) to mannages tor cryptography, generate keys and compute onion urls.
@ -194,3 +225,131 @@ The following settings cannot me changer with this variable:
- 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.
### Create a tor hidden service with a link
```sh
# run a container with a network application
$ docker run -d --name hello_world tutum/hello-world
# and just link it to this container
$ docker run -ti --link hello_world goldy/tor-hidden-service
```
The .onion URLs are displayed to stdout at startup.
To keep onion keys, just mount volume `/var/lib/tor/hidden_service/`
```sh
$ docker run -ti --link something --volume /path/to/keys:/var/lib/tor/hidden_service/ goldy/tor-hidden-service
```
Look at the `docker-compose.yml` file to see how to use it.
### Set private key
Private key is settable by environment or by copying file in `hostname/private_key` in docker volume (`hostname` is the link name).
It's easier to pass key in environment with `docker-compose`.
```yaml
links:
- hello
- world
environment:
# Set private key
HELLO_KEY: |
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
dnFnHEcsllSEqD1hPAAvMUWwSMJaNmBEFtl8DUMS9tPX5fWGX4w5Xx8dZwIDAQAB
AoGBAMb20jMHxaZHWg2qTRYYJa8LdHgS0BZxkWYefnBUbZn7dOz7mM+tddpX6raK
8OSqyQu3Tc1tB9GjPLtnVr9KfVwhUVM7YXC/wOZo+u72bv9+4OMrEK/R8xy30XWj
GePXEu95yArE4NucYphxBLWMMu2E4RodjyJpczsl0Lohcn4BAkEA+XPaEKnNA3AL
1DXRpSpaa0ukGUY/zM7HNUFMW3UP00nxNCpWLSBmrQ56Suy7iSy91oa6HWkDD/4C
k0HslnMW5wJBANdz4ehByMJZmJu/b5y8wnFSqep2jmJ1InMvd18BfVoBTQJwGMAr
+qwSwNXXK2YYl9VJmCPCfgN0o7h1AEzvdYECQAM5UxUqDKNBvHVmqKn4zShb1ugY
t1RfS8XNbT41WhoB96MT9P8qTwlniX8UZiwUrvNp1Ffy9n4raz8Z+APNwvsCQQC9
AuaOsReEmMFu8VTjNh2G+TQjgvqKmaQtVNjuOgpUKYv7tYehH3P7/T+62dcy7CRX
cwbLaFbQhUUUD2DCHdkBAkB6CbB+qhu67oE4nnBCXllI9EXktXgFyXv/cScNvM9Y
FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
-----END RSA PRIVATE KEY-----
```
Options are set using the following pattern: `LINKNAME_KEY`
### Setup port
__Caution__: Using `PORT_MAP` with multiple ports on single service will cause `tor` to fail.
Use link setting in environment with the following pattern: `LINKNAME_PORTS`.
Like docker, first port is exposed port and the second one is service internal port.
```yaml
links:
- hello
- world
- hey
environment:
# Set mapping ports
HELLO_PORTS: 80:80
# Multiple ports can be coma separated
WORLD_PORTS: 8000:80,8888:80,22:22
# Socket mapping is supported
HEY_PORTS: 80:unix:/var/run/socket.sock
```
__DEPRECATED:__
By default, ports are the same as linked containers, but a default port can be mapped using `PORT_MAP` environment variable.
#### Socket
To increase security, it's possible to setup your service through socket between containers and turn off network in your app container. See `docker-compose.v2.sock.yml` for an example.
__Warning__: Due to a bug in `tor` configuration parser, it's not possible to mix network link and socket link in the same `tor` configuration.
### Group services
Multiple services can be hosted behind the same onion address.
```yaml
links:
- hello
- world
- hey
environment:
# Set mapping ports
HELLO_PORTS: 80:80
# Multiple ports can be coma separated
WORLD_PORTS: 8000:80,8888:80,22:22
# Socket mapping is supported
HEY_PORTS: 80:unix:/var/run/socket.sock
# hello and world will share the same onion address
# Service name can be any string as long there is not special char
HELLO_SERVICE_NAME: foo
WORLD_SERVICE_NAME: foo
```
__Warning__: Be carefull to not use the same exposed ports for grouped services.
### Compose v2 support
Links setting are required when using docker-compose v2. See `docker-compose.v2.yml` for example.
### Copose v3 support and secrets
Links setting are required when using docker-compose v3. See `docker-compose.v3.yml` for example.

View file

@ -1 +1 @@
0.4.7.12
0.4.6.7

21
docker-compose.v1.yml Normal file
View file

@ -0,0 +1,21 @@
# docker-compose.yml example
# LEGACY CONFIGURATION
# SEE README FOR INFORMATIONS
tor:
image: goldy/tor-hidden-service:$CUR_TAG
links:
- hello
- world
environment:
PORT_MAP: 80 # Map port to detected service
volumes:
- ./keys:/var/lib/tor/hidden_service/
hello:
image: tutum/hello-world
hostname: hello
world:
image: tutum/hello-world
hostname: world

View file

@ -0,0 +1,59 @@
# docker version 2 example
version: "2"
services:
tor:
image: goldy/tor-hidden-service:$CUR_TAG
links:
- hello
- world
- again
environment:
# Set mapping ports
HELLO_PORTS: 80:80,800:80,8888:80
# Set private key
HELLO_KEY: |
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
dnFnHEcsllSEqD1hPAAvMUWwSMJaNmBEFtl8DUMS9tPX5fWGX4w5Xx8dZwIDAQAB
AoGBAMb20jMHxaZHWg2qTRYYJa8LdHgS0BZxkWYefnBUbZn7dOz7mM+tddpX6raK
8OSqyQu3Tc1tB9GjPLtnVr9KfVwhUVM7YXC/wOZo+u72bv9+4OMrEK/R8xy30XWj
GePXEu95yArE4NucYphxBLWMMu2E4RodjyJpczsl0Lohcn4BAkEA+XPaEKnNA3AL
1DXRpSpaa0ukGUY/zM7HNUFMW3UP00nxNCpWLSBmrQ56Suy7iSy91oa6HWkDD/4C
k0HslnMW5wJBANdz4ehByMJZmJu/b5y8wnFSqep2jmJ1InMvd18BfVoBTQJwGMAr
+qwSwNXXK2YYl9VJmCPCfgN0o7h1AEzvdYECQAM5UxUqDKNBvHVmqKn4zShb1ugY
t1RfS8XNbT41WhoB96MT9P8qTwlniX8UZiwUrvNp1Ffy9n4raz8Z+APNwvsCQQC9
AuaOsReEmMFu8VTjNh2G+TQjgvqKmaQtVNjuOgpUKYv7tYehH3P7/T+62dcy7CRX
cwbLaFbQhUUUD2DCHdkBAkB6CbB+qhu67oE4nnBCXllI9EXktXgFyXv/cScNvM9Y
FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
-----END RSA PRIVATE KEY-----
WORLD_PORTS: 8000:80
AGAIN_PORTS: 88:80
# hello and again will share the same onion_adress
AGAIN_SERVICE_NAME: foo
HELLO_SERVICE_NAME: foo
# Keep keys in volumes
volumes:
- tor-keys:/var/lib/tor/hidden_service/
hello:
image: tutum/hello-world
hostname: hello
world:
image: tutum/hello-world
hostname: world
again:
image: tutum/hello-world
hostname: again
volumes:
tor-keys:
driver: local

View file

@ -10,31 +10,29 @@ services:
- world
- again
environment:
######################################################################
### TOR ADDRESSES VERSION 2 ARE NOT SUPPORTED ANYMORE ###
######################################################################
# # Set mapping ports
# HELLO_TOR_SERVICE_HOSTS: 80:hello:80,800:hello:80,8888:hello:80
# # Set private key
# HELLO_TOR_SERVICE_KEY: |
# -----BEGIN RSA PRIVATE KEY-----
# MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
# NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
# dnFnHEcsllSEqD1hPAAvMUWwSMJaNmBEFtl8DUMS9tPX5fWGX4w5Xx8dZwIDAQAB
# AoGBAMb20jMHxaZHWg2qTRYYJa8LdHgS0BZxkWYefnBUbZn7dOz7mM+tddpX6raK
# 8OSqyQu3Tc1tB9GjPLtnVr9KfVwhUVM7YXC/wOZo+u72bv9+4OMrEK/R8xy30XWj
# GePXEu95yArE4NucYphxBLWMMu2E4RodjyJpczsl0Lohcn4BAkEA+XPaEKnNA3AL
# 1DXRpSpaa0ukGUY/zM7HNUFMW3UP00nxNCpWLSBmrQ56Suy7iSy91oa6HWkDD/4C
# k0HslnMW5wJBANdz4ehByMJZmJu/b5y8wnFSqep2jmJ1InMvd18BfVoBTQJwGMAr
# +qwSwNXXK2YYl9VJmCPCfgN0o7h1AEzvdYECQAM5UxUqDKNBvHVmqKn4zShb1ugY
# t1RfS8XNbT41WhoB96MT9P8qTwlniX8UZiwUrvNp1Ffy9n4raz8Z+APNwvsCQQC9
# AuaOsReEmMFu8VTjNh2G+TQjgvqKmaQtVNjuOgpUKYv7tYehH3P7/T+62dcy7CRX
# cwbLaFbQhUUUD2DCHdkBAkB6CbB+qhu67oE4nnBCXllI9EXktXgFyXv/cScNvM9Y
# FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
# -----END RSA PRIVATE KEY-----
# Set mapping ports
HELLO_TOR_SERVICE_HOSTS: 80:hello:80,800:hello:80,8888:hello:80
# Set private key
HELLO_TOR_SERVICE_KEY: |
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
dnFnHEcsllSEqD1hPAAvMUWwSMJaNmBEFtl8DUMS9tPX5fWGX4w5Xx8dZwIDAQAB
AoGBAMb20jMHxaZHWg2qTRYYJa8LdHgS0BZxkWYefnBUbZn7dOz7mM+tddpX6raK
8OSqyQu3Tc1tB9GjPLtnVr9KfVwhUVM7YXC/wOZo+u72bv9+4OMrEK/R8xy30XWj
GePXEu95yArE4NucYphxBLWMMu2E4RodjyJpczsl0Lohcn4BAkEA+XPaEKnNA3AL
1DXRpSpaa0ukGUY/zM7HNUFMW3UP00nxNCpWLSBmrQ56Suy7iSy91oa6HWkDD/4C
k0HslnMW5wJBANdz4ehByMJZmJu/b5y8wnFSqep2jmJ1InMvd18BfVoBTQJwGMAr
+qwSwNXXK2YYl9VJmCPCfgN0o7h1AEzvdYECQAM5UxUqDKNBvHVmqKn4zShb1ugY
t1RfS8XNbT41WhoB96MT9P8qTwlniX8UZiwUrvNp1Ffy9n4raz8Z+APNwvsCQQC9
AuaOsReEmMFu8VTjNh2G+TQjgvqKmaQtVNjuOgpUKYv7tYehH3P7/T+62dcy7CRX
cwbLaFbQhUUUD2DCHdkBAkB6CbB+qhu67oE4nnBCXllI9EXktXgFyXv/cScNvM9Y
FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
-----END RSA PRIVATE KEY-----
# hello and again will share the same onion_adress
FOO_TOR_SERVICE_HOSTS: 88:again:80,8000:world:80
FOO_TOR_SERVICE_VERSION: '3'
# tor v3 address private key base 64 encoded
FOO_TOR_SERVICE_KEY: |
PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAABYZRzL3zScTEqA8/5wfvHw

View file

@ -12,10 +12,9 @@ services:
environment:
# Set version 3 on BAR group
BAR_TOR_SERVICE_HOSTS: '80:hello:80,88:world:80'
# This is now optional as v2 are not supported anymore by tor network
BAR_TOR_SERVICE_VERSION: '3'
# hello and again will share the same onion_adress
# hello and again will share the same v2 onion_adress
FOO_TOR_SERVICE_HOSTS: '88:again:80,80:hello:80,800:hello:80,8888:hello:80'
@ -50,6 +49,6 @@ volumes:
secrets:
foo:
file: ./private_key_foo_v3
file: ./private_key_foo_v2
bar:
file: ./private_key_bar_v3

View file

@ -12,10 +12,9 @@ services:
environment:
# Set version 3 on BAR group
BAR_TOR_SERVICE_HOSTS: '80:hello:80,88:world:80'
# This is now optional as v2 are not supported anymore by tor network
BAR_TOR_SERVICE_VERSION: '3'
# hello and again will share the same onion_adress
# hello and again will share the same v2 onion_adress
FOO_TOR_SERVICE_HOSTS: '88:again:80,80:hello:80,800:hello:80,8888:hello:80'
@ -46,6 +45,6 @@ volumes:
secrets:
foo:
file: ./private_key_foo_v3
file: ./private_key_foo_v2
bar:
file: ./private_key_bar_v3

View file

@ -8,7 +8,7 @@ services:
environment:
# Enable control port with ip binding (see networks configuration bellow)
# Using network interface instead of 0.0.0.0 help to protect control port from hidden services.
TOR_CONTROL_PORT: 172.16.111.10
TOR_CONTROL_PORT: 127.16.111.10
# Set controle port password (optionnal)
TOR_CONTROL_PASSWORD: something_secret
@ -54,7 +54,7 @@ services:
environment:
# Set tor hostname (or ip:port or unix:/path/to/socket.sock)
TOR_CONTROL_PORT: tor:9051
TOR_CONTROL_PORT: tor
# set password if needed
TOR_CONTROL_PASSWORD: something_secret

View file

@ -57,10 +57,9 @@ class Setup(object):
self.setup[host]['ports'][host].append(port)
def _hash_control_port_password(self, password):
self.control_hashed_password = subprocess.check_output(
['/usr/local/bin/tor', '--quiet', '--hash-password', password],
env={'HOME': '/tmp'}
).decode()
self.control_hashed_password = subprocess.check_output([
'tor', '--quiet', '--hash-password', password
]).decode()
def _parse_control_port_variable(self, check_ip=True):
control_port = os.environ['TOR_CONTROL_PORT']
@ -428,7 +427,7 @@ class Onions(Setup):
def setup_services():
for name, setup in self.torrc_dict.items():
version = setup.get('version', 3)
version = setup.get('version', 2)
group = (self.find_group_by_name(name)
or self.add_empty_group(name, version=version))
for service_dict in setup.get('services', []):

View file

@ -4,6 +4,7 @@ import os
import pathlib
import re
from pytor import OnionV2
from pytor import OnionV3
from pytor.onion import EmptyDirException
@ -13,7 +14,7 @@ class ServicesGroup(object):
name = None
version = None
imported_key = False
_default_version = 3
_default_version = 2
_onion = None
_hidden_service_dir = "/var/lib/tor/hidden_service/"
@ -26,6 +27,7 @@ class ServicesGroup(object):
name_regex = r'^[a-zA-Z0-9-_]+$'
self.onion_map = {
2: OnionV2,
3: OnionV3,
}

1578
poetry.lock generated

File diff suppressed because it is too large Load diff

15
private_key_foo_v2 Normal file
View file

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDR8TdQF9fDlGhy1SMgfhMBi9TaFeD12/FK27TZE/tYGhxXvs1C
NmFJy1hjVxspF5unmUsCk0yEsvEdcAdp17Vynz6W41VdinETU9yXHlUJ6NyI32AH
dnFnHEcsllSEqD1hPAAvMUWwSMJaNmBEFtl8DUMS9tPX5fWGX4w5Xx8dZwIDAQAB
AoGBAMb20jMHxaZHWg2qTRYYJa8LdHgS0BZxkWYefnBUbZn7dOz7mM+tddpX6raK
8OSqyQu3Tc1tB9GjPLtnVr9KfVwhUVM7YXC/wOZo+u72bv9+4OMrEK/R8xy30XWj
GePXEu95yArE4NucYphxBLWMMu2E4RodjyJpczsl0Lohcn4BAkEA+XPaEKnNA3AL
1DXRpSpaa0ukGUY/zM7HNUFMW3UP00nxNCpWLSBmrQ56Suy7iSy91oa6HWkDD/4C
k0HslnMW5wJBANdz4ehByMJZmJu/b5y8wnFSqep2jmJ1InMvd18BfVoBTQJwGMAr
+qwSwNXXK2YYl9VJmCPCfgN0o7h1AEzvdYECQAM5UxUqDKNBvHVmqKn4zShb1ugY
t1RfS8XNbT41WhoB96MT9P8qTwlniX8UZiwUrvNp1Ffy9n4raz8Z+APNwvsCQQC9
AuaOsReEmMFu8VTjNh2G+TQjgvqKmaQtVNjuOgpUKYv7tYehH3P7/T+62dcy7CRX
cwbLaFbQhUUUD2DCHdkBAkB6CbB+qhu67oE4nnBCXllI9EXktXgFyXv/cScNvM9Y
FDzzNAAfVc5Nmbmx28Nw+0w6pnpe/3m0Tudbq3nHdHfQ
-----END RSA PRIVATE KEY-----

Binary file not shown.

View file

@ -1,6 +1,6 @@
[tool.poetry]
name = "docker-tor-hidden-service"
version = "0.7.1"
version = "0.6.1"
description = "Display onion sites hosted"
authors = ["Christophe Mehay <cmehay@nospam.student.42.fr>"]
license = "WTFPL"
@ -23,24 +23,24 @@ packages = [
onions = "onions:main"
[tool.poetry.dependencies]
python = ">=3.10,<3.11"
Jinja2 = ">=2.10"
importlib_metadata = ">=1.6.0"
python = ">= 3.8, < 3.9"
pytor = "^0.1.5"
Jinja2 = "^2.10"
pyentrypoint = "^0.7.4"
importlib_metadata = "^1.6.0"
vanguards = "^0.3.1"
ipy = ">=1.00"
pytor = '^0.1.9'
pyentrypoint = "^0.8.0"
ipy = "^1.00"
[tool.poetry.dev-dependencies]
autopep8 = ">=1.5.2"
tox = ">=3.15.0"
cryptography = ">=3.2"
pylint = ">=2.5.2"
ptpython = ">=3.0.2"
black = ">=22.6.0"
pre-commit = "^2.20.0"
pytest = ">=5.4.2"
pyfakefs = ">=4.0.2"
autopep8 = "^1.5.2"
tox = "^3.15.0"
cryptography = "^3.2"
pylint = "^2.5.2"
ptpython = "^3.0.2"
black = "^19.10b0"
pre-commit = "^2.3.0"
pytest = "^5.4.2"
pyfakefs = "^4.0.2"
[build-system]
requires = ["poetry>=0.12"]

View file

@ -2,19 +2,49 @@ import configparser
import json
import os
import re
import pytest
from base64 import b32encode
from base64 import b64decode
from hashlib import sha1
import pytest
from Crypto.PublicKey import RSA
from onions import Onions
def get_key_and_onion(version=3):
def get_key_and_onion(version=2):
key = {}
key[
2
] = """
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCsMP4gl6g1Q313miPhb1GnDr56ZxIWGsO2PwHM1infkbhlBakR
6DGQfpE31L1ZKTUxY0OexKbW088v8qCOfjD9Zk1i80JP4xzfWQcwFZ5yM/0fkhm3
zLXqXdEahvRthmFsS8OWusRs/04U247ryTm4k5S0Ch5OTBuvMLzQ8W0yDwIDAQAB
AoGAAZr3U5B2ZgC6E7phKUHjbf5KMlPxrDkVqAZQWvuIKmhuYqq518vlYmZ7rhyS
o1kqAMrfH4TP1WLmJJlLe+ibRk2aonR4e0GbW4x151wcJdT1V3vdWAsVSzG3+dqX
PiGT//DIe0OPSH6ecI8ftFRLODd6f5iGkF4gsUSTcVzAFgkCQQDTY67dRpOD9Ozw
oYH48xe0B9NQCw7g4NSH85jPurJXnpn6lZ6bcl8x8ioAdgLyomR7fO/dJFYLw6uV
LZLqZsVbAkEA0Iei3QcpsJnYgcQG7l5I26Sq3LwoiGRDFKRI6k0e+en9JQJgA3Ay
tsLpyCHv9jQ762F6AVXFru5DmZX40F6AXQJBAIHoKac8Xx1h4FaEuo4WPkPZ50ey
dANIx/OAhTFrp3vnMPNpDV60K8JS8vLzkx4vJBcrkXDSirqSFhkIN9grLi8CQEO2
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
@ -200,6 +230,48 @@ ff02::2 ip6-allrouters
)
def test_key(monkeypatch):
key, onion_url = get_key_and_onion()
env = {"SERVICE1_KEY": key}
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
assert len(os.environ) == 1
assert len(onion.services) == 1
assert onion.services[0].onion_url == onion_url
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,
},
]
for env in envs:
monkeypatch.setattr(os, "environ", env)
onion = Onions()
onion._get_setup_from_env()
onion._load_keys_in_services()
assert len(os.environ) == len(env)
assert len(onion.services) == 1
assert onion.services[0].onion_url == onion_url
def test_key_v3(monkeypatch):
key, onion_url = get_key_and_onion(version=3)
@ -223,7 +295,7 @@ def test_key_v3(monkeypatch):
def test_key_in_secret(fs, monkeypatch):
env = {
# "GROUP1_TOR_SERVICE_HOSTS": "80:service1:80",
"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",
@ -231,21 +303,22 @@ def test_key_in_secret(fs, monkeypatch):
monkeypatch.setattr(os, "environ", env)
# key_v2, onion_url_v2 = get_key_and_onion()
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))
onion = Onions()
onion._get_setup_from_env()
onion._load_keys_in_services()
# group1 = onion.find_group_by_name("group1")
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 != onion_url_v3
assert group1.onion_url == onion_url_v2
assert group2.onion_url not in [onion_url_v2, onion_url_v3]
assert group3.onion_url == onion_url_v3
@ -262,6 +335,7 @@ HiddenServiceSingleHopMode 1
"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",
@ -310,7 +384,7 @@ HiddenServiceSingleHopMode 1
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") == 6
assert torrc.count("HiddenServiceVersion 3") == 2
assert "HiddenServiceNonAnonymousMode 1\n" in torrc
assert "HiddenServiceSingleHopMode 1\n" in torrc
assert "ControlPort" not in torrc
@ -330,7 +404,7 @@ HiddenServiceSingleHopMode 1
for group in onion2.services:
if group.name == "group1":
assert len(group.services) == 2
assert group.version == 3
assert group.version == 2
assert group.onion_url == onions_urls[group.name]
assert set(service.host for service in group.services) == set(
["service1", "service2"]
@ -348,7 +422,7 @@ HiddenServiceSingleHopMode 1
) == set([(81, 80), (82, 8000)])
if group.name == "group2":
assert len(group.services) == 1
assert group.version == 3
assert group.version == 2
assert group.onion_url == onions_urls[group.name]
assert set(service.host for service in group.services) == set(
["group2"]
@ -361,7 +435,7 @@ HiddenServiceSingleHopMode 1
if group.name in ["group3", "group3v3"]:
assert len(group.services) == 2
assert group.version == 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"]
@ -394,7 +468,7 @@ HiddenServiceSingleHopMode 1
if group.name == "service5":
assert len(group.services) == 1
assert group.version == 3
assert group.version == 2
assert group.onion_url == onions_urls[group.name]
assert set(service.host for service in group.services) == set(
["service5"]
@ -464,7 +538,7 @@ def test_groups(monkeypatch):
onion = Onions()
onion._get_setup_from_env()
onion_match = r"^[a-z2-7]{56}.onion$"
onion_match = r"^[a-z2-7]{16}.onion$"
assert len(os.environ) == 6
assert len(onion.services) == 2

View file

@ -1,6 +1,6 @@
[tox]
isolated_build = true
envlist = py310
envlist = py38
[testenv]
whitelist_externals = poetry