diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index c08818d..8f77240 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -78,7 +78,7 @@ jobs: else # Check all files in tools/ (no .sh extension) TOOL_COUNT=0 - for script in tools/status tools/health tools/fingerprint tools/bridge-line tools/gen-auth; do + for script in tools/status tools/health tools/fingerprint tools/bridge-line tools/gen-auth tools/gen-family; do if [ -f "$script" ]; then echo "πŸ“„ Checking $(basename "$script")..." sh -n "$script" || exit 1 @@ -115,7 +115,7 @@ jobs: if [ -d "tools" ]; then echo "" echo "πŸ” ShellCheck: tools/*" - for tool in tools/status tools/health tools/fingerprint tools/bridge-line tools/gen-auth; do + for tool in tools/status tools/health tools/fingerprint tools/bridge-line tools/gen-auth tools/gen-family; do if [ -f "$tool" ]; then echo " Checking $(basename $tool)..." shellcheck -S warning "$tool" || true @@ -168,8 +168,8 @@ jobs: if [ $HAS_SH_EXT -eq 1 ]; then echo "❌ Some tools have .sh extension (should not have it)" exit 1 - elif [ $NO_EXT_COUNT -lt 4 ]; then - echo "❌ Expected 5 tools (status, health, fingerprint, bridge-line, gen-auth)" + elif [ $NO_EXT_COUNT -lt 5 ]; then + echo "❌ Expected 6 tools (status, health, fingerprint, bridge-line, gen-auth, gen-family)" exit 1 else echo "βœ… All tools have correct format (no .sh extension)" @@ -335,7 +335,7 @@ jobs: docker run --rm --entrypoint /bin/sh tor-relay:test -c "ls -la /usr/local/bin/" || exit 1 echo "" echo "πŸ› οΈ Available diagnostic tools:" - docker run --rm --entrypoint /bin/sh tor-relay:test -c "ls -1 /usr/local/bin/status /usr/local/bin/health /usr/local/bin/fingerprint /usr/local/bin/bridge-line /usr/local/bin/gen-auth" || exit 1 + docker run --rm --entrypoint /bin/sh tor-relay:test -c "ls -1 /usr/local/bin/status /usr/local/bin/health /usr/local/bin/fingerprint /usr/local/bin/bridge-line /usr/local/bin/gen-auth /usr/local/bin/gen-family" || exit 1 - name: πŸ§… Verify Tor Installation run: | @@ -564,7 +564,7 @@ jobs: if: matrix.test-case == 'help-flags' run: | echo "πŸ§ͺ Testing tool existence..." - for tool in status health fingerprint bridge-line; do + for tool in status health fingerprint bridge-line gen-auth gen-family; do TOOL_PATH="/usr/local/bin/$tool" if docker run --rm --entrypoint /bin/sh tor-relay:test -c "test -f $TOOL_PATH"; then echo "βœ… $tool exists at $TOOL_PATH" @@ -579,7 +579,7 @@ jobs: run: | echo "πŸ” Verifying file permissions for tools..." docker run --rm --entrypoint /bin/sh tor-relay:test -c " - for tool in /usr/local/bin/status /usr/local/bin/health /usr/local/bin/fingerprint /usr/local/bin/bridge-line /usr/local/bin/gen-auth; do + for tool in /usr/local/bin/status /usr/local/bin/health /usr/local/bin/fingerprint /usr/local/bin/bridge-line /usr/local/bin/gen-auth /usr/local/bin/gen-family; do if [ -f \"\$tool\" ]; then test -x \"\$tool\" && echo \"βœ… \$(basename \$tool) is executable\" || exit 1 fi @@ -607,7 +607,7 @@ jobs: run: | echo "πŸ”§ Testing tool execution..." docker run --rm --entrypoint /bin/sh tor-relay:test -c " - for tool in /usr/local/bin/status /usr/local/bin/health /usr/local/bin/fingerprint /usr/local/bin/bridge-line /usr/local/bin/gen-auth; do + for tool in /usr/local/bin/status /usr/local/bin/health /usr/local/bin/fingerprint /usr/local/bin/bridge-line /usr/local/bin/gen-auth /usr/local/bin/gen-family; do if [ -f \"\$tool\" ]; then BASENAME=\$(basename \"\$tool\") echo \"πŸ” Testing \$BASENAME...\" @@ -653,7 +653,7 @@ jobs: - πŸ—οΈ Docker image build (multi-arch ready) - πŸš€ Container smoke test - πŸ§… Tor installation verification - - πŸ”§ Tool availability check (status, health, fingerprint, bridge-line, gen-auth) + - πŸ”§ Tool availability check (status, health, fingerprint, bridge-line, gen-auth, gen-family) - πŸ” Permission verification - πŸ›‘οΈ Security scanning with Trivy - πŸ§ͺ Test matrix execution diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f31e28..306d203 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,11 +16,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [1.1.7] - 2026-03-02 + +### πŸŽ‰ Happy Family Support (Tor 0.4.9+) + +This release introduces full support for Tor's new **Happy Family** system (`FamilyId`), which replaces the legacy `MyFamily` fingerprint-exchange workflow. Relay operators can now link all their relays into a family using a single cryptographic key instead of manually listing every fingerprint on every relay. + +### ✨ Features + +- **New Tool: `gen-family`**: Generate or view Tor Happy Family keys inside the container. Supports `gen-family ` (generate), `gen-family --show` (view existing), `gen-family --force` (overwrite without backup), and `gen-family --help`. +- **`FamilyId` ENV Support**: New `TOR_FAMILY_ID` environment variable to set the `FamilyId` directive in generated torrc (guard/middle/exit modes). +- **`MyFamily` ENV Support**: New `TOR_MY_FAMILY` environment variable (comma-separated fingerprints) for backward compatibility with the legacy `MyFamily` directive. +- **Family Key Detection**: Phase 2 of the entrypoint now scans `/var/lib/tor/keys/*.secret_family_key` and logs detected keys at startup. +- **Import Workflow**: Operators can import existing family keys from bare-metal Tor installations via `docker cp` + ownership fix (`chown 100:101`). + +### βš™οΈ Changed + +- **Entrypoint** (`docker-entrypoint.sh`): Phase 2 now detects family keys; config generation for guard/middle and exit modes appends `FamilyId` and `MyFamily` lines when the corresponding ENV vars are set. +- **Dockerfiles** (`Dockerfile`, `Dockerfile.edge`): Added `COPY` and `chmod +x` for the new `gen-family` tool. +- **`status` Tool** (`tools/status`): Now displays family key count and Happy Family configuration status after the fingerprint section. +- **Tool Count**: Increased from 5 to **6** diagnostic tools (status, health, fingerprint, bridge-line, gen-auth, **gen-family**). + +### πŸ“š Documentation + +- **README.md**: Added comprehensive "Happy Family (Tor 0.4.9+)" section with Option A (generate new key) and Option B (import existing key), persistence safety table, updated tools table (6 tools), updated features list, added gen-family to flowchart diagram, and added troubleshooting entries. +- **docs/ARCHITECTURE.md**: Updated all mermaid diagrams - container lifecycle, Phase 2, config generation (guard + exit), diagnostic tools subgraph, directory structure. Updated tool characteristics table, references table, and bumped doc version to 1.1.0. +- **docs/TOOLS.md**: Added full `gen-family` documentation section with usage, output examples, exit codes, and "Set Up Happy Family" workflow. Updated count from 5 β†’ 6 tools and FAQ. +- **docs/DEPLOYMENT.md**: Updated diagnostic tool count references (5 β†’ 6) across 3 locations. +- **docs/MIGRATION.md**: Added `gen-family --show` to post-migration diagnostic checklist. +- **docs/MIGRATION-V1.1.X.md**: Added `gen-family` to diagnostic tool verification checklist. +- **Example Configs**: Added commented `FamilyId` and `MyFamily` placeholders to `relay-guard.conf`, `relay-exit.conf`, and `relay-bridge.conf`. +- **Docker Compose Templates**: Added `TOR_FAMILY_ID` and `TOR_MY_FAMILY` env vars to guard, exit, and multi-relay templates with setup instructions (Option A/B). +- **Directory Authority Voting**: Added explanation of how Tor's 9 directory authorities vote on relay flags (Guard, Stable, Fast, HSDir) and that at least 5 of 9 must agree in consensus, across README, FAQ, DEPLOYMENT, and MULTI-MODE docs. +- **CIISS v2 ContactInfo**: Added documentation for the [ContactInfo Information Sharing Specification v2](https://nusenu.github.io/ContactInfo-Information-Sharing-Specification/) with field reference table, generator link, and `proof:uri-rsa` verification explanation. Updated all `TOR_CONTACT_INFO` examples to use CIISS v2 format. + +### πŸ” CI/CD + +- **validate.yml**: Added `gen-family` to shell lint, ShellCheck, tool extension verification (threshold 5 β†’ 6), integration tool checks, help-flags test, file-permissions test, and tool-executability test. Updated build summary. +- **scripts/utilities/security-validation-tests.sh**: Added `gen-family` to tool security checks and syntax validation loops. +- **scripts/utilities/quick-test.sh**: Added Test 4.5 for `gen-family --help` executability. Updated summary line. + +### πŸ›‘οΈ Security + +- **SECURITY.md**: Updated supported versions table (1.1.7 active, 1.1.6 maintenance). Added `gen-family` to diagnostic tools list. + +> **BREAKING CHANGES:** None. The `TOR_FAMILY_ID` and `TOR_MY_FAMILY` environment variables are entirely optional. Existing deployments continue to work without changes. + +--- + ## [1.1.6] - 2026-02-08 ### πŸ› Fixed * **Bind Mount Ownership:** Added startup detection for bind-mounted data/keys directories with incorrect ownership. The entrypoint now warns users with actionable `chown` commands when volumes are not writable by the `tor` user (UID 100, GID 101). -* **DEBUG Flag:** Made the `DEBUG` environment variable case-insensitive β€” now accepts `true`, `TRUE`, `1`, `yes`, `YES`. +* **DEBUG Flag:** Made the `DEBUG` environment variable case-insensitive - now accepts `true`, `TRUE`, `1`, `yes`, `YES`. * **Documentation Typo:** Fixed incorrect `chown 1000:1000` β†’ `chown 100:101` in bridge migration troubleshooting guide. ### πŸ›‘οΈ Security @@ -455,7 +503,7 @@ BREAKING CHANGES: None ## πŸ“Š Release Information * **πŸŽ‰ First Release:** v1.0.0 (November 1, 2025) -* **πŸ“¦ Current Stable:** v1.1.6 (February 8, 2026) +* **πŸ“¦ Current Stable:** v1.1.7 (March 2, 2026) * **πŸ”— Latest Release:** [GitHub Releases](https://github.com/r3bo0tbx1/tor-guard-relay/releases/latest) * **🐳 Docker Images:** @@ -468,14 +516,15 @@ BREAKING CHANGES: None | Version | Status | Support Level | | --------- | --------------------- | ------------------------------------------- | -| **1.1.6** | 🟒 πŸ›‘οΈ **Active** | Full support (current stable) | -| **1.1.5** | 🟑 πŸ”§ **Maintenance** | Security + critical fixes only | +| **1.1.7** | 🟒 πŸ›‘οΈ **Active** | Full support (current stable) | +| **1.1.6** | 🟑 πŸ”§ **Maintenance** | Security + critical fixes only | | **< 1.1.5** | πŸ”΄ ❌ **Deprecated** | Removed - contains CVE-2025-15467 (OpenSSL CVSS 9.8). Upgrade immediately. | --- ## πŸ”— Release Links +[1.1.7]: https://github.com/r3bo0tbx1/tor-guard-relay/releases/tag/v1.1.7 [1.1.6]: https://github.com/r3bo0tbx1/tor-guard-relay/releases/tag/v1.1.6 [1.1.5]: https://github.com/r3bo0tbx1/tor-guard-relay/releases/tag/v1.1.5 [1.1.4]: https://github.com/r3bo0tbx1/tor-guard-relay/releases/tag/v1.1.4 diff --git a/Dockerfile b/Dockerfile index 3ea35f3..db5a566 100644 --- a/Dockerfile +++ b/Dockerfile @@ -60,6 +60,7 @@ COPY tools/health /usr/local/bin/health COPY tools/fingerprint /usr/local/bin/fingerprint COPY tools/bridge-line /usr/local/bin/bridge-line COPY tools/gen-auth /usr/local/bin/gen-auth +COPY tools/gen-family /usr/local/bin/gen-family RUN set -eux \ && chmod +x /usr/local/bin/docker-entrypoint.sh \ @@ -69,6 +70,7 @@ RUN set -eux \ /usr/local/bin/fingerprint \ /usr/local/bin/bridge-line \ /usr/local/bin/gen-auth \ + /usr/local/bin/gen-family \ && echo "🧩 Registered diagnostic tools:" \ && ls -lh /usr/local/bin/status /usr/local/bin/health /usr/local/bin/fingerprint /usr/local/bin/bridge-line diff --git a/Dockerfile.edge b/Dockerfile.edge index 4e102fc..d2d14ae 100644 --- a/Dockerfile.edge +++ b/Dockerfile.edge @@ -60,6 +60,7 @@ COPY tools/health /usr/local/bin/health COPY tools/fingerprint /usr/local/bin/fingerprint COPY tools/bridge-line /usr/local/bin/bridge-line COPY tools/gen-auth /usr/local/bin/gen-auth +COPY tools/gen-family /usr/local/bin/gen-family RUN set -eux \ && chmod +x /usr/local/bin/docker-entrypoint.sh \ @@ -69,6 +70,7 @@ RUN set -eux \ /usr/local/bin/fingerprint \ /usr/local/bin/bridge-line \ /usr/local/bin/gen-auth \ + /usr/local/bin/gen-family \ && echo "🧩 Registered diagnostic tools:" \ && ls -lh /usr/local/bin/status /usr/local/bin/health /usr/local/bin/fingerprint /usr/local/bin/bridge-line diff --git a/README.md b/README.md index 3850a77..a6a061d 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ - πŸ›‘οΈ **Security-First** - Hardened Alpine Linux, non-root operation, and minimized port exposure - πŸͺΆ **Very light** - Ultra-minimal 16.8 MB image - 🎯 **Simple** - One command to deploy, minimal configuration needed -- πŸ“Š **Observable** - 5 busybox-only diagnostic tools with JSON health API +- πŸ“Š **Observable** - 6 busybox-only diagnostic tools with JSON health API - πŸŒ‰ **Multi-Mode** - Supports guard, exit, and bridge (obfs4) relays - πŸ”„ **Automated** - Weekly security rebuilds, CI/CD ready - πŸ“š **Documented** - Comprehensive guides for deployment, monitoring, backup, and more @@ -157,11 +157,11 @@ We offer **two build variants** to match your risk tolerance and requirements: ```bash # Pull from Docker Hub (easiest) docker pull r3bo0tbx1/onion-relay:latest -docker pull r3bo0tbx1/onion-relay:1.1.6 +docker pull r3bo0tbx1/onion-relay:1.1.7 # Pull from GHCR docker pull ghcr.io/r3bo0tbx1/onion-relay:latest -docker pull ghcr.io/r3bo0tbx1/onion-relay:1.1.6 +docker pull ghcr.io/r3bo0tbx1/onion-relay:1.1.7 ``` ### Edge Variant (Testing Only) @@ -180,7 +180,7 @@ docker pull r3bo0tbx1/onion-relay:edge # Pull from GHCR docker pull ghcr.io/r3bo0tbx1/onion-relay:edge -docker pull ghcr.io/r3bo0tbx1/onion-relay:1.1.6-edge +docker pull ghcr.io/r3bo0tbx1/onion-relay:1.1.7-edge ``` **When to use edge:** @@ -230,7 +230,7 @@ See [Deployment Guide](docs/DEPLOYMENT.md) for complete instructions. ## πŸ”§ Diagnostic Tools -Five busybox-only diagnostic tools are included (since v1.1.1). +Six busybox-only diagnostic tools are included. | Tool | Purpose | Usage | |------|---------|--------| @@ -239,6 +239,7 @@ Five busybox-only diagnostic tools are included (since v1.1.1). | fingerprint | Show fingerprint | `docker exec tor-relay fingerprint` | | bridge-line | obfs4 line | `docker exec tor-relay bridge-line` | | gen-auth | Credentials for Nyx | `docker exec tor-relay gen-auth` | +| gen-family | Happy Family key gen | `docker exec tor-relay gen-family MyRelays` | ```bash # Full health report with emojis @@ -263,7 +264,7 @@ Example JSON: } ``` -> πŸ“– **Complete reference:** See [Tools Documentation](docs/TOOLS.md) for all 5 tools with examples, JSON schema, and integration guides. +> πŸ“– **Complete reference:** See [Tools Documentation](docs/TOOLS.md) for all 6 tools with examples, JSON schema, and integration guides. --- @@ -340,10 +341,11 @@ STATUS=$(echo "$HEALTH" | jq -r '.status') - βœ… Graceful shutdown with cleanup ### Operations & Automation -- βœ… **5 busybox-only diagnostic tools** (status, health, fingerprint, bridge-line, gen-auth) +- βœ… **6 busybox-only diagnostic tools** (status, health, fingerprint, bridge-line, gen-auth, gen-family) - βœ… **JSON health API** for monitoring integration - βœ… **Multi-mode support** (guard, exit, bridge with obfs4) -- βœ… **ENV-based config** (TOR_RELAY_MODE, TOR_NICKNAME, etc.) +- βœ… **Happy Family support** (Tor 0.4.9+ key-based relay families) +- βœ… **ENV-based config** (TOR_RELAY_MODE, TOR_NICKNAME, TOR_FAMILY_ID, etc.) - βœ… **Multi-architecture** builds (AMD64, ARM64) - βœ… **Weekly security rebuilds** via GitHub Actions - βœ… **Docker Compose templates** for single/multi-relay @@ -383,7 +385,7 @@ STATUS=$(echo "$HEALTH" | jq -r '.status') ### Technical Reference - **[Architecture](docs/ARCHITECTURE.md)** - ⭐ **NEW!** Technical architecture with Mermaid diagrams -- **[Tools Reference](docs/TOOLS.md)** - ✨ **UPDATED!** Complete guide to all 5 diagnostic tools +- **[Tools Reference](docs/TOOLS.md)** - ✨ **UPDATED!** Complete guide to all 6 diagnostic tools - **[Monitoring Guide](docs/MONITORING.md)** - ✨ **UPDATED!** External monitoring integration, JSON health API, alerts, and observability - **[Control Port Guide](docs/CONTROL-PORT.md)** - ⭐ **NEW!** Authentication setup and Nyx integration - **[Backup Guide](docs/BACKUP.md)** - Data persistence, recovery, and disaster planning @@ -409,7 +411,7 @@ STATUS=$(echo "$HEALTH" | jq -r '.status') ```ini Nickname MyTorRelay -ContactInfo your-email@example.com +ContactInfo email:your-email[]example.com url:https://example.com proof:uri-rsa ciissversion:2 ORPort 9001 ORPort [::]:9001 DirPort 0 @@ -419,6 +421,8 @@ DataDirectory /var/lib/tor Log notice file /var/log/tor/notices.log ``` +> πŸ“ **ContactInfo format:** We recommend the [ContactInfo Information Sharing Specification (CIISS) v2](https://nusenu.github.io/ContactInfo-Information-Sharing-Specification/), a machine-readable format that replaces `@` with `[]` and includes structured fields like `email:`, `url:`, `proof:`, `pgp:`, `hoster:`, and more. Use the [CIISS Generator](https://torcontactinfogenerator.netlify.app/) to create yours. + ### Production Configuration ```ini @@ -438,6 +442,109 @@ Examples are found in the [`examples/`](examples/) directory for complete, annot > πŸ“– **Configuration help:** See [Deployment Guide](docs/DEPLOYMENT.md#configuration) for complete reference. +### Happy Family (Tor 0.4.9+) + +Tor 0.4.9 introduces **Happy Families**, a cryptographic key-based replacement for `MyFamily`. Instead of listing every relay fingerprint in every relay's config, all relays in a family share one secret key. + +**Why upgrade?** +- Eliminates huge `MyFamily` lists that waste bandwidth and memory +- Simpler to maintain - one key file instead of NΓ—N fingerprint entries +- Required for future Arti Relay compatibility + +#### Option A: Generate a new family key in Docker + +Use this if you don't already have a family key from another setup. + +```bash +# 1. Generate a family key (run on any ONE relay container) +docker exec tor-relay gen-family MyRelays + +# 2. Note the FamilyId output - you need it for your torrc +# FamilyId + +# 3. Copy the key to all your other relay containers +docker cp tor-relay:/var/lib/tor/keys/MyRelays.secret_family_key . +docker cp MyRelays.secret_family_key other-relay:/var/lib/tor/keys/ + +# 4. Fix ownership and permissions inside the target container +docker exec -u 0 other-relay chown 100:101 /var/lib/tor/keys/MyRelays.secret_family_key +docker exec -u 0 other-relay chmod 600 /var/lib/tor/keys/MyRelays.secret_family_key + +# 5. Add FamilyId to each relay's torrc, then restart +docker restart tor-relay other-relay +``` + +#### Option B: Import an existing family key into Docker + +Use this if you already generated a family key on a bare-metal or source-built Tor relay and want to use the same key for your Docker relays. + +```bash +# 1. Transfer the .secret_family_key file to your Docker host +# (via scp, sftp, or any secure method) +scp user@source-server:/var/lib/tor/keys/MyRelays.secret_family_key ~/tor-keys/ + +# 2. Copy the key into each running container (no restart needed yet) +docker cp ~/tor-keys/MyRelays.secret_family_key tor-relay:/var/lib/tor/keys/ + +# 3. Fix ownership and permissions inside the container +# The tor user in the container runs as UID 100, GID 101 +docker exec -u 0 tor-relay chown 100:101 /var/lib/tor/keys/MyRelays.secret_family_key +docker exec -u 0 tor-relay chmod 600 /var/lib/tor/keys/MyRelays.secret_family_key + +# 4. Verify the key is in place +docker exec tor-relay ls -la /var/lib/tor/keys/MyRelays.secret_family_key + +# 5. Add the FamilyId line to your torrc (same value from your source server) +# FamilyId +# Keep your existing MyFamily lines during the transition period + +# 6. Restart the container to pick up the config change +docker restart tor-relay +``` + +Repeat steps 2-6 for each container that should be in the family. + +> **This is safe for running containers.** `docker cp` writes directly into the named Docker volume. Your relay identity keys, family key, and all data persist in the volume across container restarts, image updates, and `docker compose up --force-recreate`. Volumes are **only** deleted if you explicitly run `docker volume rm` or `docker compose down -v`. + +#### Torrc configuration + +During the transition period, configure **both** `FamilyId` and `MyFamily` in your torrc: + +```ini +# Happy Family (Tor 0.4.9+) +FamilyId wweKJrJxUDs1EdtFFHCDtvVgTKftOC/crUl1mYJv830 + +# MyFamily (legacy - keep during transition) +MyFamily 9A2B5C7D8E1F3A4B6C8D0E2F4A6B8C0D2E4F6A8B +MyFamily 1F3E5D7C9B0A2F4E6D8C0B2A4F6E8D0C2B4A6F8E +``` + +The Tor Project will announce when `MyFamily` can be removed. + +#### ENV-based config (alternative to mounted torrc) + +```yaml +environment: + TOR_FAMILY_ID: "wweKJrJxUDs1EdtFFHCDtvVgTKftOC/crUl1mYJv830" + TOR_MY_FAMILY: "FINGERPRINT1,FINGERPRINT2,FINGERPRINT3" +``` + +#### Key persistence + +The `.secret_family_key` file lives in `/var/lib/tor/keys/` inside your data volume. It persists across container restarts and image updates automatically. + +| Scenario | Identity preserved? | Family key preserved? | +|----------|:---:|:---:| +| `docker restart` | βœ… | βœ… | +| `docker compose up --force-recreate` | βœ… | βœ… | +| `docker compose down` then `up` | βœ… | βœ… | +| `docker compose down -v` | ❌ | ❌ | +| `docker volume rm ` | ❌ | ❌ | + +> ⚠️ **Treat the `.secret_family_key` like a private key.** Anyone with this file can claim their relay belongs to your family. Back it up securely - losing it means regenerating for all relays. + +> πŸ“– **Official docs:** [Tor Happy Family Guide](https://community.torproject.org/relay/setup/post-install/family-ids/) + --- ## πŸ” Monitoring Your Relay @@ -475,6 +582,8 @@ Search by: | First Statistics | 24-48 hours | Bandwidth graphs appear | | Guard Flag | 8+ days | Trusted for entry connections | +> πŸ—³οΈ **How relay flags work:** Tor has **9 Directory Authorities** that vote every hour on relay flags (Guard, Stable, Fast, HSDir, etc.). A relay only receives a flag when **at least 5 of 9** authorities agree in the consensus. This is why flags take time - your relay must prove itself to a majority of independent authorities. + > πŸ“– **Detailed monitoring:** See [Monitoring Guide](docs/MONITORING.md) for complete observability setup with Prometheus and Grafana. --- @@ -498,6 +607,10 @@ docker exec tor-relay bridge-line # Generate Control Port hash docker exec tor-relay gen-auth + +# Generate/view Happy Family key +docker exec tor-relay gen-family MyRelays +docker exec tor-relay gen-family --show ``` ### Common Issues @@ -520,7 +633,7 @@ If you use **host bind mounts** (e.g. `-v /my/path:/var/lib/tor`) instead of nam [warn] Failed to parse/validate config: Couldn't access private data directory "/var/lib/tor//keys" ``` -**Fix β€” set correct ownership on the host:** +**Fix - set correct ownership on the host:** ```bash chown -R 100:101 /path/to/your/tor-data chown -R 100:101 /path/to/your/tor-keys # if mounted separately @@ -537,7 +650,7 @@ chown -R 100:101 /path/to/your/tor-keys # if mounted separately > πŸ“ **NEW:** See the complete [Architecture Documentation](docs/ARCHITECTURE.md) for detailed technical design with Mermaid diagrams covering: > - Container lifecycle and initialization flow (6 phases) > - ENV compatibility layer and configuration priority -> - Config generation for guard/exit/bridge modes +> - Config generation for guard/exit/bridge modes with Happy Family support > - OBFS4V security validation > - Diagnostic tools architecture > - Signal handling and graceful shutdown @@ -627,6 +740,10 @@ flowchart TB ━━━━━━━━━━ Generate Control Port Auth Data"] + Tools --> GenFamily["πŸ‘¨β€πŸ‘©β€πŸ‘§ gen-family + ━━━━━━━━━━ + Happy Family Key + Generation & Import"] end Running -->|docker stop SIGTERM| Shutdown @@ -659,6 +776,7 @@ flowchart TB style Finger fill:#4DD0E1,stroke:#0097A7,stroke-width:2px,color:#000 style BLine fill:#4DD0E1,stroke:#0097A7,stroke-width:2px,color:#000 style GenAuth fill:#4DD0E1,stroke:#0097A7,stroke-width:2px,color:#000 + style GenFamily fill:#4DD0E1,stroke:#0097A7,stroke-width:2px,color:#000 style Graceful fill:#FFB74D,stroke:#F57C00,stroke-width:2px,color:#000 style End fill:#E57373,stroke:#C62828,stroke-width:2px,color:#fff @@ -766,7 +884,7 @@ See [`examples/`](examples/) directory for relay configurations. βœ… Store `relay.conf` with restricted permissions (`chmod 600`) βœ… Never commit configs with sensitive info to Git -βœ… Use PGP key in ContactInfo for verification +βœ… Use [CIISS v2](https://nusenu.github.io/ContactInfo-Information-Sharing-Specification/) format in ContactInfo for verification βœ… Regularly update Docker image for security patches βœ… Monitor logs for suspicious activity βœ… Configure firewall properly @@ -782,14 +900,14 @@ Images are automatically rebuilt on separate schedules to include security patch **Stable Variant** (`:latest`) - **Schedule:** Every Sunday at 18:30 UTC - **Includes:** Latest Tor + Alpine 3.23.3 updates -- **Strategy:** Overwrites last release version (e.g., `:1.1.6`) with updated packages -- **Tags Updated:** `:latest` and version tags (e.g., `:1.1.6`) +- **Strategy:** Overwrites last release version (e.g., `:1.1.7`) with updated packages +- **Tags Updated:** `:latest` and version tags (e.g., `:1.1.7`) **Edge Variant** (`:edge`) - **Schedule:** Every 3 days at 12:00 UTC (independent schedule) - **Includes:** Latest Tor + Alpine edge (bleeding-edge) updates -- **Strategy:** Overwrites last release version (e.g., `:1.1.6-edge`) with updated packages -- **Tags Updated:** `:edge` and version tags (e.g., `:1.1.6-edge`) +- **Strategy:** Overwrites last release version (e.g., `:1.1.7-edge`) with updated packages +- **Tags Updated:** `:edge` and version tags (e.g., `:1.1.7-edge`) - **Frequency:** ~2-3x more frequent updates than stable All images auto-published to Docker Hub and GitHub Container Registry @@ -824,7 +942,7 @@ All images auto-published to Docker Hub and GitHub Container Registry ![GitHub Repo stars](https://img.shields.io/github/stars/r3bo0tbx1/tor-guard-relay?style=for-the-badge) ![GitHub Issues](https://img.shields.io/github/issues/r3bo0tbx1/tor-guard-relay?style=for-the-badge) -**Current Version:** v1.1.6 β€’ **Status:** Production Ready +**Current Version:** v1.1.7 β€’ **Status:** Production Ready **Image Size:** 16.8 MB β€’ **Retention:** Last 7 Releases **Registries:** Docker Hub β€’ GHCR @@ -904,4 +1022,4 @@ Or via **[AnonPay](https://trocador.app/anonpay?ticker_to=xmr&network_to=Mainnet πŸ“š [Documentation](docs/README.md) ⬆ [Back to top](#readme-top) - \ No newline at end of file + diff --git a/SECURITY.md b/SECURITY.md index fa4f013..ac420f4 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -14,9 +14,9 @@ We actively support the following versions with security updates: | Version | Status | Support Level | | --------- | --------------------- | ------------------------------------------- | -| **1.1.6** | 🟒 πŸ›‘οΈ **Active** | Full support (current stable) | -| **1.1.5** | 🟑 πŸ”§ **Maintenance** | Security + critical fixes only | -| **< 1.1.5** | πŸ”΄ ❌ **Deprecated** | Removed β€” contains CVE-2025-15467 (OpenSSL CVSS 9.8). Upgrade immediately. | +| **1.1.7** | 🟒 πŸ›‘οΈ **Active** | Full support (current stable) | +| **1.1.6** | 🟑 πŸ”§ **Maintenance** | Security + critical fixes only | +| **< 1.1.5** | πŸ”΄ ❌ **Deprecated** | Removed - contains CVE-2025-15467 (OpenSSL CVSS 9.8). Upgrade immediately. | --- @@ -74,6 +74,7 @@ docker exec tor-relay health # JSON health output docker exec tor-relay fingerprint # Display fingerprint docker exec tor-relay bridge-line # Get bridge line (bridge mode) docker exec tor-relay gen-auth # Generate Control Port hash +docker exec tor-relay gen-family # Generate/view Happy Family key (Tor 0.4.9+) ``` ### Network Architecture @@ -324,13 +325,15 @@ chown root:root /path/to/relay.conf #### Contact Information ```conf -# Use a dedicated email for relay operations -ContactInfo tor-relay@example.com <0xPGP_FINGERPRINT> +# CIISS v2 format (recommended) - generate at https://torcontactinfogenerator.netlify.app/ +ContactInfo email:tor-relay[]example.com url:https://example.com proof:uri-rsa pgp:EF6E286DDA85EA2A4BA7DE684E2C6E8793298290 ciissversion:2 -# Optionally include abuse contact -ContactInfo your-email proof:uri-rsa abuse:abuse@example.com +# With abuse contact (recommended for exits) +ContactInfo email:tor-relay[]example.com abuse:abuse[]example.com url:https://example.com proof:uri-rsa ciissversion:2 ``` +> πŸ“ **CIISS v2:** The [ContactInfo Information Sharing Specification](https://nusenu.github.io/ContactInfo-Information-Sharing-Specification/) provides a machine-readable, verifiable format. The `proof:uri-rsa` method lets tools verify your relay ownership by checking `https://your-domain/.well-known/tor-relay/rsa-fingerprint.txt` for your relay's fingerprint. + #### Network Security ```bash @@ -658,4 +661,4 @@ Security researchers who responsibly disclose vulnerabilities will be listed her --- -*Last Updated: 2026-02-08 | Version: 1.1.6* +*Last Updated: 2026-03-02 | Version: 1.1.7* diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index d688bec..d61f752 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -50,7 +50,7 @@ cleanup_and_exit() { startup_banner() { log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - log "πŸ§… Tor Guard Relay v1.1.6 - Initialization" + log "πŸ§… Tor Guard Relay v1.1.7 - Initialization" log "https://github.com/r3bo0tbx1/tor-guard-relay" log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log "" @@ -90,10 +90,24 @@ phase_2_permissions() { if [ -d "$TOR_DATA_DIR/keys" ] && [ ! -w "$TOR_DATA_DIR/keys" ]; then warn "Keys directory $TOR_DATA_DIR/keys has wrong ownership!" KEYS_OWNER=$(stat -c '%u:%g' "$TOR_DATA_DIR/keys" 2>/dev/null || echo "unknown") - warn " Current owner: $KEYS_OWNER β€” Expected: $CURRENT_UID:$CURRENT_GID" + warn " Current owner: $KEYS_OWNER - Expected: $CURRENT_UID:$CURRENT_GID" warn " Fix on the host: chown -R $CURRENT_UID:$CURRENT_GID " fi + # Check for Happy Family key files + FAMILY_KEY_COUNT=0 + if [ -d "$TOR_DATA_DIR/keys" ]; then + for fk in "$TOR_DATA_DIR/keys"/*.secret_family_key; do + [ -f "$fk" ] || continue + FAMILY_KEY_COUNT=$((FAMILY_KEY_COUNT + 1)) + FK_NAME=$(basename "$fk" .secret_family_key) + info "Found Happy Family key: $FK_NAME" + done + fi + if [ "$FAMILY_KEY_COUNT" -gt 0 ]; then + success "$FAMILY_KEY_COUNT family key(s) detected in keys directory" + fi + success "Permissions configured securely" log "" } @@ -218,6 +232,19 @@ BridgeRelay 0 EOF [ -n "${TOR_BANDWIDTH_RATE:-}" ] && echo "RelayBandwidthRate ${TOR_BANDWIDTH_RATE}" >> "$TOR_CONFIG" [ -n "${TOR_BANDWIDTH_BURST:-}" ] && echo "RelayBandwidthBurst ${TOR_BANDWIDTH_BURST}" >> "$TOR_CONFIG" + + # Happy Family (Tor 0.4.9+) + [ -n "${TOR_FAMILY_ID:-}" ] && echo "" >> "$TOR_CONFIG" && echo "# Happy Family (Tor 0.4.9+)" >> "$TOR_CONFIG" && echo "FamilyId ${TOR_FAMILY_ID}" >> "$TOR_CONFIG" + + # MyFamily (legacy, keep during transition) + if [ -n "${TOR_MY_FAMILY:-}" ]; then + echo "" >> "$TOR_CONFIG" + echo "# MyFamily (legacy - keep during transition to Happy Family)" >> "$TOR_CONFIG" + echo "$TOR_MY_FAMILY" | tr ',' '\n' | while IFS= read -r fp; do + fp=$(printf "%s" "$fp" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + [ -n "$fp" ] && echo "MyFamily $fp" >> "$TOR_CONFIG" + done + fi ;; exit) @@ -234,6 +261,19 @@ ${TOR_EXIT_POLICY:-ExitPolicy reject *:*} EOF [ -n "${TOR_BANDWIDTH_RATE:-}" ] && echo "RelayBandwidthRate ${TOR_BANDWIDTH_RATE}" >> "$TOR_CONFIG" [ -n "${TOR_BANDWIDTH_BURST:-}" ] && echo "RelayBandwidthBurst ${TOR_BANDWIDTH_BURST}" >> "$TOR_CONFIG" + + # Happy Family (Tor 0.4.9+) + [ -n "${TOR_FAMILY_ID:-}" ] && echo "" >> "$TOR_CONFIG" && echo "# Happy Family (Tor 0.4.9+)" >> "$TOR_CONFIG" && echo "FamilyId ${TOR_FAMILY_ID}" >> "$TOR_CONFIG" + + # MyFamily (legacy, keep during transition) + if [ -n "${TOR_MY_FAMILY:-}" ]; then + echo "" >> "$TOR_CONFIG" + echo "# MyFamily (legacy - keep during transition to Happy Family)" >> "$TOR_CONFIG" + echo "$TOR_MY_FAMILY" | tr ',' '\n' | while IFS= read -r fp; do + fp=$(printf "%s" "$fp" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') + [ -n "$fp" ] && echo "MyFamily $fp" >> "$TOR_CONFIG" + done + fi ;; bridge) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 4f3eba4..9336c91 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -58,12 +58,14 @@ flowchart TD DiagTools -->|fingerprint| FingerprintTool[πŸ†” tools/fingerprint] DiagTools -->|bridge-line| BridgeTool[πŸŒ‰ tools/bridge-line] DiagTools -->|gen-auth| GenAuthTool[πŸ”‘ tools/gen-auth] + DiagTools -->|gen-family| GenFamilyTool[πŸ‘¨β€πŸ‘©β€πŸ‘§ tools/gen-family] StatusTool --> Running HealthTool --> Running FingerprintTool --> Running BridgeTool --> Running GenAuthTool --> Running + GenFamilyTool --> Running Trap --> StopTail[🧽 Kill tail -F PID] StopTail --> StopTor[πŸ“¨ Send SIGTERM to Tor] @@ -94,6 +96,7 @@ flowchart TD subgraph P2["πŸ” Phase 2: Permission Hardening"] P2_1[πŸ”’ chmod 700 data dir] --> P2_2[πŸ“ chmod 755 log dir] + P2_2 --> P2_3[πŸ‘¨β€πŸ‘©β€πŸ‘§ Detect family keys] end subgraph P3["βš™οΈ Phase 3: Configuration Setup"] @@ -136,7 +139,7 @@ flowchart TD | Phase | Purpose | Key Operations | Error Handling | |-------|---------|----------------|----------------| | **1** | Directory Setup | `mkdir -p` data/log/run, show disk space | Fail if mkdir fails | -| **2** | Permissions | `chmod 700` data, `chmod 755` log | Warn on failure (read-only mount) | +| **2** | Permissions | `chmod 700` data, `chmod 755` log, detect family keys | Warn on failure (read-only mount) | | **3** | Configuration | Priority: mounted > ENV > error | Die if no config source | | **4** | Validation | `tor --verify-config` syntax check | Die if invalid config | | **5** | Build Info | Show version/arch/mode/source | Warn if missing | @@ -351,8 +354,14 @@ flowchart TD G4 -->|Not set| G6 G5 --> G6{TOR_BANDWIDTH_BURST?} G6 -->|Set| G7[Add RelayBandwidthBurst] - G6 -->|Not set| GuardDone - G7 --> GuardDone([Guard Config Done]) + G6 -->|Not set| G8 + G7 --> G8{TOR_FAMILY_ID?} + G8 -->|Set| G9[Add FamilyId] + G8 -->|Not set| G10 + G9 --> G10{TOR_MY_FAMILY?} + G10 -->|Set| G11[Add MyFamily entries] + G10 -->|Not set| GuardDone + G11 --> GuardDone([πŸ›‘οΈ Guard Config Done]) end subgraph ExitConfig["πŸšͺ Exit Config (lines 260-273)"] @@ -364,8 +373,14 @@ flowchart TD E5 -->|Not set| E7 E6 --> E7{TOR_BANDWIDTH_BURST?} E7 -->|Set| E8[Add RelayBandwidthBurst] - E7 -->|Not set| ExitDone - E8 --> ExitDone([Exit Config Done]) + E7 -->|Not set| E9 + E8 --> E9{TOR_FAMILY_ID?} + E9 -->|Set| E10[Add FamilyId] + E9 -->|Not set| E11 + E10 --> E11{TOR_MY_FAMILY?} + E11 -->|Set| E12[Add MyFamily entries] + E11 -->|Not set| ExitDone + E12 --> ExitDone([πŸšͺ Exit Config Done]) end subgraph BridgeConfig["πŸŒ‰ Bridge Config (lines 276-343)"] @@ -402,6 +417,7 @@ flowchart TD ``` **Base Config Includes:** Nickname, ContactInfo, ORPort, SocksPort 0, DataDirectory, Logging +**Family Config (guard/exit):** Optional FamilyId (Tor 0.4.9+) and MyFamily (legacy, comma-separated fingerprints via TOR_MY_FAMILY) **Code Reference:** `docker-entrypoint.sh` lines 222-350 (generate_config_from_env) @@ -456,7 +472,7 @@ flowchart TD style Enable fill:#e3f2fd ``` -**Security Features (fixed in v1.1.1, improved through v1.1.6):** +**Security Features (fixed in v1.1.1, improved through v1.1.7):** - **Newline detection:** `wc -l` instead of busybox-incompatible `grep -qE '[\x00\n\r]'` - **Control char detection:** `tr -d '[ -~]'` removes printable chars, leaves control chars - **Whitelist enforcement:** Only known-safe torrc options allowed @@ -468,7 +484,7 @@ flowchart TD ## Diagnostic Tools -Five busybox-only diagnostic tools provide observability: +Six busybox-only diagnostic tools provide observability: ```mermaid flowchart TD @@ -478,6 +494,7 @@ flowchart TD Choice -->|health| HealthFlow Choice -->|fingerprint| FingerprintFlow Choice -->|bridge-line| BridgeFlow + Choice -->|gen-family| FamilyFlow subgraph StatusFlow["πŸ“Š tools/status - Full Health Report"] S1[πŸ” Check Tor process running] --> S2[πŸ“ˆ Read bootstrap %] @@ -518,10 +535,25 @@ flowchart TD FingerprintFlow --> Output3([🟒 Fingerprint + URL]) BridgeFlow --> Output4([🟒 Bridge line or error]) + subgraph FamilyFlow["πŸ‘¨β€πŸ‘©β€πŸ‘§ tools/gen-family - Happy Family Management"] + FM1{Which action?} + FM1 -->|gen-family Name| FM2[πŸ”‘ Check Tor version] + FM2 --> FM3{Key already exists?} + FM3 -->|Yes| FM4[⚠️ Warn: key exists] + FM3 -->|No| FM5[πŸ” tor --keygen-family Name] + FM5 --> FM6[πŸ“€ Output FamilyId + instructions] + FM1 -->|gen-family --show| FM7[πŸ” Scan keys dir for .secret_family_key] + FM7 --> FM8[πŸ“ Show FamilyId from torrc] + FM8 --> FM9[ℹ️ Show MyFamily status] + end + + FamilyFlow --> Output5([🟒 Key + FamilyId or status]) + style Output1 fill:#b2fab4 style Output2 fill:#b2fab4 style Output3 fill:#b2fab4 style Output4 fill:#b2fab4 + style Output5 fill:#b2fab4 ``` **JSON Output Fields:** status, pid, uptime, bootstrap, reachable, errors, fingerprint, nickname @@ -535,6 +567,7 @@ flowchart TD | **fingerprint** | Relay identity | Text + URL | busybox: cat, awk | | **bridge-line** | Bridge sharing | obfs4 bridge line | busybox: grep, sed, awk, wget | | **gen-auth** | Credential generation | Text (Pass + Hash) | busybox: head, tr, tor | +| **gen-family** | Happy Family key mgmt | Text (Key + FamilyId) | busybox: tor --keygen-family, grep, basename | **All tools:** - Use `#!/bin/sh` (POSIX sh, not bash) @@ -576,11 +609,13 @@ graph TD Lib["πŸ“ /var/lib"] TorData["πŸ“¦ /var/lib/tor VOLUME"] Keys["πŸ”‘ keys/"] + FamilyKey["πŸ‘¨β€πŸ‘©β€πŸ‘§ *.secret_family_key"] FingerprintFile["πŸ†” fingerprint"] PTState["πŸŒ€ pt_state/"] Lib --> TorData TorData --> Keys + Keys --> FamilyKey TorData --> FingerprintFile TorData --> PTState end @@ -620,6 +655,7 @@ graph TD Fingerprint["🧬 fingerprint"] BridgeLine["πŸŒ‰ bridge-line"] GenAuth["πŸ”‘ gen-auth"] + GenFamily["πŸ‘¨β€πŸ‘©β€πŸ‘§ gen-family"] UsrLocal --> Bin Bin --> Entrypoint @@ -628,6 +664,8 @@ graph TD Bin --> Health Bin --> Fingerprint Bin --> BridgeLine + Bin --> GenAuth + Bin --> GenFamily end Usr --> UsrLocal @@ -661,7 +699,7 @@ graph TD class TorData,TorLog volumeStyle class TorRC configStyle - class Entrypoint,Healthcheck,Status,Health,Fingerprint,BridgeLine scriptStyle + class Entrypoint,Healthcheck,Status,Health,Fingerprint,BridgeLine,GenAuth,GenFamily scriptStyle class TorBin,Lyrebird,Tini binaryStyle class TorPID runtimeStyle class TorRCSample deletedStyle @@ -831,7 +869,7 @@ flowchart LR ``` **Weekly Rebuild Strategy:** -- Rebuilds use the **same version tag** as the last release (e.g., `1.1.6`) +- Rebuilds use the **same version tag** as the last release (e.g., `1.1.7`) - Overwrites existing image with fresh Alpine packages (security updates) - No `-weekly` suffix needed - just updated packages - `:latest` always points to most recent release version @@ -902,6 +940,7 @@ flowchart TD | `tools/fingerprint` | Show relay identity | ~50 | | `tools/bridge-line` | Generate bridge line | ~80 | | `tools/gen-auth` | Generate Control Port auth | ~30 | +| `tools/gen-family` | Happy Family key management | ~180 | ### External Documentation @@ -913,6 +952,6 @@ flowchart TD ---
-**Document Version:** 1.0.5 β€’ **Last Updated:** 2026-02-08 β€’ **Container Version:** v1.1.6 +**Document Version:** 1.1.0 β€’ **Last Updated:** 2026-03-02 β€’ **Container Version:** v1.1.7
\ No newline at end of file diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index 06be864..2c49053 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -54,7 +54,7 @@ nano relay-guard.conf **Minimum required edits:** - `Nickname` - Your relay name -- `ContactInfo` - Your email +- `ContactInfo` - Your contact info ([CIISS v2](https://nusenu.github.io/ContactInfo-Information-Sharing-Specification/) format recommended) - `ORPort` - Usually 9001 or 443 - `RelayBandwidthRate` - Your bandwidth limit @@ -91,7 +91,7 @@ docker ps | grep tor-relay # Check logs and bootstrap progress docker logs -f tor-relay -# Run diagnostics (5 tools available) +# Run diagnostics (6 tools available) docker exec tor-relay status # Full health report with emojis docker exec tor-relay health # JSON health data docker exec tor-relay fingerprint # Show fingerprint + Tor Metrics URL @@ -128,7 +128,7 @@ nano relay.conf Edit at minimum: - `Nickname` -- `ContactInfo` +- `ContactInfo` ([CIISS v2](https://nusenu.github.io/ContactInfo-Information-Sharing-Specification/) format recommended) - `RelayBandwidthRate` ### Step 4: Deploy @@ -194,7 +194,7 @@ Paste your relay configuration (see [example config](../examples/relay-guard.con **Important**: Edit at minimum: - `Nickname` - Your relay name -- `ContactInfo` - Your email +- `ContactInfo` - Your contact info ([CIISS v2](https://nusenu.github.io/ContactInfo-Information-Sharing-Specification/) format recommended) - `RelayBandwidthRate` - Your bandwidth limit Save and set permissions: @@ -347,7 +347,7 @@ docker run -d \ --network host \ -e TOR_RELAY_MODE=guard \ -e TOR_NICKNAME=MyGuardRelay \ - -e TOR_CONTACT_INFO=tor@example.com \ + -e TOR_CONTACT_INFO="email:tor[]example.com ciissversion:2" \ -e TOR_ORPORT=9001 \ -v tor-data:/var/lib/tor \ r3bo0tbx1/onion-relay:latest @@ -370,7 +370,7 @@ docker run -d \ --network host \ -e TOR_RELAY_MODE=exit \ -e TOR_NICKNAME=MyExitRelay \ - -e TOR_CONTACT_INFO=tor@example.com \ + -e TOR_CONTACT_INFO="email:tor[]example.com ciissversion:2" \ -e TOR_ORPORT=9001 \ -e TOR_EXIT_POLICY="accept *:80,accept *:443,reject *:*" \ -v tor-data:/var/lib/tor \ @@ -394,7 +394,7 @@ docker run -d \ --network host \ -e TOR_RELAY_MODE=bridge \ -e TOR_NICKNAME=MyBridge \ - -e TOR_CONTACT_INFO=tor@example.com \ + -e TOR_CONTACT_INFO="email:tor[]example.com ciissversion:2" \ -e TOR_ORPORT=9001 \ -e TOR_OBFS4_PORT=9002 \ -v tor-data:/var/lib/tor \ @@ -420,7 +420,7 @@ Full configuration via environment variables is supported (no config file needed #### Core Configuration - `TOR_RELAY_MODE` - guard, exit, or bridge (default: guard) - `TOR_NICKNAME` - Relay nickname (required for ENV config) -- `TOR_CONTACT_INFO` - Contact email (required for ENV config) +- `TOR_CONTACT_INFO` - Contact info ([CIISS v2](https://nusenu.github.io/ContactInfo-Information-Sharing-Specification/) format recommended, required for ENV config) - `TOR_ORPORT` - ORPort (default: 9001) - `TOR_DIRPORT` - DirPort for guard/exit (default: 0 - disabled) - `TOR_OBFS4_PORT` - obfs4 port for bridge mode (default: 9002) @@ -453,7 +453,7 @@ services: environment: TOR_RELAY_MODE: guard TOR_NICKNAME: MyRelay - TOR_CONTACT_INFO: tor@example.com + TOR_CONTACT_INFO: "email:tor[]example.com ciissversion:2" TOR_ORPORT: 9001 TOR_BANDWIDTH_RATE: 50 MBytes TOR_BANDWIDTH_BURST: 100 MBytes @@ -510,7 +510,7 @@ abc123def456 r3bo0tbx1/onion-relay:latest Up 5 minutes (healthy) ### 2. Run Diagnostics -The image provides **5 diagnostic tools**: +The image provides **6 diagnostic tools**: ```bash # Full health report with emojis @@ -562,6 +562,8 @@ docker exec tor-relay health - **24-48 hours**: Full statistics available - **8+ days**: Eligible for Guard flag (guard relays only) +> πŸ—³οΈ **How flags are assigned:** Tor's **9 Directory Authorities** vote every hour on relay flags (Guard, Stable, Fast, HSDir, etc.). Your relay only receives a flag when **at least 5 of 9** authorities reach consensus. New relays start as unmeasured middle relays and earn flags over time as authorities observe stable uptime and sufficient bandwidth. + Search for your relay: - **Clearnet**: https://metrics.torproject.org/rs.html - **Tor Browser**: http://hctxrvjzfpvmzh2jllqhgvvkoepxb4kfzdjm6h7egcwlumggtktiftid.onion/rs.html @@ -964,7 +966,7 @@ After successful deployment: ## Support - πŸ“– [Main README](../README.md) -- πŸ”§ [Tools Documentation](TOOLS.md) - Complete guide to the 5 diagnostic tools +- πŸ”§ [Tools Documentation](TOOLS.md) - Complete guide to the 6 diagnostic tools - πŸ“Š [Monitoring Guide](MONITORING.md) - External monitoring integration - πŸ› [Report Issues](https://github.com/r3bo0tbx1/tor-guard-relay/issues) - πŸ’¬ [Tor Project Forum](https://forum.torproject.net/) diff --git a/docs/FAQ.md b/docs/FAQ.md index 2157cd9..8d72444 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -32,7 +32,7 @@ Built on Alpine Linux 3.23.0 with a minimal 20MB image size, busybox-only tools, |---------|--------------|-----------------| | **Image size** | ~16.8 MB | ~100+ MB | | **Base** | Alpine 3.23.0 | Debian | -| **Diagnostics** | 5 busybox tools + JSON API | None | +| **Diagnostics** | 6 busybox tools + JSON API | None | | **Multi-mode** | Guard/Exit/Bridge in one image | Separate images | | **Weekly rebuilds** | βœ… Automated | ❌ Manual | | **ENV configuration** | βœ… Full support | Limited | @@ -72,7 +72,7 @@ docker run -d \ --network host \ -e TOR_RELAY_MODE=guard \ -e TOR_NICKNAME=MyGuardRelay \ - -e TOR_CONTACT_INFO="admin@example.com" \ + -e TOR_CONTACT_INFO="email:admin[]example.com ciissversion:2" \ -e TOR_ORPORT=9001 \ -e TOR_DIRPORT=9030 \ -v tor-data:/var/lib/tor \ @@ -89,6 +89,37 @@ docker run -d \ ghcr.io/r3bo0tbx1/onion-relay:latest ``` +### What is the ContactInfo Information Sharing Specification (CIISS)? + +The [CIISS v2](https://nusenu.github.io/ContactInfo-Information-Sharing-Specification/) is a machine-readable format for the Tor relay `ContactInfo` field. Instead of a plain email, it uses structured `key:value` pairs that tools can parse and verify automatically. + +**Format:** +``` +email:your-email[]example.com url:https://example.com proof:uri-rsa ciissversion:2 +``` + +**Key fields:** +| Field | Purpose | Example | +|-------|---------|---------| +| `email:` | Contact email (`@` β†’ `[]`) | `email:tor[]example.com` | +| `url:` | Operator website | `url:https://example.com` | +| `proof:` | URL ownership verification | `proof:uri-rsa` | +| `pgp:` | 40-char PGP fingerprint | `pgp:EF6E286DDA85EA2A4BA7DE684E2C6E8793298290` | +| `abuse:` | Abuse contact (exits) | `abuse:abuse[]example.com` | +| `hoster:` | Hosting provider domain | `hoster:www.example-hoster.com` | +| `uplinkbw:` | Uplink bandwidth (Mbit/s) | `uplinkbw:1000` | +| `ciissversion:` | Spec version (**mandatory**) | `ciissversion:2` | + +**Why use it?** +- Tools like [Tor Metrics](https://metrics.torproject.org/) can parse your info automatically +- `proof:uri-rsa` lets anyone verify you own the URL (place relay fingerprints at `https://your-domain/.well-known/tor-relay/rsa-fingerprint.txt`) +- Helps detect impersonation - operators can't fake verified URLs +- Improves trust and visibility in the Tor network + +**Generate your string:** Use the [CIISS Generator](https://torcontactinfogenerator.netlify.app/) - fill in the fields and copy the result into your `ContactInfo` line or `TOR_CONTACT_INFO` env var. + +> πŸ“– **Full spec:** [nusenu.github.io/ContactInfo-Information-Sharing-Specification](https://nusenu.github.io/ContactInfo-Information-Sharing-Specification/) + ### What's the difference between TOR_* and official bridge naming? Both work identically - we support two naming conventions for compatibility: @@ -97,7 +128,7 @@ Both work identically - we support two naming conventions for compatibility: ```bash TOR_RELAY_MODE=bridge TOR_NICKNAME=MyBridge -TOR_CONTACT_INFO=admin@example.com +TOR_CONTACT_INFO=email:admin[]example.com ciissversion:2 TOR_ORPORT=9001 TOR_OBFS4_PORT=9002 ``` @@ -195,6 +226,8 @@ sudo ufw allow 9002/tcp | First statistics | 24-48 hours | Bandwidth graphs appear | | Guard flag | 8+ days | Relay trusted for entry connections | +> πŸ—³οΈ **Directory Authority Voting:** Tor has **9 Directory Authorities** that vote hourly on relay flags. A relay only earns a flag (Guard, Stable, Fast, HSDir, etc.) when **at least 5 of 9** authorities agree in the consensus. This is why flags aren't instant - your relay must prove itself to a majority of independent authorities. + **Troubleshooting:** 1. **Check bootstrap:** `docker exec tor-relay status` - Must show "Bootstrapped 100%" @@ -247,7 +280,7 @@ docker logs tor-bridge | grep "bridge line" **Factors affecting bandwidth:** 1. **Relay age** - New relays are untrusted 2. **Uptime percentage** - Must maintain 99%+ for Guard flag -3. **Relay flags** - Guard, Fast, Stable flags increase usage +3. **Relay flags** - Guard, Fast, Stable flags increase usage (assigned by directory authority consensus - at least 5 of 9 authorities must vote for each flag) 4. **Configured bandwidth** - Tor won't exceed your limits 5. **Exit policy** - Exit relays typically get more traffic @@ -426,7 +459,7 @@ docker run -d --name tor-relay ... # Same config **Verify upgrade:** ```bash docker exec tor-relay cat /build-info.txt -# Should show: Version: 1.1.6 +# Should show: Version: 1.1.7 docker exec tor-relay fingerprint # Verify fingerprint unchanged @@ -537,5 +570,5 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md) for guidelines. --- -**Last Updated:** Feburary 2026 (v1.1.6) +**Last Updated:** March 2026 (v1.1.7) **Maintained by:** [@r3bo0tbx1](https://github.com/r3bo0tbx1) diff --git a/docs/MIGRATION-V1.1.X.md b/docs/MIGRATION-V1.1.X.md index 3505d79..965ae50 100644 --- a/docs/MIGRATION-V1.1.X.md +++ b/docs/MIGRATION-V1.1.X.md @@ -436,7 +436,7 @@ docker rm obfs4-bridge - [ ] Fingerprint matches backup - [ ] Container starts without errors - [ ] Bootstrap reaches 100% -- [ ] Diagnostic tools work (status, health, fingerprint) +- [ ] Diagnostic tools work (status, health, fingerprint, gen-family) - [ ] Monitoring updated (if applicable) --- diff --git a/docs/MIGRATION.md b/docs/MIGRATION.md index 8c8049e..95c84c1 100644 --- a/docs/MIGRATION.md +++ b/docs/MIGRATION.md @@ -178,6 +178,7 @@ After any migration: - `docker exec status` - `docker exec health` - `docker exec fingerprint` + - `docker exec gen-family --show` (if using Happy Family) - [ ] Tor Metrics shows relay (after 1-2 hours) --- diff --git a/docs/MULTI-MODE.md b/docs/MULTI-MODE.md index 90e3114..5915f4a 100644 --- a/docs/MULTI-MODE.md +++ b/docs/MULTI-MODE.md @@ -49,7 +49,7 @@ The Tor Guard Relay container now supports **three relay modes**: **Best for:** - Operators who want to contribute without legal complexity - Stable, high-bandwidth connections -- Long-term operation (8+ days to earn Guard flag) +- Long-term operation (8+ days to earn Guard flag - requires at least 5 of 9 directory authorities to vote in consensus) **Requirements:** - Public IP with ports 9001, 9030 accessible @@ -491,7 +491,7 @@ nc -zv 9001 **Normal for:** - New relays (2-8 weeks to build reputation) - Bridges (intentionally low visibility) -- Guards without Guard flag (need 8+ days uptime) +- Guards without Guard flag (need 8+ days uptime - at least 5 of 9 directory authorities must agree in consensus) **Check:** 1. Verify relay is reachable: `docker exec status` diff --git a/docs/TOOLS.md b/docs/TOOLS.md index 824b680..cdcc680 100644 --- a/docs/TOOLS.md +++ b/docs/TOOLS.md @@ -1,6 +1,6 @@ # πŸ› οΈ Tools Reference Guide -**Tor Guard Relay 1.1.3** includes 5 essential diagnostic tools built directly into the ultra-optimized ~20 MB container. All tools are busybox-compatible, executable without file extensions, and designed for production use. +**Tor Guard Relay 1.1.3** includes 6 essential diagnostic tools built directly into the ultra-optimized ~20 MB container. All tools are busybox-compatible, executable without file extensions, and designed for production use. --- @@ -13,6 +13,7 @@ | **fingerprint** | Display relay fingerprint | Text | With Tor Metrics link | | **bridge-line** | Get obfs4 bridge line | Text | Bridge mode only | | gen-auth | Generate Control Port auth | Text | Password + Hash | +| gen-family | Generate/view Happy Family key | Text | Tor 0.4.9+ only | --- @@ -224,6 +225,53 @@ When to use: --- +### `gen-family` + +**Purpose:** Generate or view a Tor Happy Family key (Tor 0.4.9+). This replaces the old `MyFamily` fingerprint-exchange workflow with a single shared `FamilyId`. + +**Usage:** +```bash +# Generate a new family key +docker exec tor-relay gen-family MyRelays + +# View existing family key and FamilyId +docker exec tor-relay gen-family --show + +# Show help +docker exec tor-relay gen-family --help +``` + +**Output Example (generate):** +``` +════════════════════════════════════════════════════════════ +Tor Happy Family Key Generator (Tor 0.4.9+) +════════════════════════════════════════════════════════════ + +βœ“ Generated family key: MyRelays + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +Your FamilyId (add to torrc or TOR_FAMILY_ID env var): +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + FamilyId wweKJrJxUDs1EdtFFHCDtvVgTKftOC/crUl1mYJv830 + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +πŸ’‘ Copy the secret key file to all relays in this family. + Then set TOR_FAMILY_ID in each relay's environment. +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +**Exit Codes:** +- `0` - Key generated or displayed successfully +- `1` - Error (key already exists, Tor not found, etc.) + +**When to use:** +- When linking multiple relays (guard, exit, middle) into a family +- Run once to generate, then copy the key file to all family members +- Replaces the old manual fingerprint exchange (`MyFamily`) + +--- + ## πŸš€ Common Workflows ### 1. Quick Health Check @@ -270,7 +318,21 @@ docker exec tor-bridge bridge-line # Share ONLY with trusted users, NOT publicly ``` -### 5. Automated Monitoring +### 5. Set Up Happy Family (Tor 0.4.9+) +```bash +# Generate a family key on one relay +docker exec tor-relay gen-family MyRelays + +# Copy the key file to all other family members +docker cp tor-relay:/var/lib/tor/keys/MyRelays.secret_family_key ./ +docker cp ./MyRelays.secret_family_key tor-relay-2:/var/lib/tor/keys/ +docker exec -u 0 tor-relay-2 chown 100:101 /var/lib/tor/keys/MyRelays.secret_family_key + +# Set TOR_FAMILY_ID on each relay and restart +# (use the FamilyId from gen-family --show output) +``` + +### 6. Automated Monitoring ```bash # Simple monitoring script while true; do @@ -288,7 +350,7 @@ while true; do done ``` -### 6. Check Logs +### 7. Check Logs ```bash # View recent logs docker logs --tail 100 tor-relay @@ -322,7 +384,7 @@ docker logs tor-relay 2>&1 | grep -i warn # Verify tools exist docker exec tor-relay ls -la /usr/local/bin/ -# Should show: status, health, fingerprint, bridge-line, gen-auth +# Should show: status, health, fingerprint, bridge-line, gen-auth, gen-family # Check PATH docker exec tor-relay echo $PATH @@ -401,18 +463,22 @@ docker logs tor-relay | grep -i obfs4 ## ❓ FAQ -**Q: Why only 5 tools instead of 9?** -A: The v1.1.3 build remains ultra-light (~16.8 MB). These 5 tools cover all essential operations including health checks, identity, and authentication setup. +**Q: Why only 6 tools instead of 9?** + +A: The v1.1.3 build remains ultra-light (~16.8 MB). These 6 tools cover all essential operations including health checks, identity, authentication setup, and Happy Family key management. **Q: Where are metrics/monitoring endpoints?** + A: Removed to achieve ultra-small image size. Use `health` tool with external monitoring systems or check `/var/log/tor/notices.log` directly. **Q: Can I still use Prometheus?** + A: Yes! Use `gen-auth` to configure the Control Port, then run a separate `prometheus-tor-exporter` container alongside this one. **Q: What happened to the dashboard?** + A: Removed (required Python/Flask). Use `status` tool for visual output or build your own dashboard using `health` JSON. --- -**Last Updated:** December 2025 | **Version:** 1.1.3 \ No newline at end of file +**Last Updated:** March 2026 | **Version:** 1.1.7 \ No newline at end of file diff --git a/docs/TROUBLESHOOTING-BRIDGE-MIGRATION.md b/docs/TROUBLESHOOTING-BRIDGE-MIGRATION.md index 8ede819..ad5c29c 100644 --- a/docs/TROUBLESHOOTING-BRIDGE-MIGRATION.md +++ b/docs/TROUBLESHOOTING-BRIDGE-MIGRATION.md @@ -501,7 +501,7 @@ After migration: - ✨ Official Tor Project ENV variable compatibility - ✨ Bootstrap progress logs in terminal - ✨ Enhanced emoji logging (v1.1.0 style) -- ✨ 5 diagnostic tools (status, health, fingerprint, bridge-line, gen-auth) +- ✨ 6 diagnostic tools (status, health, fingerprint, bridge-line, gen-auth, gen-family) - ✨ Auto-detection of bridge mode from PT_PORT - ✨ OBFS4V_* variable processing diff --git a/examples/relay-bridge.conf b/examples/relay-bridge.conf index 9e0c91b..6791c33 100644 --- a/examples/relay-bridge.conf +++ b/examples/relay-bridge.conf @@ -1,5 +1,14 @@ -Nickname ShinobiKage +Nickname MyTorBridge ContactInfo email:your-email[]example.com pgp:YOUR_PGP_FINGERPRINT ciissversion:2 + +# Happy Family (Tor 0.4.9+) - replaces MyFamily +# Generate with: docker exec tor-bridge gen-family MyRelays +#FamilyId YOUR_FAMILY_ID_HERE + +# MyFamily (legacy - keep BOTH during transition period) +#MyFamily FINGERPRINT_OF_OTHER_RELAY_1 +#MyFamily FINGERPRINT_OF_OTHER_RELAY_2 + Address YOUR.IPV4.IP.ADDRESS ORPort 24819 IPv4Only ORPort [YOUR:IPV6:IP:ADDRESS::]:24819 diff --git a/examples/relay-exit.conf b/examples/relay-exit.conf index ea1064f..d4fbc38 100644 --- a/examples/relay-exit.conf +++ b/examples/relay-exit.conf @@ -1,5 +1,15 @@ Nickname MyTorExitRelay ContactInfo email:your-email[]example.com pgp:YOUR_PGP_FINGERPRINT ciissversion:2 + +# Happy Family (Tor 0.4.9+) - replaces MyFamily +# Generate with: docker exec tor-relay gen-family MyRelays +#FamilyId YOUR_FAMILY_ID_HERE + +# MyFamily (legacy - keep BOTH during transition period) +# Once Tor Project announces MyFamily removal, you can drop these lines +#MyFamily FINGERPRINT_OF_OTHER_RELAY_1 +#MyFamily FINGERPRINT_OF_OTHER_RELAY_2 + Address YOUR.IPV4.IP.ADDRESS ORPort 9001 IPv4Only ORPort [YOUR:IPV6:IP:ADDRESS::]:9001 diff --git a/examples/relay-guard.conf b/examples/relay-guard.conf index 2cd4a3b..0a3c82c 100644 --- a/examples/relay-guard.conf +++ b/examples/relay-guard.conf @@ -1,5 +1,15 @@ Nickname MyTorGuardRelay ContactInfo email:your-email[]example.com pgp:YOUR_PGP_FINGERPRINT ciissversion:2 + +# Happy Family (Tor 0.4.9+) - replaces MyFamily +# Generate with: docker exec tor-relay gen-family MyRelays +#FamilyId YOUR_FAMILY_ID_HERE + +# MyFamily (legacy - keep BOTH during transition period) +# Once Tor Project announces MyFamily removal, you can drop these lines +#MyFamily FINGERPRINT_OF_OTHER_RELAY_1 +#MyFamily FINGERPRINT_OF_OTHER_RELAY_2 + Address YOUR.IPV4.IP.ADDRESS ORPort 9001 IPv4Only ORPort [YOUR:IPV6:IP:ADDRESS::]:9001 diff --git a/scripts/migration/migration-validator.sh b/scripts/migration/migration-validator.sh index e455bc9..f908a4d 100644 --- a/scripts/migration/migration-validator.sh +++ b/scripts/migration/migration-validator.sh @@ -620,7 +620,7 @@ main() { log "" log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - log "πŸ§… Tor Relay Migration Validator v1.1.6" + log "πŸ§… Tor Relay Migration Validator v1.1.7" log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log "" diff --git a/scripts/release/README.md b/scripts/release/README.md index 012cce1..769a5f2 100644 --- a/scripts/release/README.md +++ b/scripts/release/README.md @@ -163,7 +163,7 @@ Auto-update version numbers across all documentation, templates, and configurati - Format: `## [v1.1.2] - 2025-01-14` 3. **templates/*.yml** (Docker Compose) - - `image:` tags from `onion-relay:1.1.5` β†’ `onion-relay:1.1.6` + - `image:` tags from `onion-relay:1.1.6` β†’ `onion-relay:1.1.7` 4. **templates/*.json** (Cosmos Cloud) - `"image":` fields in JSON templates @@ -515,13 +515,13 @@ sed -i 's/1.1.1/1.1.2/g' path/to/file **Solution:** ```bash # Ensure image exists locally or in registry -docker pull ghcr.io/r3bo0tbx1/onion-relay:1.1.6 +docker pull ghcr.io/r3bo0tbx1/onion-relay:1.1.7 # Generate SBOM locally for testing docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ anchore/syft:latest \ - ghcr.io/r3bo0tbx1/onion-relay:1.1.6 \ + ghcr.io/r3bo0tbx1/onion-relay:1.1.7 \ -o cyclonedx-json ``` diff --git a/scripts/utilities/quick-test.sh b/scripts/utilities/quick-test.sh index 889b3b1..852952e 100644 --- a/scripts/utilities/quick-test.sh +++ b/scripts/utilities/quick-test.sh @@ -231,6 +231,13 @@ else warn "bridge-line tool not ready yet (needs full bootstrap - 10-30 minutes)" fi +# Test 4.5: gen-family tool (help flag) +if docker exec test-tools gen-family --help >/dev/null 2>&1; then + success "gen-family tool works" +else + warn "gen-family tool not available (requires Tor 0.4.9+)" +fi + # Cleanup docker stop test-tools >/dev/null 2>&1 docker rm test-tools >/dev/null 2>&1 @@ -306,7 +313,7 @@ echo "βœ… OBFS4V_* variables are processed correctly" echo "βœ… Bridge mode auto-detected from PT_PORT" echo "βœ… TOR_* ENV naming works (TOR_ORPORT, TOR_CONTACT_INFO, etc.)" echo "βœ… Guard/Exit/Bridge modes configured correctly" -echo "βœ… Diagnostic tools work (status, health, fingerprint, bridge-line)" +echo "βœ… Diagnostic tools work (status, health, fingerprint, bridge-line, gen-family)" echo "βœ… Mixed ENV naming works (can combine official + TOR_* prefix)" echo "" echo "🎯 Your image is fully compatible with thetorproject/obfs4-bridge!" diff --git a/scripts/utilities/relay-status.sh b/scripts/utilities/relay-status.sh index 3a75cbb..1aadc6c 100644 --- a/scripts/utilities/relay-status.sh +++ b/scripts/utilities/relay-status.sh @@ -1,7 +1,7 @@ #!/bin/bash # -# relay-status.sh β€” Tor relay/bridge status checker with security validation -# Version: 1.1.6 +# relay-status.sh - Tor relay/bridge status checker with security validation +# Version: 1.1.7 # Automatically detects Tor containers or uses specified container name # @@ -11,7 +11,7 @@ set -euo pipefail CONTAINER="${1:-}" # Accept container name as first argument readonly FINGERPRINT_PATH="/var/lib/tor/fingerprint" readonly TORRC_PATH="/etc/tor/torrc" -readonly VERSION="1.1.6" +readonly VERSION="1.1.7" # Colors for output readonly RED='\033[0;31m' @@ -359,7 +359,7 @@ EOF # Show version show_version() { echo "relay-status.sh version ${VERSION}" - echo "Part of Tor Guard Relay v1.1.6" + echo "Part of Tor Guard Relay v1.1.7" } # Main execution diff --git a/scripts/utilities/security-validation-tests.sh b/scripts/utilities/security-validation-tests.sh index 7846f0c..ba5fcef 100644 --- a/scripts/utilities/security-validation-tests.sh +++ b/scripts/utilities/security-validation-tests.sh @@ -4,7 +4,7 @@ set -e -echo "πŸ” Security Validation Tests - Tor Guard Relay v1.1.6" +echo "πŸ” Security Validation Tests - Tor Guard Relay v1.1.7" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" @@ -126,7 +126,7 @@ echo "Test 3: Tool Scripts Security" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" # Check for 4 essential tools -for tool in status health fingerprint bridge-line; do +for tool in status health fingerprint bridge-line gen-family; do if [ -f "tools/$tool" ]; then if head -1 "tools/$tool" | grep -q "^#!/bin/sh"; then test_pass "tools/$tool uses busybox sh" @@ -303,7 +303,7 @@ echo "" echo "Test 8: Shell Script Syntax" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -for script in docker-entrypoint.sh tools/status tools/health tools/fingerprint tools/bridge-line; do +for script in docker-entrypoint.sh tools/status tools/health tools/fingerprint tools/bridge-line tools/gen-family; do if [ -f "$script" ]; then if sh -n "$script" 2>/dev/null; then test_pass "$script has valid POSIX sh syntax" diff --git a/templates/README.md b/templates/README.md index 5248673..1230d48 100644 --- a/templates/README.md +++ b/templates/README.md @@ -49,7 +49,7 @@ docker run -d \ --security-opt no-new-privileges:true \ -e TOR_RELAY_MODE=bridge \ -e TOR_NICKNAME=MyBridge \ - -e TOR_CONTACT_INFO=admin@example.com \ + -e TOR_CONTACT_INFO="email:admin[]example.com ciissversion:2" \ -e TOR_ORPORT=9001 \ -e TOR_OBFS4_PORT=9002 \ -v tor-data:/var/lib/tor \ @@ -61,7 +61,7 @@ docker run -d \ # Core (required for ENV-based config) TOR_RELAY_MODE=guard|exit|bridge # Relay mode TOR_NICKNAME=MyRelay # Relay nickname (1-19 chars, alphanumeric) -TOR_CONTACT_INFO=admin@example.com # Contact email +TOR_CONTACT_INFO="email:admin[]example.com ciissversion:2" # Contact info (CIISS v2) # Ports (configurable) TOR_ORPORT=9001 # ORPort for relay traffic (default: 9001) @@ -127,7 +127,7 @@ We support **BOTH** naming conventions for maximum compatibility: ```bash TOR_RELAY_MODE=bridge TOR_NICKNAME=MyBridge -TOR_CONTACT_INFO=admin@example.com +TOR_CONTACT_INFO="email:admin[]example.com ciissversion:2" TOR_ORPORT=9001 TOR_OBFS4_PORT=9002 ``` @@ -296,6 +296,6 @@ If you still see this error after updating to the latest version: --- -**Version:** 1.1.6 -**Last Updated:** 2026-02-08 +**Version:** 1.1.7 +**Last Updated:** 2026-03-02 **Maintainer:** rE-Bo0t.bx1 diff --git a/templates/cosmos-compose/cosmos-bind-config-guard-relay.json b/templates/cosmos-compose/cosmos-bind-config-guard-relay.json index 91029ae..d7821f1 100644 --- a/templates/cosmos-compose/cosmos-bind-config-guard-relay.json +++ b/templates/cosmos-compose/cosmos-bind-config-guard-relay.json @@ -46,7 +46,7 @@ "cosmos-icon": "https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/refs/heads/main/src/onion.png", "cosmos-stack": "TorGuardRelay", "cosmos-stack-main": "TorGuardRelay", - "cosmos-version": "1.1.6", + "cosmos-version": "1.1.7", "maintainer": "rE-Bo0t.bx1 " } } diff --git a/templates/cosmos-compose/cosmos-bind-confing-bridge.json b/templates/cosmos-compose/cosmos-bind-confing-bridge.json index 53931a7..c4e745d 100644 --- a/templates/cosmos-compose/cosmos-bind-confing-bridge.json +++ b/templates/cosmos-compose/cosmos-bind-confing-bridge.json @@ -46,7 +46,7 @@ "cosmos-icon": "https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/refs/heads/main/src/obfs4.png", "cosmos-stack": "OBFS4-Bridge", "cosmos-stack-main": "OBFS4-Bridge", - "cosmos-version": "1.1.6", + "cosmos-version": "1.1.7", "maintainer": "rE-Bo0t.bx1 " } } diff --git a/templates/cosmos-compose/cosmos-compose-bridge-official.json b/templates/cosmos-compose/cosmos-compose-bridge-official.json index 727691d..aae16fd 100644 --- a/templates/cosmos-compose/cosmos-compose-bridge-official.json +++ b/templates/cosmos-compose/cosmos-compose-bridge-official.json @@ -52,7 +52,7 @@ "cosmos-stack-main": "OBFS4-Bridge", "cosmos-description": "πŸŒ‰ Tor obfs4 Bridge - Drop-in replacement for thetorproject/obfs4-bridge", "cosmos-icon": "https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/refs/heads/main/src/obfs4.png", - "cosmos-version": "1.1.6", + "cosmos-version": "1.1.7", "maintainer": "rE-Bo0t.bx1 " } } diff --git a/templates/cosmos-compose/cosmos-compose-bridge.json b/templates/cosmos-compose/cosmos-compose-bridge.json index 16f7975..ab9de01 100644 --- a/templates/cosmos-compose/cosmos-compose-bridge.json +++ b/templates/cosmos-compose/cosmos-compose-bridge.json @@ -9,7 +9,7 @@ "environment": [ "TOR_RELAY_MODE=bridge", "TOR_NICKNAME=MyTorBridge", - "TOR_CONTACT_INFO=admin@example.com", + "TOR_CONTACT_INFO=email:admin[]example.com ciissversion:2", "TOR_ORPORT=9001", "TOR_OBFS4_PORT=9002" ], @@ -54,7 +54,7 @@ "cosmos-description": "πŸ§… Tor obfs4 Bridge - ENV-based config", "cosmos-icon": "https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/refs/heads/main/src/obfs4.png", "cosmos-force-network-secured": "false", - "cosmos-version": "1.1.6" + "cosmos-version": "1.1.7" } } }, diff --git a/templates/cosmos-compose/cosmos-compose-exit.json b/templates/cosmos-compose/cosmos-compose-exit.json index 427d122..e7a7db0 100644 --- a/templates/cosmos-compose/cosmos-compose-exit.json +++ b/templates/cosmos-compose/cosmos-compose-exit.json @@ -9,7 +9,7 @@ "environment": [ "TOR_RELAY_MODE=exit", "TOR_NICKNAME=MyExitRelay", - "TOR_CONTACT_INFO=admin@example.com", + "TOR_CONTACT_INFO=email:admin[]example.com ciissversion:2", "TOR_ORPORT=9001", "TOR_DIRPORT=0", "TOR_BANDWIDTH_RATE=50 MBytes", @@ -58,7 +58,7 @@ "cosmos-icon": "https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/refs/heads/main/src/exit.png", "cosmos-auto-update": "true", "cosmos-force-network-secured": "false", - "cosmos-version": "1.1.6" + "cosmos-version": "1.1.7" } } }, diff --git a/templates/cosmos-compose/cosmos-compose-guard.json b/templates/cosmos-compose/cosmos-compose-guard.json index 3689add..8099915 100644 --- a/templates/cosmos-compose/cosmos-compose-guard.json +++ b/templates/cosmos-compose/cosmos-compose-guard.json @@ -9,7 +9,7 @@ "environment": [ "TOR_RELAY_MODE=guard", "TOR_NICKNAME=MyGuardRelay", - "TOR_CONTACT_INFO=admin@example.com", + "TOR_CONTACT_INFO=email:admin[]example.com ciissversion:2", "TOR_ORPORT=9001", "TOR_DIRPORT=0", "TOR_BANDWIDTH_RATE=50 MBytes", @@ -56,7 +56,7 @@ "cosmos-description": "πŸ›‘οΈ Tor Guard Relay | ENV-based config", "cosmos-icon": "https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/refs/heads/main/src/onion.png", "cosmos-force-network-secured": "false", - "cosmos-version": "1.1.6" + "cosmos-version": "1.1.7" } } }, diff --git a/templates/cosmos-compose/cosmos-compose-multi-relay.json b/templates/cosmos-compose/cosmos-compose-multi-relay.json index 91c79a7..f150f17 100644 --- a/templates/cosmos-compose/cosmos-compose-multi-relay.json +++ b/templates/cosmos-compose/cosmos-compose-multi-relay.json @@ -56,7 +56,7 @@ "cosmos-description": "πŸ›‘οΈ Multi Tor Guard Relay - 1", "cosmos-icon": "https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/src/onion.png", "cosmos-force-network-secured": "false", - "cosmos-version": "1.1.6", + "cosmos-version": "1.1.7", "maintainer": "rE-Bo0t.bx1 " } }, @@ -114,7 +114,7 @@ "cosmos-description": "πŸ›‘οΈ Multi Tor Guard Relay - 2", "cosmos-icon": "https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/src/onion.png", "cosmos-force-network-secured": "false", - "cosmos-version": "1.1.6", + "cosmos-version": "1.1.7", "maintainer": "rE-Bo0t.bx1 " } }, @@ -172,7 +172,7 @@ "cosmos-description": "πŸ›‘οΈ Multi Tor Guard Relay - 3", "cosmos-icon": "https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/src/onion.png", "cosmos-force-network-secured": "false", - "cosmos-version": "1.1.6", + "cosmos-version": "1.1.7", "maintainer": "rE-Bo0t.bx1 " } } diff --git a/templates/docker-compose/docker-compose-bridge-official.yml b/templates/docker-compose/docker-compose-bridge-official.yml index 5201931..8ccab28 100644 --- a/templates/docker-compose/docker-compose-bridge-official.yml +++ b/templates/docker-compose/docker-compose-bridge-official.yml @@ -41,7 +41,7 @@ services: labels: com.centurylinklabs.watchtower.enable: "true" description: "Tor obfs4 Bridge - Drop-in replacement for thetorproject/obfs4-bridge" - version: "1.1.6" + version: "1.1.7" maintainer: "rE-Bo0t.bx1 " volumes: diff --git a/templates/docker-compose/docker-compose-bridge.yml b/templates/docker-compose/docker-compose-bridge.yml index 75d1a3d..6ca7c11 100644 --- a/templates/docker-compose/docker-compose-bridge.yml +++ b/templates/docker-compose/docker-compose-bridge.yml @@ -9,7 +9,7 @@ services: environment: TOR_RELAY_MODE: bridge TOR_NICKNAME: MyTorBridge - TOR_CONTACT_INFO: "your-email@example.com" + TOR_CONTACT_INFO: "email:your-email[]example.com ciissversion:2" TOR_ORPORT: 9001 TOR_OBFS4_PORT: 9002 TOR_BANDWIDTH_RATE: "10 MBytes" @@ -36,7 +36,7 @@ services: labels: com.centurylinklabs.watchtower.enable: "true" description: "Tor obfs4 Bridge" - version: "1.1.6" + version: "1.1.7" maintainer: "rE-Bo0t.bx1 " volumes: diff --git a/templates/docker-compose/docker-compose-exit.yml b/templates/docker-compose/docker-compose-exit.yml index 0487a43..4df7923 100644 --- a/templates/docker-compose/docker-compose-exit.yml +++ b/templates/docker-compose/docker-compose-exit.yml @@ -9,11 +9,15 @@ services: environment: TOR_RELAY_MODE: exit TOR_NICKNAME: MyExitRelay - TOR_CONTACT_INFO: "your-email@example.com <0xYOUR_PGP_KEY>" + TOR_CONTACT_INFO: "email:your-email[]example.com url:https://example.com proof:uri-rsa ciissversion:2" TOR_ORPORT: 9001 TOR_DIRPORT: 0 TOR_BANDWIDTH_RATE: "50 MBytes" TOR_BANDWIDTH_BURST: "100 MBytes" + # Happy Family (Tor 0.4.9+) - generate with: docker exec tor-exit-relay gen-family MyRelays + # TOR_FAMILY_ID: "YOUR_FAMILY_ID_HERE" + # MyFamily (legacy, comma-separated fingerprints - keep during transition) + # TOR_MY_FAMILY: "FINGERPRINT1,FINGERPRINT2" TOR_EXIT_POLICY: "accept *:20-23,accept *:43,accept *:53,accept *:79-81,accept *:88,accept *:110,accept *:143,accept *:194,accept *:220,accept *:389,accept *:443,accept *:464,accept *:465,accept *:531,accept *:543-544,accept *:554,accept *:563,accept *:636,accept *:706,accept *:749,accept *:873,accept *:902-904,accept *:981,accept *:989-995,accept *:1194,accept *:1220,accept *:1293,accept *:1500,accept *:1533,accept *:1677,accept *:1723,accept *:1755,accept *:1863,accept *:2082,accept *:2083,accept *:2086-2087,accept *:2095-2096,accept *:2102-2104,accept *:3128,accept *:3389,accept *:3690,accept *:4321,accept *:4643,accept *:5050,accept *:5190,accept *:5222-5223,accept *:5228,accept *:5900,accept *:6660-6669,accept *:6679,accept *:6697,accept *:8000,accept *:8008,accept *:8074,accept *:8080,accept *:8082,accept *:8087-8088,accept *:8232-8233,accept *:8332-8333,accept *:8443,accept *:8888,accept *:9418,accept *:9999,accept *:10000,accept *:11371,accept *:19294,accept *:19638,accept *:50002,accept *:64738,reject *:*" volumes: - tor-exit-data:/var/lib/tor @@ -37,7 +41,7 @@ services: labels: com.centurylinklabs.watchtower.enable: "true" description: "Tor Exit Relay" - version: "1.1.6" + version: "1.1.7" maintainer: "rE-Bo0t.bx1 " volumes: diff --git a/templates/docker-compose/docker-compose-guard-env.yml b/templates/docker-compose/docker-compose-guard-env.yml index d49b430..058e639 100644 --- a/templates/docker-compose/docker-compose-guard-env.yml +++ b/templates/docker-compose/docker-compose-guard-env.yml @@ -9,11 +9,15 @@ services: environment: TOR_RELAY_MODE: guard TOR_NICKNAME: MyGuardRelay - TOR_CONTACT_INFO: "your-email@example.com <0xYOUR_PGP_KEY>" + TOR_CONTACT_INFO: "email:your-email[]example.com url:https://example.com proof:uri-rsa ciissversion:2" TOR_ORPORT: 9001 TOR_DIRPORT: 0 TOR_BANDWIDTH_RATE: "50 MBytes" TOR_BANDWIDTH_BURST: "100 MBytes" + # Happy Family (Tor 0.4.9+) - generate with: docker exec tor-guard-relay gen-family MyRelays + # TOR_FAMILY_ID: "YOUR_FAMILY_ID_HERE" + # MyFamily (legacy, comma-separated fingerprints - keep during transition) + # TOR_MY_FAMILY: "FINGERPRINT1,FINGERPRINT2" volumes: - tor-guard-data:/var/lib/tor - tor-guard-logs:/var/log/tor diff --git a/templates/docker-compose/docker-compose-multi-relay.yml b/templates/docker-compose/docker-compose-multi-relay.yml index 0267596..427af8a 100644 --- a/templates/docker-compose/docker-compose-multi-relay.yml +++ b/templates/docker-compose/docker-compose-multi-relay.yml @@ -1,5 +1,26 @@ version: '3.8' +# Happy Family Setup (Tor 0.4.9+): +# +# Option A - Generate a new key: +# 1. Start relay-1, then run: docker exec guard-relay-1 gen-family MyRelays +# 2. Copy the .secret_family_key to all relay volumes: +# docker cp guard-relay-1:/var/lib/tor/keys/MyRelays.secret_family_key . +# docker cp MyRelays.secret_family_key guard-relay-2:/var/lib/tor/keys/ +# docker cp MyRelays.secret_family_key guard-relay-3:/var/lib/tor/keys/ +# 3. Fix ownership: docker exec -u 0 chown 100:101 /var/lib/tor/keys/MyRelays.secret_family_key +# 4. Add 'FamilyId ' to each relay's torrc +# 5. Keep MyFamily lines during the transition period +# 6. Restart all relays +# +# Option B - Import an existing key from a non-Docker setup: +# 1. Copy your .secret_family_key to the Docker host +# 2. docker cp MyRelays.secret_family_key guard-relay-1:/var/lib/tor/keys/ +# (repeat for each relay container) +# 3. Fix ownership: docker exec -u 0 chown 100:101 /var/lib/tor/keys/MyRelays.secret_family_key +# 4. Add 'FamilyId ' to each relay's torrc +# 5. Restart all relays + services: tor-relay-1: image: r3bo0tbx1/onion-relay:latest diff --git a/templates/tor-exit-notice/tor-exit-notice-(r3bo0tbx1).html b/templates/tor-exit-notice/tor-exit-notice-(r3bo0tbx1).html index 5fe8e44..34ce565 100644 --- a/templates/tor-exit-notice/tor-exit-notice-(r3bo0tbx1).html +++ b/templates/tor-exit-notice/tor-exit-notice-(r3bo0tbx1).html @@ -703,7 +703,7 @@

Important: The traffic you observed did not originate from this machine. It originated from an anonymous user somewhere in the world who routed their traffic through the Tor network. This server merely forwarded that traffic to your destination.

-

Think of this server like a postal service that delivers lettersβ€”the postal worker doesn't write the letters, they just deliver them. Similarly, this exit node doesn't create traffic, it only forwards it.

+

Think of this server like a postal service that delivers letters - the postal worker doesn't write the letters, they just deliver them. Similarly, this exit node doesn't create traffic, it only forwards it.

diff --git a/tools/gen-family b/tools/gen-family new file mode 100644 index 0000000..d38fa0c --- /dev/null +++ b/tools/gen-family @@ -0,0 +1,249 @@ +#!/bin/sh +# Generate or display Tor Happy Family key and FamilyId +# Requires Tor >= 0.4.9.x with --keygen-family support + +set -e + +GREEN=$(printf '\033[0;32m') +BLUE=$(printf '\033[0;34m') +YELLOW=$(printf '\033[1;33m') +CYAN=$(printf '\033[0;36m') +RED=$(printf '\033[0;31m') +BOLD=$(printf '\033[1m') +NC=$(printf '\033[0m') + +TOR_DATA_DIR="${TOR_DATA_DIR:-/var/lib/tor}" +KEYS_DIR="${TOR_DATA_DIR}/keys" +FORCE=0 + +for arg in "$@"; do + case "$arg" in + --force|-f) FORCE=1 ;; + esac +done + +FAMILY_NAME="" +for arg in "$@"; do + case "$arg" in + --force|-f|--help|-h|--show|-s) ;; + *) FAMILY_NAME="$arg"; break ;; + esac +done +FAMILY_NAME="${FAMILY_NAME:-TorFamily}" + +show_usage() { + echo "" + echo "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}" + echo "${CYAN}β•‘${NC} ${BOLD}Tor Happy Family Key Generator${NC} ${CYAN}β•‘${NC}" + echo "${CYAN}β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•${NC}" + echo "" + echo "${BOLD}Usage:${NC}" + echo " gen-family [name] Generate a new family key" + echo " gen-family [name] --force Overwrite existing key (no backup prompt)" + echo " gen-family --show Show existing FamilyId" + echo " gen-family --help Show this help" + echo "" + echo "${BOLD}Examples:${NC}" + echo " docker exec tor-relay gen-family MyRelays" + echo " docker exec tor-relay gen-family --show" + echo "" + echo "${BOLD}What is Happy Family?${NC}" + echo " Tor 0.4.9+ replaces MyFamily with a cryptographic key-based" + echo " system. All relays in a family share one secret key file." + echo " See: https://community.torproject.org/relay/setup/post-install/family-ids/" + echo "" +} + +show_existing() { + echo "" + echo "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}" + echo "${CYAN}β•‘${NC} ${BOLD}Tor Happy Family - Current Status${NC} ${CYAN}β•‘${NC}" + echo "${CYAN}β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•${NC}" + echo "" + + FOUND=0 + for keyfile in "$KEYS_DIR"/*.secret_family_key; do + [ -f "$keyfile" ] || continue + FOUND=1 + BASENAME=$(basename "$keyfile" .secret_family_key) + echo "${GREEN}βœ“${NC} Found family key: ${BOLD}${BASENAME}${NC}" + echo " File: ${BLUE}${keyfile}${NC}" + done + + if [ "$FOUND" -eq 0 ]; then + echo "${YELLOW}⚠${NC} No family keys found in ${KEYS_DIR}" + echo "" + echo " Generate one with: ${BOLD}gen-family MyRelays${NC}" + echo "" + exit 1 + fi + + TORRC="${TOR_CONFIG:-/etc/tor/torrc}" + if [ -f "$TORRC" ]; then + echo "" + FAMILY_IDS=$(grep -i "^FamilyId " "$TORRC" 2>/dev/null || true) + if [ -n "$FAMILY_IDS" ]; then + echo "${GREEN}βœ“${NC} FamilyId in torrc:" + echo "$FAMILY_IDS" | while read -r line; do + echo " ${BLUE}${line}${NC}" + done + else + echo "${YELLOW}⚠${NC} No FamilyId line found in torrc" + echo " Add the FamilyId line to your torrc to activate Happy Family" + fi + fi + + if [ -f "$TORRC" ]; then + MY_FAMILY=$(grep -i "^MyFamily " "$TORRC" 2>/dev/null || true) + if [ -n "$MY_FAMILY" ]; then + echo "" + echo "${YELLOW}β„Ή${NC} MyFamily lines also present (transition period - this is expected)" + MY_FAMILY_COUNT=$(echo "$MY_FAMILY" | wc -l) + echo " ${MY_FAMILY_COUNT} MyFamily entries configured" + fi + fi + + echo "" +} + +generate_key() { + echo "" + echo "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}" + echo "${CYAN}β•‘${NC} ${BOLD}Tor Happy Family Key Generator${NC} ${CYAN}β•‘${NC}" + echo "${CYAN}β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•${NC}" + echo "" + + TOR_VERSION=$(tor --version 2>/dev/null | head -n1 || echo "unknown") + echo "${BOLD}Tor version:${NC} ${TOR_VERSION}" + echo "" + + if [ -f "${KEYS_DIR}/${FAMILY_NAME}.secret_family_key" ]; then + if [ "$FORCE" -eq 1 ]; then + echo "${YELLOW}⚠${NC} Removing existing family key: ${BOLD}${FAMILY_NAME}${NC}" + rm -f "${KEYS_DIR}/${FAMILY_NAME}.secret_family_key" + echo "${GREEN}βœ“${NC} Old key removed" + echo "" + else + echo "${YELLOW}⚠${NC} Family key '${FAMILY_NAME}' already exists!" + echo " File: ${BLUE}${KEYS_DIR}/${FAMILY_NAME}.secret_family_key${NC}" + echo "" + echo " ${BOLD}To replace without backup:${NC}" + echo " ${BOLD}gen-family ${FAMILY_NAME} --force${NC}" + echo "" + echo " ${BOLD}To replace safely:${NC}" + echo " 1. Back it up first:" + echo " ${BOLD}docker cp :${KEYS_DIR}/${FAMILY_NAME}.secret_family_key ./${FAMILY_NAME}.secret_family_key.bak${NC}" + echo " 2. Remove the old key:" + echo " ${BOLD}docker exec -u 0 rm ${KEYS_DIR}/${FAMILY_NAME}.secret_family_key${NC}" + echo " 3. Run gen-family again:" + echo " ${BOLD}gen-family ${FAMILY_NAME}${NC}" + echo "" + echo " ${RED}⚠️ WARNING:${NC} Replacing a family key means ALL relays using it" + echo " must be updated with the new key and FamilyId. Back up first!" + echo "" + echo " ${BOLD}Or use a different name:${NC} gen-family NewFamilyName" + echo " ${BOLD}View existing keys:${NC} gen-family --show" + echo "" + exit 1 + fi + fi + + mkdir -p "$KEYS_DIR" 2>/dev/null || true + + echo "${BOLD}Generating family key: ${CYAN}${FAMILY_NAME}${NC}" + echo "" + + KEYGEN_OUTPUT=$(cd "$KEYS_DIR" && tor --keygen-family "$FAMILY_NAME" 2>&1) || { + echo "${RED}βœ—${NC} Failed to generate family key!" + echo "" + echo " Output: ${KEYGEN_OUTPUT}" + echo "" + echo " This requires Tor >= 0.4.9.2-alpha" + echo " Your version: ${TOR_VERSION}" + echo "" + exit 1 + } + + FAMILY_ID=$(echo "$KEYGEN_OUTPUT" | grep "^FamilyId " | head -1) + + if [ -z "$FAMILY_ID" ]; then + FAMILY_ID=$(echo "$KEYGEN_OUTPUT" | grep "FamilyId" | head -1 | sed 's/.*\(FamilyId .*\)/\1/') + fi + + echo "${GREEN}βœ“${NC} Family key generated successfully!" + echo "" + + if [ -n "$FAMILY_ID" ]; then + echo "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "${BOLD}1. Add this line to your torrc:${NC}" + echo "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "" + echo " ${GREEN}${FAMILY_ID}${NC}" + echo "" + else + echo "${YELLOW}⚠${NC} Could not extract FamilyId from output." + echo " Full output:" + echo " ${KEYGEN_OUTPUT}" + echo "" + fi + + echo "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "${BOLD}2. Key file location:${NC}" + echo "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "" + echo " ${BLUE}${KEYS_DIR}/${FAMILY_NAME}.secret_family_key${NC}" + echo "" + echo "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "${BOLD}3. For multi-relay setups:${NC}" + echo "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "" + echo " Copy this key to ALL your relays. Each relay needs:" + echo " β€’ The ${BOLD}.secret_family_key${NC} file in its keys directory" + echo " β€’ The ${BOLD}FamilyId${NC} line in its torrc" + echo "" + echo " Extract from this container:" + echo " ${BOLD}docker cp :${KEYS_DIR}/${FAMILY_NAME}.secret_family_key .${NC}" + echo "" + echo " Copy to another container's volume:" + echo " ${BOLD}docker cp ${FAMILY_NAME}.secret_family_key :${KEYS_DIR}/${NC}" + echo "" + echo "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo "" + echo "${CYAN}πŸ“ Next steps:${NC}" + echo " 1. Add the FamilyId line to your torrc (all relays)" + echo " 2. Copy the .secret_family_key to all relay keys directories" + echo " 3. Restart your relays: ${BOLD}docker restart tor-relay${NC}" + echo " 4. Keep MyFamily lines during the transition period" + echo "" + echo "${CYAN}⚠️ Important:${NC}" + echo " β€’ Keep your .secret_family_key ${RED}SECRET${NC} - treat it like a private key" + echo " β€’ Back up the key file - losing it means regenerating for all relays" + echo " β€’ The key persists in your Docker volume (${BOLD}/var/lib/tor${NC})" + echo " β€’ During transition, keep BOTH MyFamily AND FamilyId configured" + echo "" + echo "${CYAN}πŸ“– Documentation:${NC}" + echo " https://community.torproject.org/relay/setup/post-install/family-ids/" + echo "" +} + +ACTION="" +for arg in "$@"; do + case "$arg" in + --help|-h) ACTION="help"; break ;; + --show|-s) ACTION="show"; break ;; + --force|-f) ;; + *) ACTION="generate"; break ;; + esac +done + +case "${ACTION:-help}" in + help) + show_usage + ;; + show) + show_existing + ;; + generate) + generate_key + ;; +esac diff --git a/tools/status b/tools/status index e8c3906..3ffb5ad 100644 --- a/tools/status +++ b/tools/status @@ -57,6 +57,24 @@ if [ -f "$TOR_DATA/fingerprint" ] && [ -r "$TOR_DATA/fingerprint" ]; then echo "πŸ”‘ Fingerprint: ${FP_START}...${FP_END}" fi +# Happy Family status +FAMILY_KEY_COUNT=0 +if [ -d "$TOR_DATA/keys" ]; then + for fk in "$TOR_DATA/keys"/*.secret_family_key; do + [ -f "$fk" ] || continue + FAMILY_KEY_COUNT=$((FAMILY_KEY_COUNT + 1)) + done +fi +TORRC="${TOR_CONFIG:-/etc/tor/torrc}" +if [ "$FAMILY_KEY_COUNT" -gt 0 ]; then + echo "πŸ‘¨β€πŸ‘©β€πŸ‘§ Family Key: $FAMILY_KEY_COUNT key(s) present" +fi +if [ -f "$TORRC" ] && grep -qi "^FamilyId " "$TORRC" 2>/dev/null; then + echo "βœ… Happy Family: CONFIGURED" +elif [ "$FAMILY_KEY_COUNT" -gt 0 ]; then + echo "⚠️ Happy Family: key present but FamilyId not in torrc" +fi + ERRORS=$(grep -c "\[err\]" "$TOR_LOG" 2>/dev/null || echo "0") ERRORS=$(sanitize_num "$ERRORS") WARNINGS=$(grep -c "\[warn\]" "$TOR_LOG" 2>/dev/null || echo "0")