This repository has no description
3.0 kB
110 lines
1#!/usr/bin/env bash
2set -euo pipefail
3set -x
4
5# Create temporary directory for this tor instance
6TOR_DIR=$(mktemp -d -t tornade.XXXXXX)
7trap 'rm -rf "$TOR_DIR"' EXIT
8
9# Generate random ports
10SOCKS_PORT=$((9050 + RANDOM % 1000))
11CONTROL_PORT=$((SOCKS_PORT + 1))
12
13# Create tor configuration
14cat > "$TOR_DIR/torrc" <<EOF
15DataDirectory $TOR_DIR/data
16SocksPort 127.0.0.1:$SOCKS_PORT
17ControlPort 127.0.0.1:$CONTROL_PORT
18Log notice file $TOR_DIR/tor.log
19RunAsDaemon 0
20
21# Performance and reliability optimizations
22CircuitBuildTimeout 15
23LearnCircuitBuildTimeout 0
24NumEntryGuards 8
25KeepalivePeriod 60
26SocksTimeout 120
27
28# Reliability settings
29MaxCircuitDirtiness 600
30NewCircuitPeriod 30
31UseEntryGuards 1
32EOF
33
34# Start tor in background - suppress output to avoid protocol interference
35tor -f "$TOR_DIR/torrc" >/dev/null 2>&1 &
36TOR_PID=$!
37
38# Function to cleanup tor process
39cleanup() {
40 if kill -0 "$TOR_PID" 2>/dev/null; then
41 kill "$TOR_PID" 2>/dev/null || true
42 wait "$TOR_PID" 2>/dev/null || true
43 fi
44 rm -rf "$TOR_DIR"
45}
46trap cleanup EXIT INT TERM
47
48# Retry up to 5 times to establish circuits
49for attempt in 1 2 3 4 5; do
50
51 if [ $attempt -gt 1 ]; then
52 # Kill previous tor instance and restart
53 kill "$TOR_PID" 2>/dev/null || true
54 wait "$TOR_PID" 2>/dev/null || true
55 tor -f "$TOR_DIR/torrc" >/dev/null 2>&1 &
56 TOR_PID=$!
57 fi
58
59 # Check frequently at first, then slow down - longer timeout per attempt
60 for i in {1..120}; do
61 # Check if log file exists and contains the success message
62 if [ -f "$TOR_DIR/tor.log" ] && grep -q "Bootstrapped 100%" "$TOR_DIR/tor.log" 2>/dev/null; then
63 # Success - exit both loops
64 break 2
65 fi
66 # If log file doesn't exist after 2 seconds, tor likely failed to start
67 if [ "$i" -eq 20 ] && [ ! -f "$TOR_DIR/tor.log" ]; then
68 # Log file wasn't created after 2 seconds - tor likely failed completely
69 # Exit with failure immediately rather than retrying
70 break
71 fi
72 # Check every 0.1s for first 2 seconds, then every 0.5s
73 if [ "$i" -le 20 ]; then
74 sleep 0.1
75 else
76 sleep 0.5
77 fi
78 done
79
80 # This attempt failed, continue to next attempt
81done
82
83# Final check - if still not ready after all attempts, exit
84if ! grep -q "Bootstrapped 100%" "$TOR_DIR/tor.log" 2>/dev/null; then
85 exit 1
86fi
87
88# Check if we're on Darwin
89if [[ "$(uname)" == "Darwin" ]]; then
90 if [[ "$1" == "ssh" ]]; then
91 # Direct SSH call - use old behavior
92 shift # remove 'ssh' from arguments
93 exec ssh -o ProxyCommand="nc -x 127.0.0.1:$SOCKS_PORT %h %p" "$@"
94 else
95 # Other commands - create SSH wrapper and add to PATH
96 SSH_WRAPPER="$TOR_DIR/ssh"
97 cat > "$SSH_WRAPPER" <<EOF
98#!/usr/bin/env bash
99# SSH wrapper that routes through Tor on Darwin
100exec /usr/bin/ssh -o ProxyCommand="nc -x 127.0.0.1:$SOCKS_PORT %h %p" "\$@"
101EOF
102 chmod +x "$SSH_WRAPPER"
103 export PATH="$TOR_DIR:$PATH"
104 fi
105fi
106
107# Execute the command
108export TORSOCKS_TOR_PORT=$SOCKS_PORT
109export TOR_CONTROL_PORT=$CONTROL_PORT
110exec torsocks "$@"