SPDX-License-Identifier: MIT
This policy covers the Tor Guard Relay Docker image, scripts, and workflows in this repository. Issues related to the Tor network itself should be reported directly to The Tor Project.
We actively support the following versions with security updates:
| Version | Status | Support Level |
|---|---|---|
| 2.0.0 | π’ π‘οΈ Active | Full support (current stable) |
| < 2.0.0 | π΄ β Deprecated | Unsupported after v2.0.0 release; tags retained in registries for reproducibility. |
Support policy: Only the latest released version receives updates. When a new version is released, all previous versions automatically become unsupported and no longer receive maintenance, security fixes, or scheduled rebuild updates. Historical tags remain available in registries for reproducibility.
- Affects vulnerable OpenSSL package ranges in Alpine-based images.
- Fix target for this project is
openssl >= 3.5.6-r0via base image/package refresh and rebuild. - Mitigation is image-level: pull updated image tags after release.
- This is a Linux kernel vulnerability and is in CISA KEV.
- Mitigation is primarily host-level: update/pin host kernels using your distro or cloud vendor guidance.
- Pulling a new container image does not patch an unpatched host kernel.
This project follows an ultra-minimal security architecture:
- β NO monitoring HTTP endpoints - Removed for maximum security
- β
NO exposed metrics ports - All monitoring via
docker execonly - β Only Tor protocol ports exposed - ORPort (configurable), obfs4 (bridge mode), DirPort (disabled)
- β ~16.8 MB image - Minimal attack surface
Ports exposed depend on relay mode and configuration:
PUBLIC PORTS:
TOR_ORPORT (default: 9001) β Tor ORPort (relay traffic)
TOR_DIRPORT β Directory service (optional, disabled by default)
PUBLIC PORTS:
TOR_ORPORT (default: 9001) β Tor ORPort (relay traffic)
TOR_DIRPORT β Directory service (optional, disabled by default)
PUBLIC PORTS:
TOR_ORPORT (default: 9001) β Tor ORPort (relay traffic)
TOR_OBFS4_PORT (default: 9002) β obfs4 pluggable transport
All port numbers are fully configurable via environment variables.
ZERO exposed monitoring services:
- β No metrics HTTP endpoints
- β No health check HTTP APIs
- β No dashboard web interfaces
- β
All diagnostics via
docker execcommands only
Available diagnostic tools (container exec only):
docker exec tor-relay status # Health report with emojis
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.2-alpha or later)This project uses host networking mode (--network host) for best Tor performance:
Why host networking?
- β IPv6 Support - Direct access to host's IPv6 stack
- β No NAT - Tor binds directly to ports without translation
- β Better Performance - Eliminates network overhead
- β Tor Recommended - Follows Tor Project best practices
Security with host networking:
- β
Runs as non-root user (
torUID 100) - β Drops all capabilities, adds only required ones
- β
Uses
no-new-privileges:true - β Minimal Alpine Linux base (~16.8 MB)
- β No exposed monitoring ports
- β Automatic permission healing
Why this matters:
- β Minimizes attack surface - Only Tor protocol ports exposed
- β No monitoring vulnerabilities - Cannot attack what doesn't exist
- β Follows Tor best practices - Standard relay configuration
- β Defense in depth - Ultra-minimal design philosophy
Security implications:
- Exposed ORPort: Required for Tor relay operation (configurable)
- Disabled DirPort: Not necessary unless you operate a Directory Authority
- Exposed obfs4 port: Only in bridge mode (configurable)
- NO other services are accessible (internal or external)
# Docker CLI with host networking (recommended)
docker run -d \
--name tor-relay \
--network host \
--security-opt no-new-privileges:true \
--restart unless-stopped \
-v $(pwd)/relay.conf:/etc/tor/torrc:ro \
-v tor-guard-data:/var/lib/tor \
-v tor-guard-logs:/var/log/tor \
r3bo0tbx1/onion-relay:latest # or ghcr.io/r3bo0tbx1/onion-relay:latest# Docker Compose with host networking
services:
tor-relay:
image: r3bo0tbx1/onion-relay:latest
container_name: tor-relay
restart: unless-stopped
network_mode: host
volumes:
- ./relay.conf:/etc/tor/torrc:ro
- tor-guard-data:/var/lib/tor
- tor-guard-logs:/var/log/torExternal monitoring is used for maximum security and minimal image size:
# Check status
docker exec tor-relay status
# Get JSON health (raw)
docker exec tor-relay health
# Parse with jq (requires jq on host)
docker exec tor-relay health | jq .
# View fingerprint
docker exec tor-relay fingerprintCreate your own HTTP wrapper if needed:
#!/usr/bin/env python3
from flask import Flask, jsonify
import subprocess
import json
app = Flask(__name__)
@app.route('/health')
def health():
result = subprocess.run(
['docker', 'exec', 'tor-relay', 'health'],
capture_output=True,
text=True
)
return jsonify(json.loads(result.stdout))
if __name__ == '__main__':
app.run(host='127.0.0.1', port=9100) # Bind to localhost only!Use dedicated Tor exporters for Prometheus integration:
# Use tor_exporter for detailed metrics
docker run -d --name tor-exporter \
--network host \
ghcr.io/atx/prometheus-tor_exporter:latest \
--tor.control-address=127.0.0.1:9051See Monitoring Guide for complete integration examples.
Recommended firewall rules for guard/middle relay:
# UFW (Ubuntu/Debian)
sudo ufw default deny incoming
sudo ufw allow 9001/tcp # ORPort (or your custom port)
sudo ufw enable
# iptables
sudo iptables -A INPUT -p tcp --dport 9001 -j ACCEPT
sudo iptables -A INPUT -j DROP
# firewalld (RHEL/CentOS)
sudo firewall-cmd --permanent --add-port=9001/tcp
sudo firewall-cmd --reloadFor bridge mode:
# UFW (Ubuntu/Debian)
sudo ufw allow 9001/tcp # ORPort
sudo ufw allow 9002/tcp # obfs4 portFor custom ports:
# Replace with your configured ports
sudo ufw allow <TOR_ORPORT>/tcp # guard/exit only
sudo ufw allow <TOR_OBFS4_PORT>/tcp # bridge only- Security patches are released as soon as possible after discovery
- Critical vulnerabilities are prioritized
- Weekly automated builds include the latest Alpine and Tor security updates
- Subscribe to GitHub Releases for notifications
To reduce patch-lag risk, GitHub Actions automatically:
- Pulls the latest Alpine base image
- Installs the latest Tor package
- Applies security patches
- Rebuilds multi-architecture images
- Publishes to Docker Hub and GHCR
Rebuild schedule: Sundays at 18:30 UTC
These rebuilds include Alpine CVE patches and Tor security fixes without changing functionality.
Do NOT report security vulnerabilities through public GitHub issues.
Email: r3bo0tbx1@brokenbotnet.com
Subject: [SECURITY] Tor Guard Relay β <short summary>
Please use my PGP key 0xB3BD6196E1CFBFB4 π to encrypt if your report contains sensitive technical details.
- Description of the vulnerability
- Steps to reproduce the issue
- Impact assessment (who is affected, what's at risk)
- Suggested fix (if you have one)
- Your contact information for follow-up
- Acknowledgment: within 48 hours
- Initial assessment: within 1 week
- Status updates: every 2 weeks until resolved
Resolution timelines:
| Severity | Response Time |
|---|---|
| Critical | 1-7 days |
| High | 1-4 weeks |
| Medium | 1-3 months |
| Low | Next release cycle |
We follow responsible disclosure practices:
- Report received β We acknowledge and investigate
- Fix developed β We create and test a patch
- Coordinated release β We agree on disclosure timing
- Public disclosure β We release the fix and advisory
- Credit given β We acknowledge the reporter (unless anonymity is requested)
# Secure your relay.conf file
chmod 600 /path/to/relay.conf
chown root:root /path/to/relay.conf
# Use read-only mounts
-v /path/to/relay.conf:/etc/tor/torrc:ro# CIISS v3 format (recommended) - generate at https://torcontactinfogenerator.netlify.app/
ContactInfo email:tor-relay[]example.com url:https://example.com proof:uri-familyid-ed25519 pgp:EF6E286DDA85EA2A4BA7DE684E2C6E8793298290 ciissversion:3
# With abuse contact (recommended for exits)
ContactInfo email:tor-relay[]example.com abuse:abuse[]example.com url:https://example.com proof:uri-familyid-ed25519 ciissversion:3π CIISS v3: The ContactInfo Information Sharing Specification provides a machine-readable, verifiable format. The
proof:uri-familyid-ed25519method lets tools verify your relay ownership by checkinghttps://your-domain/.well-known/tor-relay/ed25519-family-id.txtfor your Happy Family ID (Tor 0.4.9.2-alpha or later).
# Regular security updates
apt update && apt upgrade -y # Ubuntu/Debian
yum update -y # RHEL/CentOS
# Verify firewall rules
sudo ufw status numbered
sudo iptables -L -n -v
# Pull latest security-patched image
docker pull r3bo0tbx1/onion-relay:latest# Log monitoring
docker logs tor-relay 2>&1 | grep -iE "(error|warn|critical)"
# Health checks via diagnostic tools
docker exec tor-relay status
# JSON health check for automation (raw)
docker exec tor-relay health
# Parse with jq (requires jq on host)
docker exec tor-relay health | jq .
# Resource monitoring
docker stats tor-relay --no-stream- Never commit secrets or API keys
- Use
.gitignorefor sensitive files - Review dependencies for vulnerabilities
- Follow the principle of least privilege
- Validate all user inputs
- Use POSIX sh only (no bash dependencies)
# Always specify explicit base version
FROM alpine:3.24.1 # Pinned version for reproducibility
# Run as non-root user
USER tor
# Use Docker security options
--security-opt no-new-privileges:true
--cap-drop ALL
--cap-add NET_BIND_SERVICE
--cap-add CHOWN
--cap-add SETUID
--cap-add SETGID
--cap-add DAC_OVERRIDE# NEVER do this:
git add relay.conf # Contains sensitive info!
# Instead:
echo "*.conf" >> .gitignore
echo "relay.conf" >> .gitignoreWhat--network host
Why
Security Impact:
- β
Container runs as non-root user (
torUID 100) - β Drops all capabilities, adds only required ones
- β
Uses
no-new-privileges:true - β No exposed monitoring services
β οΈ Shares host network namespace (required for IPv6)β οΈ Relies on firewall for port isolation
Mitigations:
- Drops all capabilities by default
- Adds only NET_BIND_SERVICE, CHOWN, SETUID, SETGID, DAC_OVERRIDE
- Uses
no-new-privileges:true - Ultra-minimal Alpine base (~16.8 MB)
- NO monitoring HTTP endpoints to attack
- Automatic permission healing
- Configuration validation before start
What: Persistent volumes store keys and state
Security Impact: Keys live in /var/lib/tor; protect from unauthorized access
Mitigation:
# Check volume permissions
docker volume inspect tor-guard-data
# The container automatically sets:
chmod 700 /var/lib/tor
chown tor:tor /var/lib/torUID/GID in Alpine:
toruser: UID 100, GID 101- Different from Debian-based images (UID 101)
- Automatic permission healing on startup
What: Configuration is mounted from the host Impact: May reveal bandwidth limits, ContactInfo, etc.
Mitigation:
- Use read-only mount (
:ro) - Set restrictive file permissions (600)
- Never commit configs to Git
- Sanitize before sharing
- β
Non-root operation (user
torUID 100) - β Minimal base image (Alpine Linux ~16.8 MB)
- β Drops all capabilities, adds only required ones
- β Read-only configuration mount
- β Automatic permission healing
- β Configuration validation on startup
- β NO exposed monitoring HTTP endpoints
- β Busybox-only tools (no bash/python dependencies)
- β Smart healthcheck.sh for Docker health checks
- β Input validation for all ENV variables
- β OBFS4V_* whitelist to prevent command injection
The container supports three relay modes:
| Mode | Default Config | Security Risk |
|---|---|---|
| guard | Guard/middle relay | Low |
| exit | Exit relay | HIGH - Legal implications |
| bridge | obfs4 bridge | Low-Medium |
Default: Guard/middle relay (lowest risk)
Changing modes:
-e TOR_RELAY_MODE=guard # Guard/middle relay (default)
-e TOR_RELAY_MODE=exit # Exit relay (understand legal risks!)
-e TOR_RELAY_MODE=bridge # obfs4 bridgeSee docs/MULTI-MODE.md and docs/LEGAL.md for details.
To ensure ongoing hardening, CI automatically:
- Pulls latest Alpine base (weekly)
- Installs updated Tor package
- Applies available security patches
- Rebuilds for AMD64 + ARM64
- Publishes to Docker Hub and GHCR
Schedule: Sundays at 18:30 UTC
Enable automatic updates in Cosmos:
"cosmos-auto-update": "true",
"cosmos-auto-update-notify": "true"Running a Tor relay is legal in most countries, but:
β οΈ Check local laws and ISP terms of serviceβ οΈ Understand guard vs. exit vs. bridge differencesβ οΈ Keep contact information accurateβ οΈ Read docs/LEGAL.md before deployment
This project supports guard, exit, and bridge modes (configurable via TOR_RELAY_MODE).
- Tor relays do not log traffic content
- Relay fingerprints are public (guard/exit modes)
- Bridge fingerprints are NOT public (distributed via BridgeDB)
- Contact information and bandwidth statistics are public (guard/exit modes)
If you receive abuse complaints:
- Verify it's actually your relay
- Review Tor Project abuse response templates
- Respond professionally
- Consider your legal position
- Join tor-relays mailing list for help
#!/bin/bash
# security-audit.sh - Quick security audit for Tor Guard Relay
echo "π Tor Guard Relay Security Audit"
echo "==========================================="
# Check container is using host networking
echo ""
echo "1. Checking network mode..."
NETWORK_MODE=$(docker inspect tor-relay --format='{{.HostConfig.NetworkMode}}')
if [ "$NETWORK_MODE" = "host" ]; then
echo "β
Using host networking (recommended)"
else
echo "β οΈ Not using host networking: $NETWORK_MODE"
fi
# Test Tor ports
echo ""
echo "2. Testing Tor port accessibility..."
PUBLIC_IP=$(curl -s https://icanhazip.com)
timeout 5 nc -zv $PUBLIC_IP 9001 && echo "β
ORPort accessible" || echo "β ORPort not accessible"
# Verify diagnostic tools work
echo ""
echo "3. Testing diagnostic tools..."
docker exec tor-relay status > /dev/null 2>&1 && echo "β
status tool works" || echo "β status tool failed"
docker exec tor-relay health > /dev/null 2>&1 && echo "β
health tool works" || echo "β health tool failed"
# Check file permissions
echo ""
echo "4. Checking critical file permissions..."
docker exec tor-relay ls -la /var/lib/tor | grep -E "keys|fingerprint"
# Check process user
echo ""
echo "5. Checking process user..."
docker exec tor-relay ps aux | grep -E "^tor" | grep -v grep | head -1
# Check capabilities
echo ""
echo "6. Checking container capabilities..."
docker inspect tor-relay --format='{{.HostConfig.CapDrop}}' | grep -q "ALL" && echo "β
All capabilities dropped" || echo "β οΈ Capabilities not fully restricted"
# Check volumes
echo ""
echo "7. Checking volume mounts..."
docker inspect tor-relay --format='{{range .Mounts}}{{.Source}} β {{.Destination}} ({{.Mode}}){{println}}{{end}}'
echo ""
echo "==========================================="
echo "β
Audit complete!"Security researchers who responsibly disclose vulnerabilities will be listed here:
No vulnerabilities reported yet.
- Security Issues: r3bo0tbx1@brokenbotnet.com
- General Questions: GitHub Discussions
- Project Maintainer: rE-Bo0t.bx1
Thank you for helping keep this project secure! ππ§
Last Updated: 2026-06-05 | Current Stable: 2.0.0