#!/usr/bin/env sh #tunlr has pulled the plug, this script isn't working anymore. # The script works under ash and bash decide wich to use `{ echo true | /usr/bin/env ash 2>/dev/null && echo '/usr/bin/env ash'; } || { echo true | /usr/bin/env bash 2>/dev/null && echo '/usr/bin/env bash'; } || { echo 'bash or ash not found' >&2; echo 'exit 1'; }` <<'EOF' #################### ## -- Settings -- ## #################### # Add your API token here from https://gatekeeper.tunlr.net/account_options TOKEN='insert_your_token_here' # Specify the client you want to use, the options are: curl wget CLIENT='wget' # Extra command line options to parse to the client. xOPT='' # Set to 0 to not log to console LOGCONSOLE=1 # Secify the command to pipe the log messages to, e.g. logger cmdLog='' # Secify the command to pipe the warning messages to, e.g. logger cmdWrn='' # Secify the command to pipe the error messages to, e.g. logger cmdErr='' # If secure is 1 it uses https and if set to 0 it uses http SECURE=0 # Agent string to send to the webserver AGENT='update-script v2' # Specify the verbosity to use: # 1 Only show the error messages # 2 Show error and warning messages # 3 show error, warning and log messages # 4 show error, warning, log and client transaction messages VERBOSE=3 # Days left on a subscription before a warning message is shown dWARN=7 #################### ## -- messages -- ## #################### messages() { case "$1" in 'invalid_token' ) logErr "Your token is not valid, check your tunlr dashboard";; 'api_access_disabled') logErr "API access disabled, check your tunlr dashboard";; 'days_remaining_w' ) logWrn "$2 days remaining on your $3 subscription plan";; 'days_remaining' ) logMsg "$2 days remaining on your $3 subscription plan";; 'up_for_renewal' ) logWrn "Your account is up for renewal, please check your tunlr dashboard";; 'as/hosting' ) logWrn "ISP-enforced transparent proxy, a VPN provider or a server provider has been detected";; 'as/abuse' ) logWrn "Autonomous system is banned";; 'cidr/hosting' ) logWrn "Network range belongs to a VPN or server provider";; 'cidr/abuse' ) logWrn "Network range is banned";; 'proxy' ) logWrn "A proxy has been detected";; 'no_ip_change' ) logMsg "Your ip has not changed";; 'ip_change' ) logWrn "Your ip has changed";; 'state/expired' ) logErr "There is currently no subscription plan, please check your tunlr dashboard";; 'state/active' ) logMsg "Account is active";; 'state/banned' ) logErr "Account is banned";; 'state/pending' ) logErr "Account is pending, check your tunlr dashboard";; 'no_account' ) logErr "Failed to get account info";; 'update/fail' ) logErr "Failed to update ip address";; 'update/block' ) logErr "Your current ip is blacklisted by tunlr";; 'update/none' ) logWrn "Nothing to update";; 'update/done' ) logWrn "Ip has been updated";; 'api/client' ) logErr "wrong client selected, options are wget or curl";; 'api/get' ) logMsg "Getting the json respone from ${2}TOKEN-redacted";; 'api/noConnect' ) logErr "$2 failed to connect";; 'api/empty' ) logErr "tunlr API returned an empty page";; 'json/exp1' ) logErr "json: EXPECTED , or ] GOT $2";; 'json/exp2' ) logErr "json: EXPECTED string GOT $2";; 'json/exp3' ) logErr "json: EXPECTED : GOT $2";; 'json/exp4' ) logErr "json: EXPECTED , or } GOT $2";; 'json/exp5' ) logErr "json: EXPECTED value GOT $2";; 'json/exp6' ) logErr "json: EXPECTED EOF GOT $2";; *'false'|*'true' ) ;; # don't output anything on false or true * ) logWrn "Unkown: $*";; #unkown message handler esac } ############################## ## -- Script starts here -- ## ############################## logErr () { if [ "$VERBOSE" -ge 1 ]; then [ "$LOGCONSOLE" != '0' ] && echo " $esc[31m$*$esc[0m" >&2 [ -n "${cmdErr}" ] && echo "$*" | ${cmdErr} fi echo exit 1 } logWrn () { if [ "$VERBOSE" -ge 2 ]; then [ "$LOGCONSOLE" != '0' ] && echo " $esc[31m$*$esc[0m" >&2 [ -n "${cmdWrn}" ] && echo "$*" | ${cmdWrn} fi } logMsg () { if [ "$VERBOSE" -ge 3 ]; then [ "$LOGCONSOLE" != '0' ] && echo " $esc[32m$*$esc[0m" >&2 [ -n "${cmdMsg}" ] && echo "$*" | ${cmdMsg} fi } awk_egrep () { local pattern_string=$1 gawk '{ while ($0) { start=match($0, pattern); token=substr($0, start, RLENGTH); print token; $0=substr($0, start+RLENGTH); } }' pattern=$pattern_string } tokenize () { local GREP local ESCAPE local CHAR if echo "test string" | egrep -ao --color=never "test" &>/dev/null then GREP='egrep -ao --color=never' else GREP='egrep -ao' fi if echo "test string" | egrep -o "test" &>/dev/null then ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})' CHAR='[^[:cntrl:]"\\]' else GREP=awk_egrep ESCAPE='(\\\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})' CHAR='[^[:cntrl:]"\\\\]' fi local STRING="\"$CHAR*($ESCAPE$CHAR*)*\"" local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?' local KEYWORD='null|false|true' local SPACE='[[:space:]]+' $GREP "$STRING|$NUMBER|$KEYWORD|$SPACE|." | egrep -v "^$SPACE$" } parse_array () { local index=0 local ary='' read -r token case "$token" in ']') ;; *) while : do parse_value "$1" "$index" index=$((index+1)) ary="$ary""$value" read -r token case "$token" in ']') break ;; ',') ary="$ary," ;; *) messages 'json/exp1' "${token:-EOF}";; esac read -r token done ;; esac : } parse_object () { local key local obj='' read -r token case "$token" in '}') ;; *) while : do case "$token" in '"'*'"') key=$token ;; *) messages 'json/exp2' "${token:-EOF}" "EXPECTED string GOT ${token:-EOF}" ;; esac read -r token case "$token" in ':') ;; *) messages 'json/exp3' "${token:-EOF}" ;; esac read -r token parse_value "$1" "$key" obj="$obj$key:$value" read -r token case "$token" in '}') break ;; ',') obj="$obj," ;; *) messages 'json/exp4' "${token:-EOF}" ;; esac read -r token done ;; esac : } parse_value () { local jpath="${1:+$1,}$2" isleaf=0 isempty=0 case "$token" in '{') parse_object "$jpath" ;; '[') parse_array "$jpath" ;; ''|[!0-9]) messages 'json/exp5' "${token:-EOF}" ;; *) value=$token isleaf=1 [ "$value" = '""' ] && isempty=1 ;; esac [ "$value" = '' ] && return [ "$isleaf" -eq 1 ] && printf "[%s]\t%s\n" "$jpath" "$value" : } parse () { read -r token parse_value read -r token case "$token" in '') ;; *) messages 'json/exp6' "$token" ;; esac } getField() { echo "$fields" | grep "\[${1}\]" | sed 's/.*\t//;s/^"//;s/"$//;s/^null$/false/;s/^$/false/' } tunlrApi() { local url='' json='' [ "$SECURE" = '1' ] && url='https' || url='http' url="$url://gatekeeper-api.tunlr.net/$API/$1/" messages 'api/get' "$url" url="${url}${TOKEN}" json=`{ [ "$VERBOSE" -ge 4 ] || exec 2>/dev/null case "${CLIENT}" in wget) wget -O - -U "${AGENT}" ${xOPT} "$url" ;; curl) curl --fail --user-agent "${AGENT}" ${xOPT} "$url" ;; *) messages 'api/client' ;; esac }` || messages 'api/noConnect' "${CLIENT}" [ -z "$json" ] && messages 'api/empty' echo "${json}" | tokenize | parse } tunlrUpdate() { local fields message plan days ipChange esc esc="$(echo | tr '\n' '\033')" echo fields=`tunlrApi get_account` || exit 1 message=`getField '"message"'` messages "$message" [ "$(getField '"success"')" != "true" ] && messages 'no_account' messages "state/$(getField '"account","state"')" plan=`getField '"subscription","plan_name"'` [ "$plan" = "false" ] && messages 'state/expired' days=`getField '"subscription","days_remaining"'` if [ "$days" != 'false' ] && [ "$days" -le "$dWARN" ]; then messages 'days_remaining_w' "$days" "$plan" else messages 'days_remaining' "$days" "$plan" fi [ "$(getField '"subscription","up_for_renewal"')" = 'true' ] && messages 'up_for_renewal' ipChange=`getField '"subscription","has_ip_changed"'` case "$ipChange" in false) messages 'no_ip_change';; true ) messages 'ip_change';; * ) messages "$ipChange";; esac case "$message" in *hosting | *abuse | *proxy) messages 'update/block';; esac if [ "$ipChange" = false ]; then messages 'update/none' echo "" exit 0 fi fields=`tunlrApi update_ip` || exit 1 message=`getField '"message"'` messages "$message" [ "$(getField '"success"')" != "true" ] && messages 'update/fail' || messages 'update/done' echo } API='api_v1' tunlrUpdate EOF