This repository has no description
2.8 kB
102 lines
1#!/usr/bin/env bash
2set -euo pipefail
3
4# Check for existing Tor daemon (env var or default port 9050)
5EXISTING_TOR_PORT="${TOR_SOCKS_PORT:-9050}"
6if nc -z 127.0.0.1 "$EXISTING_TOR_PORT" 2>/dev/null; then
7 # Use existing Tor daemon - no startup/cleanup needed
8 export TORSOCKS_TOR_PORT=$EXISTING_TOR_PORT
9 if [[ "$(uname)" == "Darwin" ]]; then
10 if [[ "$1" == "ssh" ]]; then
11 shift
12 exec ssh -o ProxyCommand="nc -x 127.0.0.1:$EXISTING_TOR_PORT %h %p" "$@"
13 else
14 exec torsocks "$@"
15 fi
16 else
17 exec torsocks "$@"
18 fi
19fi
20
21# Create temporary directory for this tor instance
22TOR_DIR=$(mktemp -d -t tornade.XXXXXX)
23
24# Generate random ports in ephemeral range (49152-65535) to avoid collisions
25SOCKS_PORT=$((49152 + RANDOM % 16383))
26CONTROL_PORT=$((SOCKS_PORT + 1))
27
28# Track tor PID for cleanup
29TOR_PID=""
30
31# Cleanup function - must be defined before trap
32cleanup() {
33 if [ -n "$TOR_PID" ] && kill -0 "$TOR_PID" 2>/dev/null; then
34 kill "$TOR_PID" 2>/dev/null || true
35 wait "$TOR_PID" 2>/dev/null || true
36 fi
37 rm -rf "$TOR_DIR"
38}
39trap cleanup EXIT INT TERM
40
41# Create tor configuration
42cat > "$TOR_DIR/torrc" <<EOF
43DataDirectory $TOR_DIR/data
44SocksPort 127.0.0.1:$SOCKS_PORT
45ControlPort 127.0.0.1:$CONTROL_PORT
46Log notice file $TOR_DIR/tor.log
47RunAsDaemon 0
48
49# Hidden service optimizations - longer timeouts for .onion addresses
50CircuitBuildTimeout 60
51LearnCircuitBuildTimeout 0
52SocksTimeout 300
53
54# Keep circuits stable for longer sessions
55MaxCircuitDirtiness 900
56KeepalivePeriod 60
57EOF
58
59# Start tor in background - suppress output to avoid protocol interference
60tor -f "$TOR_DIR/torrc" >/dev/null 2>&1 &
61TOR_PID=$!
62
63# Wait for Tor to bootstrap (up to 90 seconds)
64for i in {1..90}; do
65 if [ -f "$TOR_DIR/tor.log" ] && grep -q "Bootstrapped 100%" "$TOR_DIR/tor.log" 2>/dev/null; then
66 break
67 fi
68 # If log file doesn't exist after 5 seconds, tor likely failed to start
69 if [ "$i" -eq 5 ] && [ ! -f "$TOR_DIR/tor.log" ]; then
70 exit 1
71 fi
72 sleep 1
73done
74
75# Final check - if still not ready after all attempts, exit
76if ! grep -q "Bootstrapped 100%" "$TOR_DIR/tor.log" 2>/dev/null; then
77 exit 1
78fi
79
80# Execute the command (don't use exec - need cleanup trap to run)
81export TORSOCKS_TOR_PORT=$SOCKS_PORT
82export TOR_CONTROL_PORT=$CONTROL_PORT
83
84if [[ "$(uname)" == "Darwin" ]]; then
85 if [[ "$1" == "ssh" ]]; then
86 # Direct SSH call via nc SOCKS proxy
87 shift
88 ssh -o ProxyCommand="nc -x 127.0.0.1:$SOCKS_PORT %h %p" "$@"
89 else
90 # Other commands - create SSH wrapper and add to PATH
91 SSH_WRAPPER="$TOR_DIR/ssh"
92 cat > "$SSH_WRAPPER" <<'SSHEOF'
93#!/usr/bin/env bash
94exec /usr/bin/ssh -o ProxyCommand="nc -x 127.0.0.1:$TORSOCKS_TOR_PORT %h %p" "$@"
95SSHEOF
96 chmod +x "$SSH_WRAPPER"
97 PATH="$TOR_DIR:$PATH" torsocks "$@"
98 fi
99else
100 torsocks "$@"
101fi
102# cleanup trap runs on exit