mirror of
https://github.com/r3bo0tbx1/tor-guard-relay.git
synced 2026-04-06 00:32:04 +02:00
🛠️ chore: update scripts and documentation for v1.1.3 release
This commit is contained in:
@@ -1,65 +1,40 @@
|
||||
#!/bin/sh
|
||||
# docker-entrypoint.sh - Tor Guard Relay initialization and process management
|
||||
# 🆕 v1.1.2 - Ultra-optimized 16.8 MB build with multi-mode support
|
||||
|
||||
set -e
|
||||
|
||||
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
# ENV Variable Compatibility Layer
|
||||
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
# Supports BOTH naming conventions for maximum compatibility:
|
||||
#
|
||||
# 1. Our naming (TOR_* prefix):
|
||||
# - TOR_NICKNAME, TOR_CONTACT_INFO, TOR_ORPORT, TOR_OBFS4_PORT, etc.
|
||||
#
|
||||
# 2. Official Tor Project bridge naming (for compatibility):
|
||||
# - NICKNAME, EMAIL, OR_PORT, PT_PORT, OBFS4V_* (additional torrc options)
|
||||
#
|
||||
# Priority: Official names override TOR_* defaults (for drop-in compatibility)
|
||||
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
# Map official bridge ENV vars to our internal TOR_* prefix
|
||||
# Official naming takes precedence over TOR_* defaults from Dockerfile
|
||||
[ -n "${NICKNAME:-}" ] && TOR_NICKNAME="$NICKNAME"
|
||||
[ -n "${EMAIL:-}" ] && TOR_CONTACT_INFO="$EMAIL"
|
||||
[ -n "${OR_PORT:-}" ] && TOR_ORPORT="$OR_PORT"
|
||||
[ -n "${PT_PORT:-}" ] && TOR_OBFS4_PORT="$PT_PORT"
|
||||
|
||||
# Auto-detect bridge mode if PT_PORT is set (official bridge convention)
|
||||
if [ -n "${PT_PORT:-}" ] && [ "${TOR_RELAY_MODE:-guard}" = "guard" ]; then
|
||||
TOR_RELAY_MODE="bridge"
|
||||
fi
|
||||
|
||||
# Configuration
|
||||
readonly TOR_CONFIG="${TOR_CONFIG:-/etc/tor/torrc}"
|
||||
readonly TOR_DATA_DIR="${TOR_DATA_DIR:-/var/lib/tor}"
|
||||
readonly TOR_LOG_DIR="${TOR_LOG_DIR:-/var/log/tor}"
|
||||
readonly TOR_RELAY_MODE="${TOR_RELAY_MODE:-guard}"
|
||||
|
||||
# Global PID tracking for cleanup
|
||||
TOR_PID=""
|
||||
TAIL_PID=""
|
||||
|
||||
# Emoji logging helpers (v1.1.0 style)
|
||||
log() { printf "%s\n" "$1"; }
|
||||
info() { printf " ℹ️ %s\n" "$1"; }
|
||||
success() { printf "✅ %s\n" "$1"; }
|
||||
warn() { printf "🛑 %s\n" "$1"; }
|
||||
die() { printf "🛑 ERROR: %s\n" "$1"; exit 1; }
|
||||
|
||||
# Signal handler for graceful shutdown
|
||||
trap 'cleanup_and_exit' SIGTERM SIGINT
|
||||
|
||||
cleanup_and_exit() {
|
||||
log ""
|
||||
warn "Shutdown signal received. Stopping Tor relay..."
|
||||
|
||||
# Stop log tail process first
|
||||
if [ -n "$TAIL_PID" ] && kill -0 "$TAIL_PID" 2>/dev/null; then
|
||||
kill -TERM "$TAIL_PID" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Stop Tor process
|
||||
if [ -n "$TOR_PID" ] && kill -0 "$TOR_PID" 2>/dev/null; then
|
||||
log " Sending SIGTERM to Tor (PID: $TOR_PID)..."
|
||||
kill -TERM "$TOR_PID" 2>/dev/null || true
|
||||
@@ -73,15 +48,13 @@ cleanup_and_exit() {
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Startup banner
|
||||
startup_banner() {
|
||||
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
log "🧅 Tor Guard Relay v1.1.2 - Initialization"
|
||||
log "🧅 Tor Guard Relay v1.1.3 - Initialization"
|
||||
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
log ""
|
||||
}
|
||||
|
||||
# Phase 1: Directory setup
|
||||
phase_1_directories() {
|
||||
log "🗂️ Phase 1: Directory Structure"
|
||||
mkdir -p "$TOR_DATA_DIR" "$TOR_LOG_DIR" /run/tor /tmp
|
||||
@@ -91,7 +64,6 @@ phase_1_directories() {
|
||||
log " • Logs: $TOR_LOG_DIR"
|
||||
log " • Run: /run/tor"
|
||||
|
||||
# Show disk space
|
||||
if command -v df >/dev/null 2>&1; then
|
||||
available=$(df -h "$TOR_DATA_DIR" 2>/dev/null | tail -n 1 | awk '{print $4}' || echo "unknown")
|
||||
log " 💽 Available disk space: $available"
|
||||
@@ -99,12 +71,9 @@ phase_1_directories() {
|
||||
log ""
|
||||
}
|
||||
|
||||
# Phase 2: Permissions
|
||||
phase_2_permissions() {
|
||||
log "🔐 Phase 2: Permission Hardening"
|
||||
|
||||
# Note: Ownership is set at build time by Dockerfile (chown requires root)
|
||||
# Only set directory permissions (chmod doesn't require ownership)
|
||||
chmod 700 "$TOR_DATA_DIR" 2>/dev/null || warn "Failed to set data directory permissions (may be read-only mount)"
|
||||
chmod 755 "$TOR_LOG_DIR" 2>/dev/null || warn "Failed to set log directory permissions (may be read-only mount)"
|
||||
|
||||
@@ -112,13 +81,11 @@ phase_2_permissions() {
|
||||
log ""
|
||||
}
|
||||
|
||||
# Validate relay configuration parameters
|
||||
validate_relay_config() {
|
||||
# Validate relay mode
|
||||
if [ -n "${TOR_RELAY_MODE:-}" ]; then
|
||||
case "$TOR_RELAY_MODE" in
|
||||
guard|middle|exit|bridge)
|
||||
: # Valid
|
||||
:
|
||||
;;
|
||||
*)
|
||||
die "TOR_RELAY_MODE must be: guard, middle, exit, or bridge (got: $TOR_RELAY_MODE)"
|
||||
@@ -126,17 +93,14 @@ validate_relay_config() {
|
||||
esac
|
||||
fi
|
||||
|
||||
# Validate nickname (1-19 alphanumeric characters)
|
||||
if [ -n "${TOR_NICKNAME:-}" ]; then
|
||||
nickname_len=$(printf "%s" "$TOR_NICKNAME" | wc -c)
|
||||
if [ "$nickname_len" -lt 1 ] || [ "$nickname_len" -gt 19 ]; then
|
||||
die "TOR_NICKNAME must be 1-19 characters (got: $nickname_len)"
|
||||
fi
|
||||
# Check for invalid characters (busybox-compatible)
|
||||
if ! printf "%s" "$TOR_NICKNAME" | grep -qE '^[a-zA-Z0-9]+$'; then
|
||||
die "TOR_NICKNAME must contain only alphanumeric characters"
|
||||
fi
|
||||
# Check for reserved names
|
||||
case "$(printf "%s" "$TOR_NICKNAME" | tr '[:upper:]' '[:lower:]')" in
|
||||
unnamed|noname|default|tor|relay|bridge|exit)
|
||||
die "TOR_NICKNAME cannot use reserved name: $TOR_NICKNAME"
|
||||
@@ -144,52 +108,39 @@ validate_relay_config() {
|
||||
esac
|
||||
fi
|
||||
|
||||
# Validate contact info is not empty if set
|
||||
if [ -n "${TOR_CONTACT_INFO:-}" ]; then
|
||||
# Trim leading/trailing whitespace (fixes Cosmos ENV variable padding)
|
||||
TOR_CONTACT_INFO="$(printf "%s" "$TOR_CONTACT_INFO" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
||||
|
||||
contact_len=$(printf "%s" "$TOR_CONTACT_INFO" | wc -c)
|
||||
if [ "$contact_len" -lt 3 ]; then
|
||||
die "TOR_CONTACT_INFO must be at least 3 characters"
|
||||
fi
|
||||
|
||||
# Check for embedded newlines using wc -l (more reliable than grep with escape sequences)
|
||||
line_count=$(printf "%s" "$TOR_CONTACT_INFO" | wc -l)
|
||||
if [ "$line_count" -gt 0 ]; then
|
||||
die "TOR_CONTACT_INFO cannot contain newlines (got $line_count lines)"
|
||||
fi
|
||||
|
||||
# Note: We don't check for null bytes as printf would truncate the string anyway
|
||||
# Email addresses are safe to use in torrc without additional escaping
|
||||
fi
|
||||
|
||||
# Validate port numbers (1024-65535)
|
||||
for port_var in TOR_ORPORT TOR_DIRPORT TOR_OBFS4_PORT; do
|
||||
eval "port_val=\${$port_var:-}"
|
||||
if [ -n "$port_val" ]; then
|
||||
# Check if it's a valid integer
|
||||
if ! printf "%s" "$port_val" | grep -qE '^[0-9]+$'; then
|
||||
die "$port_var must be a valid port number (got: $port_val)"
|
||||
fi
|
||||
# Check range (allow 0 for DirPort to disable it)
|
||||
if [ "$port_var" = "TOR_DIRPORT" ] && [ "$port_val" -eq 0 ]; then
|
||||
: # Allow 0 for DirPort
|
||||
:
|
||||
elif [ "$port_val" -lt 1 ] || [ "$port_val" -gt 65535 ]; then
|
||||
die "$port_var must be between 1-65535 (got: $port_val)"
|
||||
fi
|
||||
# Warn about privileged ports
|
||||
if [ "$port_val" -lt 1024 ] && [ "$port_val" -ne 0 ]; then
|
||||
warn "$port_var using privileged port $port_val (may require CAP_NET_BIND_SERVICE)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Validate bandwidth values if set
|
||||
for bw_var in TOR_BANDWIDTH_RATE TOR_BANDWIDTH_BURST; do
|
||||
eval "bw_val=\${$bw_var:-}"
|
||||
if [ -n "$bw_val" ]; then
|
||||
# Check for valid Tor bandwidth format (e.g., "10 MB", "1 GB")
|
||||
if ! printf "%s" "$bw_val" | grep -qE '^[0-9]+ ?(Bytes?|KBytes?|MBytes?|GBytes?|TBytes?|KB?|MB?|GB?|TB?)$'; then
|
||||
die "$bw_var has invalid format (got: $bw_val, expected: '10 MB' or '1 GB')"
|
||||
fi
|
||||
@@ -197,15 +148,12 @@ validate_relay_config() {
|
||||
done
|
||||
}
|
||||
|
||||
# Phase 3: Configuration
|
||||
phase_3_configuration() {
|
||||
log "🔧 Phase 3: Configuration Setup"
|
||||
|
||||
# Priority 1: Mounted config file
|
||||
if [ -f "$TOR_CONFIG" ] && [ -s "$TOR_CONFIG" ]; then
|
||||
success "Using mounted configuration: $TOR_CONFIG"
|
||||
CONFIG_SOURCE="mounted"
|
||||
# Priority 2: Environment variables
|
||||
elif [ -n "${TOR_NICKNAME:-}" ] && [ -n "${TOR_CONTACT_INFO:-}" ]; then
|
||||
log " Generating configuration from environment variables..."
|
||||
validate_relay_config
|
||||
@@ -219,7 +167,6 @@ phase_3_configuration() {
|
||||
log ""
|
||||
}
|
||||
|
||||
# Generate torrc from environment variables
|
||||
generate_config_from_env() {
|
||||
cat > "$TOR_CONFIG" << EOF
|
||||
# Generated Tor configuration for ${TOR_RELAY_MODE} relay
|
||||
@@ -242,7 +189,6 @@ Log notice stdout
|
||||
|
||||
EOF
|
||||
|
||||
# Mode-specific configuration
|
||||
case "$TOR_RELAY_MODE" in
|
||||
guard|middle)
|
||||
cat >> "$TOR_CONFIG" << EOF
|
||||
@@ -289,52 +235,34 @@ EOF
|
||||
[ -n "${TOR_BANDWIDTH_RATE:-}" ] && echo "RelayBandwidthRate ${TOR_BANDWIDTH_RATE}" >> "$TOR_CONFIG"
|
||||
[ -n "${TOR_BANDWIDTH_BURST:-}" ] && echo "RelayBandwidthBurst ${TOR_BANDWIDTH_BURST}" >> "$TOR_CONFIG"
|
||||
|
||||
# Process OBFS4V_* additional variables (official Tor Project bridge compatibility)
|
||||
# SECURITY: Strict validation to prevent injection attacks
|
||||
if [ "${OBFS4_ENABLE_ADDITIONAL_VARIABLES:-0}" = "1" ]; then
|
||||
echo "" >> "$TOR_CONFIG"
|
||||
echo "# Additional torrc options from OBFS4V_* environment variables" >> "$TOR_CONFIG"
|
||||
|
||||
# Get OBFS4V_* variables safely
|
||||
env | grep '^OBFS4V_' | sort | while IFS='=' read -r key value; do
|
||||
# Strip OBFS4V_ prefix to get torrc option name
|
||||
torrc_key="${key#OBFS4V_}"
|
||||
|
||||
# SECURITY: Validate torrc_key (must be alphanumeric with underscores)
|
||||
if ! printf "%s" "$torrc_key" | grep -qE '^[a-zA-Z][a-zA-Z0-9_]*$'; then
|
||||
warn "Skipping invalid OBFS4V variable name: $key (must be alphanumeric)"
|
||||
continue
|
||||
fi
|
||||
|
||||
# SECURITY: Validate value doesn't contain dangerous characters
|
||||
# Reject actual newlines (not the literal \n), nulls, and control chars
|
||||
# Use wc -l to detect real newlines (busybox-compatible)
|
||||
line_count=$(printf "%s" "$value" | wc -l)
|
||||
if [ "$line_count" -gt 0 ]; then
|
||||
warn "Skipping $key: value contains newlines ($line_count lines)"
|
||||
continue
|
||||
fi
|
||||
# Check for null bytes or other control characters (ASCII < 32, except space)
|
||||
if printf "%s" "$value" | tr -d '[ -~]' | grep -q .; then
|
||||
warn "Skipping $key: value contains control characters"
|
||||
continue
|
||||
fi
|
||||
|
||||
# SECURITY: Whitelist known safe torrc options for OBFS4V_*
|
||||
# Only allow specific torrc directives that are safe for bridges
|
||||
case "$torrc_key" in
|
||||
# Safe torrc options for bridges
|
||||
AccountingMax|AccountingStart|Address|AddressDisableIPv6|\
|
||||
BandwidthBurst|BandwidthRate|RelayBandwidthBurst|RelayBandwidthRate|\
|
||||
ContactInfo|DirPort|MaxMemInQueues|NumCPUs|ORPort|\
|
||||
OutboundBindAddress|OutboundBindAddressOR|Nickname|\
|
||||
ServerDNSAllowBrokenConfig|ServerDNSDetectHijacking)
|
||||
# Safe - write to config
|
||||
# Use printf to ensure proper escaping
|
||||
printf "%s %s\n" "$torrc_key" "$value" >> "$TOR_CONFIG"
|
||||
;;
|
||||
*)
|
||||
# Unknown/potentially dangerous option - reject
|
||||
warn "Skipping $key: torrc option '$torrc_key' not in whitelist"
|
||||
warn " If you need this option, mount a custom torrc file instead"
|
||||
;;
|
||||
@@ -349,11 +277,9 @@ EOF
|
||||
esac
|
||||
}
|
||||
|
||||
# Phase 4: Validation
|
||||
phase_4_validation() {
|
||||
log "🔎 Phase 4: Configuration Validation"
|
||||
|
||||
# Check Tor binary
|
||||
if ! command -v tor >/dev/null 2>&1; then
|
||||
die "Tor binary not found in PATH"
|
||||
fi
|
||||
@@ -361,17 +287,14 @@ phase_4_validation() {
|
||||
TOR_VERSION=$(tor --version 2>/dev/null | head -n1 || echo "unknown")
|
||||
log " 📦 Tor version: $TOR_VERSION"
|
||||
|
||||
# Validate config syntax
|
||||
log " Validating torrc syntax..."
|
||||
|
||||
# SECURITY: Set trap BEFORE creating temp file to prevent leaks
|
||||
VERIFY_TMP=""
|
||||
cleanup_verify_tmp() {
|
||||
[ -n "$VERIFY_TMP" ] && rm -f "$VERIFY_TMP"
|
||||
}
|
||||
trap cleanup_verify_tmp EXIT INT TERM
|
||||
|
||||
# Create temp file in secure location
|
||||
VERIFY_TMP=$(mktemp -t tor-verify.XXXXXX)
|
||||
|
||||
if ! tor --verify-config -f "$TOR_CONFIG" >"$VERIFY_TMP" 2>&1; then
|
||||
@@ -389,7 +312,6 @@ phase_4_validation() {
|
||||
log ""
|
||||
}
|
||||
|
||||
# Phase 5: Build info
|
||||
phase_5_build_info() {
|
||||
log "📊 Phase 5: Build Information"
|
||||
|
||||
@@ -406,7 +328,6 @@ phase_5_build_info() {
|
||||
log ""
|
||||
}
|
||||
|
||||
# Phase 6: Diagnostic tools
|
||||
phase_6_diagnostics() {
|
||||
log "🧩 Phase 6: Available Diagnostic Tools"
|
||||
log ""
|
||||
@@ -418,14 +339,12 @@ phase_6_diagnostics() {
|
||||
log ""
|
||||
}
|
||||
|
||||
# Launch Tor
|
||||
launch_tor() {
|
||||
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
success "Starting Tor relay..."
|
||||
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
log ""
|
||||
|
||||
# Start Tor in background
|
||||
tor -f "$TOR_CONFIG" &
|
||||
TOR_PID=$!
|
||||
|
||||
@@ -434,14 +353,12 @@ launch_tor() {
|
||||
log "📋 Tor bootstrap logs:"
|
||||
log ""
|
||||
|
||||
# Wait for log file to be created (max 5 seconds)
|
||||
log_wait=0
|
||||
while [ ! -f "$TOR_LOG_DIR/notices.log" ] && [ $log_wait -lt 50 ]; do
|
||||
sleep 0.1
|
||||
log_wait=$((log_wait + 1))
|
||||
done
|
||||
|
||||
# Tail Tor logs to stdout in background (if log file exists)
|
||||
if [ -f "$TOR_LOG_DIR/notices.log" ]; then
|
||||
tail -F "$TOR_LOG_DIR/notices.log" 2>/dev/null &
|
||||
TAIL_PID=$!
|
||||
@@ -449,11 +366,9 @@ launch_tor() {
|
||||
warn "Log file not created yet, bootstrap messages will not be shown"
|
||||
fi
|
||||
|
||||
# Wait for Tor process
|
||||
wait "$TOR_PID"
|
||||
TOR_EXIT_CODE=$?
|
||||
|
||||
# Stop tail process if still running
|
||||
if [ -n "$TAIL_PID" ] && kill -0 "$TAIL_PID" 2>/dev/null; then
|
||||
kill -TERM "$TAIL_PID" 2>/dev/null || true
|
||||
fi
|
||||
@@ -463,7 +378,6 @@ launch_tor() {
|
||||
cleanup_and_exit
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
startup_banner
|
||||
phase_1_directories
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
#!/bin/sh
|
||||
# healthcheck.sh - Docker HEALTHCHECK wrapper 🐋💚
|
||||
# Validates Tor configuration regardless of source (mounted file or ENV vars)
|
||||
# Validates Tor configuration regardless of source (mounted file or ENV vars) 🐋💚
|
||||
|
||||
set -e
|
||||
|
||||
TOR_CONFIG="${TOR_CONFIG:-/etc/tor/torrc}"
|
||||
|
||||
# Check if config file exists and is readable
|
||||
if [ ! -f "$TOR_CONFIG" ]; then
|
||||
echo "ERROR: Config file not found: $TOR_CONFIG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -r "$TOR_CONFIG" ]; then
|
||||
echo "ERROR: Config file not readable: $TOR_CONFIG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify Tor configuration
|
||||
if tor --verify-config -f "$TOR_CONFIG" >/dev/null 2>&1; then
|
||||
# Config is valid
|
||||
exit 0
|
||||
else
|
||||
echo "ERROR: Invalid Tor configuration"
|
||||
|
||||
@@ -44,6 +44,7 @@ You can configure Tor relays using **TWO methods**:
|
||||
docker run -d \
|
||||
--name tor-bridge \
|
||||
--network host \
|
||||
--security-opt no-new-privileges:true \
|
||||
-e TOR_RELAY_MODE=bridge \
|
||||
-e TOR_NICKNAME=MyBridge \
|
||||
-e TOR_CONTACT_INFO=admin@example.com \
|
||||
@@ -293,6 +294,6 @@ If you still see this error after updating to v1.1.1:
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.1.2
|
||||
**Last Updated:** 2025-11-18
|
||||
**Version:** 1.1.3
|
||||
**Last Updated:** 2025-12-05
|
||||
**Maintainer:** rE-Bo0t.bx1 <r3bo0tbx1@brokenbotnet.com>
|
||||
|
||||
@@ -6,9 +6,8 @@ PT_STATE_DIR="${TOR_DATA_DIR}/pt_state"
|
||||
BRIDGE_LINE_FILE="${PT_STATE_DIR}/obfs4_bridgeline.txt"
|
||||
TORRC_FILE="${TOR_CONFIG:-/etc/tor/torrc}"
|
||||
|
||||
# Check if we're running as a bridge
|
||||
if [ -f "$TORRC_FILE" ] && grep -q "^BridgeRelay 1" "$TORRC_FILE" 2>/dev/null; then
|
||||
: # Bridge mode confirmed
|
||||
:
|
||||
elif [ -f "$TORRC_FILE" ]; then
|
||||
echo ""
|
||||
echo "❌ Not a bridge relay"
|
||||
@@ -26,7 +25,6 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for bridge line file
|
||||
if [ -f "$BRIDGE_LINE_FILE" ]; then
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
@@ -53,7 +51,6 @@ if [ -f "$BRIDGE_LINE_FILE" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Bridge line not available yet
|
||||
echo ""
|
||||
echo "⏳ Bridge line not available yet"
|
||||
echo ""
|
||||
@@ -74,7 +71,6 @@ echo " 4. Verify bridge config:"
|
||||
echo " docker exec <container> grep BridgeRelay $TORRC_FILE"
|
||||
echo ""
|
||||
|
||||
# Try to find bridge line in logs as fallback
|
||||
if [ -f "/var/log/tor/notices.log" ]; then
|
||||
if grep -q "bridge line" /var/log/tor/notices.log 2>/dev/null; then
|
||||
echo "📝 Found in logs:"
|
||||
|
||||
@@ -10,7 +10,6 @@ if [ -f "$FINGERPRINT_FILE" ]; then
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
# Read and format fingerprint
|
||||
NICKNAME=$(cat "$FINGERPRINT_FILE" | awk '{print $1}')
|
||||
FINGERPRINT=$(cat "$FINGERPRINT_FILE" | awk '{print $2}')
|
||||
|
||||
@@ -18,11 +17,9 @@ if [ -f "$FINGERPRINT_FILE" ]; then
|
||||
echo " 🔐 Fingerprint: $FINGERPRINT"
|
||||
echo ""
|
||||
|
||||
# Format for easy copying
|
||||
echo " 📋 Copy/paste: $NICKNAME $FINGERPRINT"
|
||||
echo ""
|
||||
|
||||
# Show search URL
|
||||
echo " 🔍 Find on Tor Metrics:"
|
||||
echo " https://metrics.torproject.org/rs.html#search/$FINGERPRINT"
|
||||
echo ""
|
||||
|
||||
@@ -4,25 +4,21 @@
|
||||
TOR_LOG="${TOR_LOG_DIR:-/var/log/tor}/notices.log"
|
||||
TOR_DATA="${TOR_DATA_DIR:-/var/lib/tor}"
|
||||
|
||||
# Sanitize numeric values to prevent "bad number" errors
|
||||
sanitize_num() {
|
||||
v=$(printf '%s' "$1" | tr -cd '0-9')
|
||||
[ -z "$v" ] && v=0
|
||||
printf '%s' "$v"
|
||||
}
|
||||
|
||||
# Check if running
|
||||
if ! pgrep -x tor >/dev/null 2>&1; then
|
||||
echo '{"status":"down","bootstrap":0,"reachable":"unknown","errors":0}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get PID and uptime
|
||||
TOR_PID=$(pgrep -x tor)
|
||||
TOR_PID=$(sanitize_num "$TOR_PID")
|
||||
UPTIME=$(ps -o etime= -p "$TOR_PID" 2>/dev/null | tr -d ' ' || echo "unknown")
|
||||
|
||||
# Check bootstrap
|
||||
BOOTSTRAP=0
|
||||
if [ -f "$TOR_LOG" ]; then
|
||||
if grep -q "Bootstrapped 100%" "$TOR_LOG"; then
|
||||
@@ -33,7 +29,6 @@ if [ -f "$TOR_LOG" ]; then
|
||||
fi
|
||||
BOOTSTRAP=$(sanitize_num "$BOOTSTRAP")
|
||||
|
||||
# Check reachability
|
||||
REACHABLE="unknown"
|
||||
if [ -f "$TOR_LOG" ]; then
|
||||
if grep -q "Self-testing indicates your ORPort is reachable" "$TOR_LOG"; then
|
||||
@@ -43,11 +38,9 @@ if [ -f "$TOR_LOG" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Count errors
|
||||
ERRORS=$(grep -c "\[err\]" "$TOR_LOG" 2>/dev/null || echo "0")
|
||||
ERRORS=$(sanitize_num "$ERRORS")
|
||||
|
||||
# Get nickname and fingerprint
|
||||
NICKNAME="unknown"
|
||||
FINGERPRINT="unknown"
|
||||
if [ -f "$TOR_DATA/fingerprint" ]; then
|
||||
@@ -55,7 +48,6 @@ if [ -f "$TOR_DATA/fingerprint" ]; then
|
||||
FINGERPRINT=$(cat "$TOR_DATA/fingerprint" | awk '{print $2}')
|
||||
fi
|
||||
|
||||
# Output comprehensive JSON
|
||||
cat <<EOF
|
||||
{
|
||||
"status": "up",
|
||||
|
||||
10
tools/status
10
tools/status
@@ -4,21 +4,18 @@
|
||||
TOR_LOG="${TOR_LOG_DIR:-/var/log/tor}/notices.log"
|
||||
TOR_DATA="${TOR_DATA_DIR:-/var/lib/tor}"
|
||||
|
||||
# Sanitize numeric values to prevent "bad number" errors
|
||||
sanitize_num() {
|
||||
v=$(printf '%s' "$1" | tr -cd '0-9')
|
||||
[ -z "$v" ] && v=0
|
||||
printf '%s' "$v"
|
||||
}
|
||||
|
||||
# Header
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "🧅 Tor Relay Status"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
# Check if Tor is running
|
||||
if pgrep -x tor >/dev/null 2>&1; then
|
||||
TOR_PID=$(pgrep -x tor)
|
||||
echo "🚀 Status: RUNNING (PID: $TOR_PID)"
|
||||
@@ -28,14 +25,12 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check log file
|
||||
if [ ! -f "$TOR_LOG" ]; then
|
||||
echo "⚠️ Log: NOT FOUND"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Bootstrap progress
|
||||
if grep -q "Bootstrapped 100%" "$TOR_LOG" 2>/dev/null; then
|
||||
echo "✅ Bootstrap: 100% COMPLETE"
|
||||
else
|
||||
@@ -44,7 +39,6 @@ else
|
||||
echo "⏳ Bootstrap: ${PROGRESS}%"
|
||||
fi
|
||||
|
||||
# Reachability
|
||||
if grep -q "Self-testing indicates your ORPort is reachable" "$TOR_LOG"; then
|
||||
echo "🌐 ORPort: REACHABLE"
|
||||
elif grep -q "ORPort is not reachable" "$TOR_LOG"; then
|
||||
@@ -53,19 +47,16 @@ else
|
||||
echo "❓ ORPort: TESTING..."
|
||||
fi
|
||||
|
||||
# Get relay info (POSIX-compliant fingerprint truncation)
|
||||
if [ -f "$TOR_DATA/fingerprint" ] && [ -r "$TOR_DATA/fingerprint" ]; then
|
||||
FINGERPRINT=$(cat "$TOR_DATA/fingerprint" | awk '{print $2}')
|
||||
NICKNAME=$(cat "$TOR_DATA/fingerprint" | awk '{print $1}')
|
||||
echo "🪪 Nickname: $NICKNAME"
|
||||
|
||||
# POSIX-compliant substring extraction using cut
|
||||
FP_START=$(printf "%s" "$FINGERPRINT" | cut -c1-8)
|
||||
FP_END=$(printf "%s" "$FINGERPRINT" | cut -c33-40)
|
||||
echo "🔑 Fingerprint: ${FP_START}...${FP_END}"
|
||||
fi
|
||||
|
||||
# Count errors and warnings
|
||||
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")
|
||||
@@ -81,7 +72,6 @@ if [ "$WARNINGS" -gt 5 ]; then
|
||||
echo "⚠️ Warnings: $WARNINGS"
|
||||
fi
|
||||
|
||||
# Uptime
|
||||
UPTIME=$(ps -o etime= -p "$TOR_PID" 2>/dev/null | tr -d ' ' || echo "unknown")
|
||||
[ -n "$UPTIME" ] && echo "⏱️ Uptime: $UPTIME"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user