Files
tor-guard-relay/docs/MIGRATION-V1.1.X.md
rE-Bo0t.bx1 be4f2bc125 feat(v1.1.7): Happy Family support (Tor 0.4.9+ FamilyId)
🔧 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.
2026-03-02 16:23:10 +08:00

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*