| #!/bin/bash |
| |
| |
| |
| set -uo pipefail |
|
|
| CONTROL_PORT=9051 |
| STALL_TIMEOUT=150 |
| |
| MAX_TRIES=3 |
| TORRC=/etc/tor/torrc |
| COOKIE=/var/lib/tor/control_auth_cookie |
|
|
| authenticate_and_query() { |
| |
| local cookie_hex |
| cookie_hex=$(xxd -p "$COOKIE" | tr -d '\n') |
| printf 'AUTHENTICATE %s\r\nGETINFO status/bootstrap-phase\r\nQUIT\r\n' "$cookie_hex" \ |
| | timeout 5 nc 127.0.0.1 "$CONTROL_PORT" 2>/dev/null |
| } |
|
|
| wait_for_bootstrap() { |
| local waited=0 |
| while (( waited < STALL_TIMEOUT )); do |
| [[ -r "$COOKIE" ]] || { sleep 1; ((waited++)); continue; } |
| local out |
| out=$(authenticate_and_query || true) |
| if echo "$out" | grep -q 'PROGRESS=100'; then |
| return 0 |
| fi |
| if echo "$out" | grep -qi 'BOOTSTRAP'; then |
| local progress |
| progress=$(echo "$out" | grep -oP 'PROGRESS=\K[0-9]+' || echo "?") |
| echo "[bootstrap-test] progress: ${progress}% (${waited}s/${STALL_TIMEOUT}s)" |
| fi |
| sleep 3 |
| ((waited+=3)) |
| done |
| return 1 |
| } |
|
|
| disable_current_bridge_line() { |
| |
| |
| local line |
| line=$(grep -n '^Bridge ' "$TORRC" | head -1 | cut -d: -f1) |
| if [[ -n "$line" ]]; then |
| sed -i "${line}s/^Bridge /# FAILED-Bridge /" "$TORRC" |
| echo "[bootstrap-test] disabled bridge on line ${line}, will retry with next transport" |
| fi |
| } |
|
|
| for attempt in $(seq 1 "$MAX_TRIES"); do |
| echo "[bootstrap-test] attempt ${attempt}/${MAX_TRIES}" |
| if wait_for_bootstrap; then |
| echo "[bootstrap-test] SUCCESS: bootstrapped to 100%" |
| exit 0 |
| fi |
| echo "[bootstrap-test] stalled after ${STALL_TIMEOUT}s, rotating bridge and restarting tor" |
| disable_current_bridge_line |
| pkill -HUP -x tor 2>/dev/null || true |
| sleep 3 |
| pkill -x tor 2>/dev/null || true |
| tor -f "$TORRC" & |
| done |
|
|
| echo "[bootstrap-test] FAILURE: exhausted all configured bridges" |
| exit 1 |
|
|