From e075e900cf18316e375a1d961bd9310a04b1dd0e Mon Sep 17 00:00:00 2001 From: wander Date: Fri, 6 Feb 2026 22:06:44 -0500 Subject: [PATCH] stable 1.0.0 --- README.md | 231 ++++++++++------------------------------- docker-compose.yml | 14 +-- docker-compose.yml.bak | 39 +++++++ 3 files changed, 100 insertions(+), 184 deletions(-) create mode 100644 docker-compose.yml.bak diff --git a/README.md b/README.md index 2b1ad23..eca51ce 100644 --- a/README.md +++ b/README.md @@ -1,196 +1,77 @@ -# docker-tor-hidden-service +# Docker Tor Hidden Service (Modernized) -[![Build Status](https://travis-ci.org/cmehay/docker-tor-hidden-service.svg?branch=master)](https://travis-ci.org/cmehay/docker-tor-hidden-service) +A secure, lightweight, and modern Docker image for running Tor Hidden Services (Onion Services) with Vanguards protection. -## Changelog +## Features +* **Lightweight**: Built on `python:3.11-alpine` (latest stable). +* **Secure**: "Fail-fast" entrypoint script that validates all configuration before starting. +* **Vanguards Ready**: Includes [Vanguards](https://github.com/mikeperry-tor/vanguards) for active defense against deanonymization attacks. +* **No Magic**: dynamic configuration via standard `entrypoint.sh` — no opaque Python wrappers. +* **Multi-Arch**: Supports `amd64` and `arm64`. -* 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` +## Usage -* 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 - -From 2019, new conf to handle tor v3 address has been added. Here an example with `docker-compose` v2+: +### Quick Start (Docker Compose) ```yaml -version: "2" - +version: '3.8' services: tor: - image: goldy/tor-hidden-service:0.3.5.8 - links: - - hello - - world - - again + build: . environment: + # Format: ExternalPort:ContainerName:InternalPort + - HIDDEN_SERVICE_HOSTS=80:my-web-server:80 + - TOR_CONTROL_PASSWORD=secure_password + volumes: + - tor-data:/var/lib/tor/ + depends_on: + - web - # 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' - # tor v3 address private key base 64 encoded - SERVICE1_TOR_SERVICE_KEY: | - PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAACArobDQYyZAWXei4QZwr++ - j96H1X/gq14NwLRZ2O5DXuL0EzYKkdhZSILY85q+kfwZH8z4ceqe7u1F+0pQi/sM + # Example Web Server + web: + image: nginx:alpine + container_name: my-web-server - world: - image: tutum/hello-world - hostname: world + # Vanguards Sidecar (Optional but Recommended) + vanguards: + build: . + command: vanguards --control_ip tor-service --control_port 9051 --control_pass secure_password + volumes: + - tor-data:/var/lib/tor/ + depends_on: + - tor + restart: unless-stopped - hello: - image: tutum/hello-world - hostname: hello +volumes: + tor-data: ``` -This configuration will output: +### Environment Variables -``` -service1: xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:88, xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:8000 +| Variable | Description | Example | +| :--- | :--- | :--- | +| `HIDDEN_SERVICE_HOSTS` | Space-separated list of services to expose. Format: `ExtPort:Host:IntPort` | `80:web:80 22:ssh:22` | +| `TOR_CONTROL_PASSWORD` | Password for the Tor Control Port (9051). Automatically hashed. | `my_secret_password` | +| `TOR_DATA_DIR` | Location of Tor data (keys, state). Default: `/var/lib/tor` | `/var/lib/tor` | + +### Getting your Onion Address +Once running, the Tor service generates your keys automatically. + +```bash +docker exec cat /var/lib/tor/hidden_service/hostname ``` -`xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:88` will hit `again:80`. -`xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:8000` will hit `wold:80`. +### Checking Vanguards +Verify that Vanguards is connected and pinning your guards: - -#### Environment variables - -##### `{SERVICE}_TOR_SERVICE_HOSTS` - -The config patern for this variable is: `{exposed_port}:{hostname}:{port}}` - -For example `80:hello:8080` will expose an onion service on port 80 to the port 8080 of hello hostname. - -Unix sockets are supported too, `80:unix://path/to/socket.sock` will expose an onion service on port 80 to the socket `/path/to/socket.sock`. See `docker-compose.v2.socket.yml` for an example. - -You can concatenate services using comas. - -> **WARNING**: Using sockets and ports in the same service group can lead to issues - -##### `{SERVICE}_TOR_SERVICE_VERSION` - -Optionnal now, can only be `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` - - -##### `{SERVICE}_TOR_SERVICE_KEY` - -You can set the private key for the current service. - -Tor v3 addresses uses ed25519 binary keys. It should be base64 encoded: -``` -PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAACArobDQYyZAWXei4QZwr++j96H1X/gq14NwLRZ2O5DXuL0EzYKkdhZSILY85q+kfwZH8z4ceqe7u1F+0pQi/sM -``` -##### `TOR_SOCKS_PORT` - -Set tor sock5 proxy port for this tor instance. (Use this if you need to connect to tor network with your service) - -##### `TOR_EXTRA_OPTIONS` - -Add any options in the `torrc` file. - -```yaml -services: - tor: - environment: - # Add any option you need - TOR_EXTRA_OPTIONS: | - HiddenServiceNonAnonymousMode 1 - HiddenServiceSingleHopMode 1 +```bash +docker logs vanguards-sidecar +docker exec vanguards-sidecar cat /vanguards.state ``` +## Security Notes +* **User**: Tor runs as the `root` user in the container by default in this minimal setup, but drops privileges where possible. (Note: Production setups might refine this to use the `tor` user exclusively). +* **Filesystem**: The `entrypoint.sh` enforces `chmod 700` on the hidden service directory to satisfy Tor's security checks. -#### Secrets - -Secret key can be set through docker `secrets`, see `docker-compose.v3.yml` for example. - - -### Tools - -A command line tool `onions` is available in container to get `.onion` url when container is running. - -```sh -# Get services -$ docker exec -ti torhiddenproxy_tor_1 onions -hello: xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:80 -world: ootceq7skq7qpvvwf2tajeboxovalco7z3ka44vxbtfdr2tfvx5ld7ad.onion:80 - -# Get json -$ docker exec -ti torhiddenproxy_tor_1 onions --json -{"hello": ["xwjtp3mj427zdp4tljiiivg2l5ijfvmt5lcsfaygtpp6cw254kykvpyd.onion:80"], "world": ["ootceq7skq7qpvvwf2tajeboxovalco7z3ka44vxbtfdr2tfvx5ld7ad.onion:80"]} -``` - -### Auto reload - -Changing `/etc/tor/torrc` file triggers a `SIGHUP` signal to `tor` to reload configuration. - -To disable this behavior, add `ENTRYPOINT_DISABLE_RELOAD` in environment. - -### Versions - -Container version will follow tor release versions. - -### pyentrypoint - -This container uses [`pyentrypoint`](https://github.com/cmehay/pyentrypoint) to generate its setup. - -### pytor - -This containner uses [`pytor`](https://github.com/cmehay/pytor) to mannages tor cryptography, generate keys and compute onion urls. - -## Control port - -Use these environment variables to enable control port -* `TOR_CONTROL_PORT`: enable and set control port binding (`ip`, `ip:port` or `unix:/path/to/socket.sock`) (default port is 9051) -* `TOR_CONTROL_PASSWORD`: set control port password (in clear, not hashed) -* `TOR_DATA_DIRECTORY`: set data directory (default `/run/tor/data`) - -## Vanguards - -For critical hidden services, it's possible to increase security with [`Vanguards`](https://github.com/mikeperry-tor/vanguards) tool. - - -### Run in the same container - -Check out [`docker-compose.vanguards.yml`](docker-compose.vanguards.yml) for example. - -Add environment variable `TOR_ENABLE_VANGUARDS` to `true` to start `vanguards` daemon beside `tor` process. `Vanguards` logs will be displayed to stdout using `pyentrypoint` logging, if you need raw output, set `ENTRYPOINT_RAW` to `true` in environment. - -In this mode, if `vanguards` exits, sigint is sent to `tor` process to terminate it. If you want to disable this behavior, set `VANGUARD_KILL_TOR_ON_EXIT` to `false` in environment. - -### Run in separate containers -Check out[`docker-compose.vanguards-network.yml`](docker-compose.vanguards-network.yml) for an example of increased security setup using docker networks. - -#### settings - -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` +## Credits +Based on the original work by [cmehay](https://github.com/cmehay/docker-tor-hidden-service), but fully refactored to remove dependencies on `pyentrypoint`, `pytor`, and `onions` in favor of standard shell scripts and official binaries. diff --git a/docker-compose.yml b/docker-compose.yml index f071c6a..f1ced55 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: # Tor Service - Runs Tor with Strict Validation tor: @@ -9,32 +7,30 @@ services: restart: unless-stopped environment: # Format: ExternalPort:ContainerName:InternalPort - # Pointing to the new 'web' service below - HIDDEN_SERVICE_HOSTS=80:web:80 - TOR_CONTROL_PASSWORD=secure_password ports: - - "9051:9051" # Expose control port + - "9051:9051" + - "9050:9050" volumes: - tor-data:/var/lib/tor/ depends_on: - web - # Demo Web Service (So Tor has something to host) + # Demo Web Service web: image: nginx:alpine container_name: my-website restart: unless-stopped - # Vanguards Service - Runs Vanguards only (Sidecar) + # Vanguards Service - Sidecar vanguards: build: . image: docker-tor-hidden-service:latest container_name: vanguards-sidecar restart: unless-stopped + # The 'vanguards' first word triggers the logic in your entrypoint.sh command: vanguards --control_ip tor-service --control_port 9051 --control_pass secure_password - environment: - # Placeholder to ensure no tor starts here - - HIDDEN_SERVICE_HOSTS="" depends_on: - tor volumes: diff --git a/docker-compose.yml.bak b/docker-compose.yml.bak new file mode 100644 index 0000000..79f4413 --- /dev/null +++ b/docker-compose.yml.bak @@ -0,0 +1,39 @@ +services: + # Tor Service - Runs Tor with Strict Validation + tor: + build: . + image: docker-tor-hidden-service:latest + container_name: tor-service + restart: unless-stopped + environment: + # Format: ExternalPort:ContainerName:InternalPort + - HIDDEN_SERVICE_HOSTS=80:web:80 + - TOR_CONTROL_PASSWORD=secure_password + ports: + - "9051:9051" + volumes: + - tor-data:/var/lib/tor/ + depends_on: + - web + + # Demo Web Service + web: + image: nginx:alpine + container_name: my-website + restart: unless-stopped + + # Vanguards Service - Sidecar + vanguards: + build: . + image: docker-tor-hidden-service:latest + container_name: vanguards-sidecar + restart: unless-stopped + # The 'vanguards' first word triggers the logic in your entrypoint.sh + command: vanguards --control_ip tor-service --control_port 9051 --control_pass secure_password + depends_on: + - tor + volumes: + - tor-data:/var/lib/tor/ + +volumes: + tor-data: