mirror of
https://github.com/r3bo0tbx1/tor-guard-relay.git
synced 2026-04-06 00:32:04 +02:00
🔧 New tool: gen-family - generate/view Happy Family keys - Supports --force flag to overwrite existing keys without backup prompt 🐳 Dockerfiles: gen-family in both Dockerfile and Dockerfile.edge 🔧 Entrypoint: - Phase 2: detect *.secret_family_key, log found keys (informational only) - Guard/exit config gen: append FamilyId + MyFamily from ENV vars - Bridge intentionally excluded 📊 Status tool: show family key count + Happy Family config state 📚 Docs: - README: Happy Family section (generate / import), persistence table, flowchart - ARCHITECTURE: all mermaid diagrams updated (Phase 2, config gen, tools, dirs) - TOOLS: full gen-family reference with examples and exit codes - DEPLOYMENT, MIGRATION, MIGRATION-V1.1.X, TROUBLESHOOTING: 5 -> 6 tools - FAQ, example configs: version bump + FamilyId/MyFamily placeholders - Directory authority voting: how 9 dirauths vote on relay flags (5/9 consensus) - CIISS v2 ContactInfo: field reference, generator link, proof:uri-rsa verification - All TOR_CONTACT_INFO examples updated to CIISS v2 format across templates and docs 📋 Templates: - Guard/exit/multi-relay compose: TOR_FAMILY_ID + TOR_MY_FAMILY env vars - All cosmos-compose + docker-compose versions -> 1.1.7 👷 CI: validate.yml gen-family in 8 spots (threshold 6), security tests, quick-test 🛡️ SECURITY.md: 1.1.7 active, 1.1.6 maintenance, gen-family in tools list 🔖 Version bump 1.1.6 -> 1.1.7 across 30+ files, tool count 5 -> 6, CHANGELOG entry No breaking changes. TOR_FAMILY_ID and TOR_MY_FAMILY are optional.
475 lines
12 KiB
Markdown
475 lines
12 KiB
Markdown
# Migration Guide: v1.1.0 → >=v1.1.1
|
|
|
|
This guide documents **two successful real-world migration paths** validated in production:
|
|
1. **Guard/Middle Relay** (mounted torrc) - Zero issues
|
|
2. **Bridge from Official Image** (thetorproject/obfs4-bridge) - Requires ownership fix
|
|
|
|
---
|
|
|
|
## 📋 What's New in v1.1.1
|
|
|
|
### Security Fixes
|
|
- ✅ **Fixed**: Command injection via OBFS4V_* environment variables (CWE-78, CWE-94)
|
|
- ✅ **Fixed**: Health check failure on ENV-based deployments (CWE-703)
|
|
- ✅ **Fixed**: Privilege escalation attempt with silent failure (CWE-250)
|
|
- ✅ **Fixed**: Inadequate input validation (CWE-20)
|
|
- ✅ **Fixed**: Workflow permission over-granting (CWE-269)
|
|
- ✅ **Fixed**: Temporary file race condition (CWE-377)
|
|
- ✅ **Fixed**: TOR_CONTACT_INFO validation false positives
|
|
|
|
### Improvements
|
|
- ✅ Smart healthcheck script works with both mounted and ENV configs
|
|
- ✅ Comprehensive input validation with whitespace trimming
|
|
- ✅ Better error messages and debugging
|
|
- ✅ Removed non-functional chown attempt
|
|
- ✅ Cleaned up bridge configuration (removed redundant ExitPolicy)
|
|
|
|
### Breaking Changes
|
|
**None** - All changes are backward compatible!
|
|
|
|
---
|
|
|
|
## ✅ Migration Path 1: Guard/Middle Relay (Mounted Config)
|
|
|
|
**Difficulty**: Easy
|
|
**Downtime**: < 2 minutes
|
|
**Fingerprint Preserved**: Yes ✅
|
|
**Volume Changes Required**: None
|
|
|
|
### Prerequisites
|
|
|
|
```bash
|
|
# Verify you're using a mounted torrc file
|
|
docker inspect <container> --format='{{range .Mounts}}{{if eq .Destination "/etc/tor/torrc"}}MOUNTED{{end}}{{end}}'
|
|
# Should output: MOUNTED
|
|
```
|
|
|
|
### Step 1: Backup
|
|
|
|
```bash
|
|
# Stop container
|
|
docker stop <container>
|
|
|
|
# Backup volumes
|
|
docker run --rm \
|
|
-v tor-guard-data:/data \
|
|
-v /tmp:/backup \
|
|
alpine:3.23.3 tar czf /backup/tor-guard-data-backup-$(date +%Y%m%d).tar.gz /data
|
|
|
|
docker run --rm \
|
|
-v tor-guard-logs:/data \
|
|
-v /tmp:/backup \
|
|
alpine:3.23.3 tar czf /backup/tor-guard-logs-backup-$(date +%Y%m%d).tar.gz /data
|
|
|
|
# Save fingerprint
|
|
docker run --rm -v tor-guard-data:/data alpine:3.23.3 cat /data/fingerprint > /tmp/fingerprint-backup.txt
|
|
```
|
|
|
|
### Step 2: Update Configuration
|
|
|
|
**Cosmos JSON changes**:
|
|
```json
|
|
{
|
|
"image": "r3bo0tbx1/onion-relay:latest", // ← Update from :latest or :1.1.0
|
|
"cap_add": [
|
|
"NET_BIND_SERVICE" // ← Removed unnecessary CHOWN, SETUID, SETGID, DAC_OVERRIDE
|
|
],
|
|
"labels": {
|
|
"cosmos-version": "1.1.1" // ← Update version
|
|
}
|
|
}
|
|
```
|
|
|
|
### Step 3: Remove Old Container
|
|
|
|
```bash
|
|
docker rm <container>
|
|
```
|
|
|
|
### Step 4: Deploy Updated Container
|
|
|
|
- Import updated JSON in Cosmos UI
|
|
- Or redeploy with `docker-compose up -d`
|
|
|
|
### Step 5: Verify
|
|
|
|
```bash
|
|
# Check logs
|
|
docker logs -f <container>
|
|
# Expected: ✅ Using mounted configuration: /etc/tor/torrc
|
|
|
|
# Verify fingerprint matches
|
|
docker exec <container> fingerprint
|
|
cat /tmp/fingerprint-backup.txt
|
|
# Must match!
|
|
|
|
# Run diagnostics
|
|
docker exec <container> status
|
|
docker exec <container> health | jq .
|
|
```
|
|
|
|
### ✅ Success Criteria
|
|
|
|
- [ ] Container starts successfully
|
|
- [ ] Logs show "Using mounted configuration"
|
|
- [ ] Fingerprint matches backup
|
|
- [ ] Bootstrap reaches 100%
|
|
- [ ] Relay is reachable
|
|
|
|
---
|
|
|
|
## ⚠️ Migration Path 2: Bridge from Official Image
|
|
|
|
**Difficulty**: Moderate
|
|
**Downtime**: 5-10 minutes
|
|
**Fingerprint Preserved**: Yes ✅ (after fix)
|
|
**Volume Changes Required**: Yes - UID ownership fix
|
|
|
|
### The Challenge
|
|
|
|
**UID Mismatch**:
|
|
- Official `thetorproject/obfs4-bridge` (Debian): UID **101**
|
|
- `r3bo0tbx1/onion-relay` (Alpine): UID **100**
|
|
|
|
**Symptom**: `Permission denied` errors if not fixed.
|
|
|
|
### Prerequisites
|
|
|
|
```bash
|
|
# Verify current image
|
|
docker inspect <container> --format='{{.Config.Image}}'
|
|
# Should show: thetorproject/obfs4-bridge or similar
|
|
|
|
# Check ENV variables
|
|
docker inspect <container> --format='{{range .Config.Env}}{{println .}}{{end}}' | grep -E "OR_PORT|PT_PORT|EMAIL|NICKNAME"
|
|
```
|
|
|
|
### Recommended Approach: Use Mounted Config
|
|
|
|
**Why?**
|
|
- ✅ More reliable than ENV variables
|
|
- ✅ Bypasses validation complexity
|
|
- ✅ Same as guard relay (consistent approach)
|
|
- ✅ Easier to troubleshoot
|
|
|
|
### Step 1: Backup Everything
|
|
|
|
```bash
|
|
# Stop container
|
|
docker stop obfs4-bridge
|
|
|
|
# Backup volume (CRITICAL!)
|
|
docker run --rm \
|
|
-v obfs4-data:/data \
|
|
-v /tmp:/backup \
|
|
alpine:3.23.3 tar czf /backup/obfs4-data-backup-$(date +%Y%m%d).tar.gz /data
|
|
|
|
# Verify backup
|
|
ls -lh /tmp/obfs4-data-backup-*.tar.gz
|
|
|
|
# Save fingerprint
|
|
docker run --rm -v obfs4-data:/data alpine:3.23.3 cat /data/fingerprint > /tmp/bridge-fingerprint-backup.txt
|
|
cat /tmp/bridge-fingerprint-backup.txt
|
|
```
|
|
|
|
### Step 2: Fix Volume Ownership (CRITICAL!)
|
|
|
|
```bash
|
|
# Check current ownership (should be 101:101)
|
|
docker run --rm -v obfs4-data:/data alpine:3.23.3 ls -ldn /data
|
|
# Output: drwx------ ... 101 101 ...
|
|
|
|
# Fix ownership: 101 → 100
|
|
docker run --rm -v obfs4-data:/data alpine:3.23.3 chown -R 100:101 /data
|
|
|
|
# Verify fix
|
|
docker run --rm -v obfs4-data:/data alpine:3.23.3 ls -ldn /data
|
|
# Output: drwx------ ... 100 101 ... ← MUST show 100!
|
|
|
|
# Verify key files are readable
|
|
docker run --rm -v obfs4-data:/data alpine:3.23.3 ls -la /data/keys/
|
|
# Should show files owned by 100:101
|
|
```
|
|
|
|
### Step 3: Create Bridge Config File
|
|
|
|
```bash
|
|
# Create config directory
|
|
sudo mkdir -p /home/$(whoami)/onion
|
|
|
|
# Create bridge.conf
|
|
sudo tee /home/$(whoami)/onion/bridge.conf > /dev/null << 'EOF'
|
|
# Tor obfs4 Bridge Configuration
|
|
Nickname MyObfs4Bridge
|
|
ContactInfo admin@email.org
|
|
|
|
# Network configuration
|
|
ORPort 9001
|
|
SocksPort 0
|
|
|
|
# Data directories
|
|
DataDirectory /var/lib/tor
|
|
Log notice file /var/log/tor/notices.log
|
|
|
|
# Bridge relay configuration
|
|
BridgeRelay 1
|
|
PublishServerDescriptor bridge
|
|
|
|
# obfs4 pluggable transport
|
|
ServerTransportPlugin obfs4 exec /usr/bin/lyrebird
|
|
ServerTransportListenAddr obfs4 0.0.0.0:9005
|
|
ExtORPort auto
|
|
|
|
# Additional options
|
|
MaxMemInQueues 1024 MB
|
|
AddressDisableIPv6 0
|
|
EOF
|
|
|
|
# Customize with your values
|
|
sudo nano /home/$(whoami)/onion/bridge.conf
|
|
```
|
|
|
|
### Step 4: Remove Old Container
|
|
|
|
```bash
|
|
docker rm obfs4-bridge
|
|
```
|
|
|
|
### Step 5: Deploy with Mounted Config
|
|
|
|
**Cosmos JSON**:
|
|
```json
|
|
{
|
|
"minVersion": "0.8.0",
|
|
"services": {
|
|
"obfs4-bridge": {
|
|
"image": "r3bo0tbx1/onion-relay:latest",
|
|
"container_name": "obfs4-bridge",
|
|
"restart": "unless-stopped",
|
|
"network_mode": "host",
|
|
"environment": [
|
|
"TZ=UTC"
|
|
],
|
|
"volumes": [
|
|
{
|
|
"type": "volume",
|
|
"source": "obfs4-data",
|
|
"target": "/var/lib/tor"
|
|
},
|
|
{
|
|
"type": "bind",
|
|
"source": "/home/youruser/onion/bridge.conf",
|
|
"target": "/etc/tor/torrc",
|
|
"read_only": true
|
|
}
|
|
],
|
|
"security_opt": [
|
|
"no-new-privileges:true"
|
|
],
|
|
"labels": {
|
|
"cosmos-stack": "TorBridge",
|
|
"cosmos-stack-main": "obfs4-bridge",
|
|
"cosmos-description": "🌉 Hardened obfs4 Bridge v1.1.1",
|
|
"cosmos-icon": "https://iili.io/KsXP2Y7.png",
|
|
"cosmos-auto-update": "true",
|
|
"cosmos-auto-update-type": "registry",
|
|
"cosmos-force-network-secured": "false",
|
|
"cosmos-version": "1.1.1"
|
|
}
|
|
}
|
|
},
|
|
"volumes": {
|
|
"obfs4-data": {}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Key changes**:
|
|
- ✅ Removed ALL ENV variables
|
|
- ✅ Added mounted bridge.conf
|
|
- ✅ Updated image to 1.1.1
|
|
|
|
### Step 6: Deploy and Verify
|
|
|
|
```bash
|
|
# Import JSON in Cosmos UI and start
|
|
|
|
# Check logs
|
|
docker logs -f obfs4-bridge
|
|
# Expected:
|
|
# ✅ Using mounted configuration: /etc/tor/torrc
|
|
# ✅ Configuration is valid
|
|
# 🚀 Tor relay started
|
|
|
|
# Wait 30 seconds, then verify fingerprint
|
|
docker exec obfs4-bridge fingerprint
|
|
cat /tmp/bridge-fingerprint-backup.txt
|
|
# MUST MATCH!
|
|
|
|
# Check configuration
|
|
docker exec obfs4-bridge cat /etc/tor/torrc
|
|
# Should show BridgeRelay 1, obfs4 config, etc.
|
|
|
|
# Run health check
|
|
docker exec obfs4-bridge health | jq .
|
|
|
|
# Run full status
|
|
docker exec obfs4-bridge status
|
|
```
|
|
|
|
### Step 7: Get Bridge Line (After 24-48 Hours)
|
|
|
|
```bash
|
|
# Bridge line appears after Tor publishes to BridgeDB
|
|
docker exec obfs4-bridge bridge-line
|
|
```
|
|
|
|
### ✅ Success Criteria
|
|
|
|
- [ ] Container starts successfully
|
|
- [ ] Logs show "Using mounted configuration"
|
|
- [ ] Fingerprint matches backup (CRITICAL!)
|
|
- [ ] Bootstrap reaches 100%
|
|
- [ ] Bridge line available after 24-48 hours
|
|
|
|
---
|
|
|
|
## 🚨 Troubleshooting
|
|
|
|
### Issue 1: "Permission denied" on startup
|
|
|
|
**Symptom**:
|
|
```
|
|
Directory /var/lib/tor cannot be read: Permission denied
|
|
```
|
|
|
|
**Cause**: Volume ownership not fixed (still UID 101)
|
|
|
|
**Fix**:
|
|
```bash
|
|
docker stop obfs4-bridge
|
|
docker run --rm -v obfs4-data:/data alpine:3.23.3 chown -R 100:101 /data
|
|
docker start obfs4-bridge
|
|
```
|
|
|
|
### Issue 2: Different fingerprint after migration
|
|
|
|
**Symptom**: Fingerprint changed, new bridge identity
|
|
|
|
**Cause**: Bridge keys not preserved
|
|
|
|
**Fix**: Restore from backup:
|
|
```bash
|
|
docker stop obfs4-bridge
|
|
docker run --rm -v obfs4-data:/data -v /tmp:/backup alpine:3.23.3 \
|
|
sh -c 'rm -rf /data/* && tar xzf /backup/obfs4-data-backup-*.tar.gz -C / && chown -R 100:101 /data'
|
|
docker start obfs4-bridge
|
|
```
|
|
|
|
### Issue 3: "TOR_CONTACT_INFO contains invalid characters"
|
|
|
|
**Symptom**: Container in restart loop with validation error
|
|
|
|
**Cause**: Fixed in v1.1.1 - validation was too strict
|
|
|
|
**Solution**: Use mounted config instead of ENV variables (see Step 3-5 above)
|
|
|
|
### Issue 4: Container restart loop (general)
|
|
|
|
**Debug**:
|
|
```bash
|
|
# Check logs
|
|
docker logs obfs4-bridge --tail 50
|
|
|
|
# Check if it's actually using new image
|
|
docker inspect obfs4-bridge --format='{{.Image}}'
|
|
docker images r3bo0tbx1/onion-relay:latest --format='{{.ID}}'
|
|
# IDs must match!
|
|
|
|
# If IDs don't match: remove and recreate container
|
|
docker stop obfs4-bridge
|
|
docker rm obfs4-bridge
|
|
# Then redeploy
|
|
```
|
|
|
|
### Issue 5: Health check failing
|
|
|
|
**Symptom**: Container marked unhealthy
|
|
|
|
**Cause**: Old health check used hardcoded path
|
|
|
|
**Fix**: v1.1.1 includes smart healthcheck.sh that works with both mounted and ENV configs. Just update to 1.1.1 image.
|
|
|
|
---
|
|
|
|
## 📊 Comparison: ENV vs Mounted Config
|
|
|
|
| Aspect | ENV Variables | Mounted Config |
|
|
|--------|---------------|----------------|
|
|
| **Complexity** | Medium | Simple |
|
|
| **Validation** | Strict (can cause issues) | Minimal (tor validates) |
|
|
| **Debugging** | Harder | Easier (just cat file) |
|
|
| **Updates** | Restart container | Edit file + restart |
|
|
| **Recommended** | No ⚠️ | **Yes** ✅ |
|
|
| **Use Case** | Quick testing | Production |
|
|
|
|
**Recommendation**: Always use mounted config for production deployments.
|
|
|
|
---
|
|
|
|
## 🎯 Pre-Migration Checklist
|
|
|
|
### For All Migrations
|
|
- [ ] Current fingerprint saved to file
|
|
- [ ] Volumes backed up with timestamps
|
|
- [ ] Old container can be removed (stopped first)
|
|
- [ ] Firewall rules documented
|
|
- [ ] Testing plan prepared
|
|
|
|
### For Bridge from Official Image
|
|
- [ ] Volume ownership fix command prepared
|
|
- [ ] bridge.conf file created and customized
|
|
- [ ] Backup includes pt_state/obfs4_state.json
|
|
- [ ] Expected fingerprint documented
|
|
|
|
### Post-Migration
|
|
- [ ] Fingerprint matches backup
|
|
- [ ] Container starts without errors
|
|
- [ ] Bootstrap reaches 100%
|
|
- [ ] Diagnostic tools work (status, health, fingerprint, gen-family)
|
|
- [ ] Monitoring updated (if applicable)
|
|
|
|
---
|
|
|
|
## 📚 Additional Resources
|
|
|
|
- **Security Policy**: `../SECURITY.md`
|
|
- **General Migration Guide**: `MIGRATION.md`
|
|
- **Troubleshooting**: `docs/TROUBLESHOOTING-BRIDGE-MIGRATION.md`
|
|
- **Tools Documentation**: `docs/TOOLS.md`
|
|
- **Deployment Guide**: `docs/DEPLOYMENT.md`
|
|
|
|
---
|
|
|
|
## 🔒 Security Notes
|
|
|
|
### What's Fixed in v1.1.1
|
|
|
|
1. **Command Injection** (CRITICAL): OBFS4V_* variables now validated with whitelist
|
|
2. **Health Check** (CRITICAL): Works with both mounted and ENV configs
|
|
3. **Input Validation** (CRITICAL): Comprehensive validation with whitespace trimming
|
|
4. **Permissions** (HIGH): Removed non-functional chown attempt
|
|
5. **Contact Info Validation** (HIGH): Fixed false positives
|
|
|
|
### Risk Assessment
|
|
|
|
**Before Migration**: MEDIUM (using v1.1.0 with known vulnerabilities)
|
|
**After Migration**: LOW (all critical vulnerabilities patched)
|
|
|
|
**Recommendation**: Migrate as soon as possible to address security fixes.
|
|
|
|
---
|
|
|
|
*Last Updated: 2025-12-05*
|
|
*Validated with production deployments*
|