123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- #!/bin/bash
- cleanup() {
- kill $torpid
- rm -r "$datadir"
- [[ "$file" != "" ]] && rm "$file"
- }
- usage() {
- [[ "$@" != "" ]] && echo "$@"
- cat <<EOF
- Wrapper to start tor before starting applications with torsocks.
- Looks for free ports and starts a new instance of tor.
- Usage: $me [${me}_options] -- command [command_options]
- Options:
- -C Use a control port which is always one higher than the listening port.
- -f str Save port and controlport to this file, in shell-sourcable format.
- -E Use a selection of European entry/exit nodes: $Ecountries
- -c str List of countries to use (note the format above).
- The default is to not restrict the choice of entry/exit nodes.
- -P int Set Tor SOCKS localhost listening port. Default: $port
- -t int Try higher ports if chosen port is in use.
- Increase port by 1 for [int] times before giving up.
- This option checks ports with fuser The default is to try 100 times.
- If set to 0 (zero) higher ports won't be tried.
- -r Loop retry, each time with a new tor connection
- (requires interactive terminal).
- -q Be quiet. Only the launched application speaks.
- -d Set delay to sleep (in seconds) after starting tor. Default: $delay
- ~/.config/tor/ must be writeable.
- EOF
- exit 1
- }
- log() {
- [[ "$quiet" == '' ]] && echo -e "$@" >&2
- }
- trap cleanup EXIT
- me="${0##*/}"
- Ecountries="{fi},{ax},{se},{no},{dk},{ee},{lv},{lt},{cz},{sk},{at},{si},{it},{ch},{fr},{es},{pt},{be},{nl},{de},{gb},{ie},{is},{gr}"
- countries=""
- declare -i port=9222 # declare as integer
- try=100 # try higher ports so many times
- retry=0
- delay=1
- quiet=''
- torpid=bla
- file=''
- # character for separator line
- sepchar="-"
- sep=''
- columns="$(tput cols)"
- [ -z "$columns" ] && columns=80
- # adjust separator width to terminal width
- for ((i=0;i<columns;i++)); do sep="$sep$sepchar"; done
- unset sepchar columns
- controlport=false
- while getopts "c:CEP:t:rqd:h" opt; do
- case $opt in
- c)
- countries="$OPTARG"
- ;;
- C)
- controlport=true
- ;;
- E)
- countries="$Ecountries"
- ;;
- f)
- file="$OPTARG"
- [ -r "$file" ] && usage "File $file already exists. Please remove it."
- touch "$file" || usage "Cannot touch $file. Permissions?"
- ;;
- P) [[ "$OPTARG" =~ [0-9]+ ]] && (( OPTARG >= 0 )) && (( OPTARG <= 65535 )) || usage "Invalid port: $OPTARG"
- port="$OPTARG"
- ;;
- t) try="$OPTARG"
- ;;
- r) retry=1
- ;;
- q) quiet='--quiet'
- ;;
- d) delay="$OPTARG"
- ;;
- *|h) usage
- ;;
- esac
- done
- shift $((OPTIND-1))
- unset Ecountries
- # simple dependency check
- for dep in fuser tor kill torsocks; do
- type -f $dep >/dev/null || usage
- done
- ### Retry Loop
- while :; do
- now="$(printf "%(%H:%M:%S)T")"
- [[ "$controlport" == true ]] && controlport=$((port+1))
- if (( try != 0 )); then
- [[ "$try" =~ [0-9]+ ]] && (( try <= (65535-port) )) || usage "Invalid number: $try (Must be between 1 and $((65535-port))."
- # find a free port
- i=0
- for ((;i<=try;i++)); do
- fuser -sn tcp "$((port+i))" && continue
- [[ "$controlport" != false ]] && fuser -sn tcp "$((controlport+i))" && continue
- break
- done
- (( i > try )) && usage "Could not find a free port between $port and $((port+try))"
- port=$((port+i))
- [[ "$controlport" != false ]] && controlport=$((controlport+i))
- else
- fuser -sn tcp "$port" && usage "Port $port is not free."
- fi
- ### prepare tor ###
- log "Tor data dir: $HOME/.config/tor/${me}.${now}.${port}"
- datadir="$HOME/.config/tor/${me}.${now}.${port}"
- torrc="$datadir/torrc"
- rm -rf "$datadir"
- mkdir -p "$datadir" || usage "Cannot mkdir $datadir"
- if [[ "$countries" == "" ]]; then
- printf "SocksPort $port\nDataDirectory \"$datadir\"\nRunAsDaemon 1\nPidFile \"$datadir/pid\"\n" > "$torrc"
- log "Tor: no restrictions on choice of nodes\n$sep"
- else
- printf "EntryNodes $countries\nExitNodes $countries\nSocksPort $port\nDataDirectory \"$datadir\"\nRunAsDaemon 1\nPidFile \"$datadir/pid\"\n" > "$torrc"
- log "Tor: nodes only from these countries:\n$countries\n$sep"
- fi
- [[ "$controlport" != false ]] && printf "ControlPort $controlport\nCookieAuthentication 0\n" >> "$torrc"
- ### launch tor ###
- tor $quiet -f "$torrc" >&2
- ###
- [ -r "$datadir/pid" ] && torpid="$(<"$datadir/pid")"
- [[ "$torpid" == 0 ]] && usage "Apparently tor did not start; $datadir/pid is empty or does not exist."
- [[ "$file" != "" ]] && printf "port=%s\ncontrolport=%s\n" "$port" "$controlport" > "$file"
- log "$sep\nTor pid: $torpid\n$sep\nWaiting ${delay}s before continuing..."
- sleep "$delay"
- ### launch the script ###
- if [[ "$@" != "" ]] && [ -x "$1" ]; then
- log "$sep\nLaunching: torsocks $quiet -i -P $port $@\n$sep"
- torsocks $quiet -i -P "$port" "$@"
- else
- echo "Tor is now running on port $port."
- [[ "$controlport" != false ]] && echo "Control port is $controlport."
- fi
- ###
- if [[ "$retry" == 1 ]]; then
- read -p "Do you want to retry (r)? " answer
- [[ "$answer" != r ]] && exit 0
- fi
- cleanup
- echo -e "$sep\n###### Retrying #########\n$sep"
- clear
- done
|