diff --git a/bash/cfScanner.sh b/bash/cfScanner.sh index 75bf833..8025b32 100755 --- a/bash/cfScanner.sh +++ b/bash/cfScanner.sh @@ -12,21 +12,20 @@ # AUTHOR: Morteza Bashsiz (mb), morteza.bashsiz@gmail.com # ORGANIZATION: Linux # CREATED: 01/24/2023 07:36:57 PM -# REVISION: nomadzzz, armgham, beh-rouz, amini8, mahdibahramih, armineslami, miytiy, F4RAN +# REVISION: nomadzzz, armgham, beh-rouz, amini8, mahdibahramih, armineslami, miytiy, F4RAN #=============================================================================== export TOP_PID=$$ # Function fncLongIntToStr -# converts IP in long integer format to a string +# converts IP in long integer format to a string fncLongIntToStr() { local IFS=. num quad ip e num=$1 - for e in 3 2 1 - do - (( quad = 256 ** e)) - (( ip[3-e] = num / quad )) - (( num = num % quad )) + for e in 3 2 1; do + ((quad = 256 ** e)) + ((ip[3 - e] = num / quad)) + ((num = num % quad)) done ip[3]=$num echo "${ip[*]}" @@ -34,16 +33,15 @@ fncLongIntToStr() { # End of Function fncLongIntToStr # Function fncIpToLongInt -# converts IP to long integer +# converts IP to long integer fncIpToLongInt() { local IFS=. ip num e # shellcheck disable=SC2206 ip=($1) - for e in 3 2 1 - do - (( num += ip[3-e] * 256 ** e )) + for e in 3 2 1; do + ((num += ip[3 - e] * 256 ** e)) done - (( num += ip[3] )) + ((num += ip[3])) echo $num } # End of Function fncIpToLongInt @@ -51,426 +49,363 @@ fncIpToLongInt() { # Function fncSubnetToIP # converts subnet to IP list fncSubnetToIP() { - # shellcheck disable=SC2206 - local network=(${1//\// }) - # shellcheck disable=SC2206 - local iparr=(${network[0]//./ }) - local mask=32 - [[ $((${#network[@]})) -gt 1 ]] && mask=${network[1]} - - local maskarr - # shellcheck disable=SC2206 - if [[ ${mask} = '\.' ]]; then # already mask format like 255.255.255.0 - maskarr=(${mask//./ }) - else # assume CIDR like /24, convert to mask - if [[ $((mask)) -lt 8 ]]; then - maskarr=($((256-2**(8-mask))) 0 0 0) - elif [[ $((mask)) -lt 16 ]]; then - maskarr=(255 $((256-2**(16-mask))) 0 0) - elif [[ $((mask)) -lt 24 ]]; then - maskarr=(255 255 $((256-2**(24-mask))) 0) - elif [[ $((mask)) -lt 32 ]]; then - maskarr=(255 255 255 $((256-2**(32-mask)))) - elif [[ ${mask} == 32 ]]; then - maskarr=(255 255 255 255) + # shellcheck disable=SC2206 + local network=(${1//\// }) + # shellcheck disable=SC2206 + local iparr=(${network[0]//./ }) + local mask=32 + [[ $((${#network[@]})) -gt 1 ]] && mask=${network[1]} + + local maskarr + # shellcheck disable=SC2206 + if [[ ${mask} = '\.' ]]; then # already mask format like 255.255.255.0 + maskarr=(${mask//./ }) + else # assume CIDR like /24, convert to mask + if [[ $((mask)) -lt 8 ]]; then + maskarr=($((256 - 2 ** (8 - mask))) 0 0 0) + elif [[ $((mask)) -lt 16 ]]; then + maskarr=(255 $((256 - 2 ** (16 - mask))) 0 0) + elif [[ $((mask)) -lt 24 ]]; then + maskarr=(255 255 $((256 - 2 ** (24 - mask))) 0) + elif [[ $((mask)) -lt 32 ]]; then + maskarr=(255 255 255 $((256 - 2 ** (32 - mask)))) + elif [[ ${mask} == 32 ]]; then + maskarr=(255 255 255 255) + fi fi - fi - - # correct wrong subnet masks (e.g. 240.192.255.0 to 255.255.255.0) - [[ ${maskarr[2]} == 255 ]] && maskarr[1]=255 - [[ ${maskarr[1]} == 255 ]] && maskarr[0]=255 - - # generate list of ip addresses - if [[ "$randomNumber" != "NULL" ]] - then - local bytes=(0 0 0 0) - for i in $(seq 0 $((255-maskarr[0]))); do - bytes[0]="$(( i+(iparr[0] & maskarr[0]) ))" - for j in $(seq 0 $((255-maskarr[1]))); do - bytes[1]="$(( j+(iparr[1] & maskarr[1]) ))" - for k in $(seq 0 $((255-maskarr[2]))); do - bytes[2]="$(( k+(iparr[2] & maskarr[2]) ))" - for l in $(seq 1 $((255-maskarr[3]))); do - bytes[3]="$(( l+(iparr[3] & maskarr[3]) ))" - ipList+=("$(printf "%d.%d.%d.%d" "${bytes[@]}")") - done - done - done - done - # Choose random IP addresses from generated IP list - if [[ "$osVersion" == "Linux" ]] - then - mapfile -t ipList < <(shuf -e "${ipList[@]}") - mapfile -t ipList < <(shuf -e "${ipList[@]:0:$randomNumber}") - elif [[ "$osVersion" == "Mac" ]] - then - # shellcheck disable=SC2207 - ipList=($(printf '%s\n' "${ipList[@]}" | shuf)) - # shellcheck disable=SC2207 - ipList=($(printf '%s\n' "${ipList[@]:0:$randomNumber}" | shuf)) + + # correct wrong subnet masks (e.g. 240.192.255.0 to 255.255.255.0) + [[ ${maskarr[2]} == 255 ]] && maskarr[1]=255 + [[ ${maskarr[1]} == 255 ]] && maskarr[0]=255 + + # Handle the /32 case separately + if [[ ${mask} == 32 ]]; then + ipList+=("${network[0]}") else - echo "OS not supported only Linux or Mac" - exit 1 - fi - for i in "${ipList[@]}"; do - echo "$i" - done - elif [[ "$randomNumber" == "NULL" ]] - then - local bytes=(0 0 0 0) - for i in $(seq 0 $((255-maskarr[0]))); do - bytes[0]="$(( i+(iparr[0] & maskarr[0]) ))" - for j in $(seq 0 $((255-maskarr[1]))); do - bytes[1]="$(( j+(iparr[1] & maskarr[1]) ))" - for k in $(seq 0 $((255-maskarr[2]))); do - bytes[2]="$(( k+(iparr[2] & maskarr[2]) ))" - for l in $(seq 1 $((255-maskarr[3]))); do - bytes[3]="$(( l+(iparr[3] & maskarr[3]) ))" - printf "%d.%d.%d.%d\n" "${bytes[@]}" - done + # Generate IP list for subnets smaller than /32 using existing loop logic + local bytes=(0 0 0 0) + for i in $(seq 0 $((255 - maskarr[0]))); do + bytes[0]="$((i + (iparr[0] & maskarr[0])))" + for j in $(seq 0 $((255 - maskarr[1]))); do + bytes[1]="$((j + (iparr[1] & maskarr[1])))" + for k in $(seq 0 $((255 - maskarr[2]))); do + bytes[2]="$((k + (iparr[2] & maskarr[2])))" + for l in $(seq 1 $((255 - maskarr[3]))); do + bytes[3]="$((l + (iparr[3] & maskarr[3])))" + ipList+=("$(printf "%d.%d.%d.%d" "${bytes[@]}")") + done + done + done done - done - done - fi + fi + + # Process the generated IP list based on randomNumber + if [[ "$randomNumber" != "NULL" ]]; then + # Choose and print a random sample of IPs + if [[ "$osVersion" == "Linux" ]]; then + mapfile -t ipList < <(shuf -e "${ipList[@]}") + mapfile -t ipList < <(shuf -e "${ipList[@]:0:$randomNumber}") + elif [[ "$osVersion" == "Mac" ]]; then + # shellcheck disable=SC2207 + ipList=($(printf '%s\n' "${ipList[@]}" | shuf)) + # shellcheck disable=SC2207 + ipList=($(printf '%s\n' "${ipList[@]:0:$randomNumber}" | shuf)) + else + echo "OS not supported only Linux or Mac" + exit 1 + fi + fi + + printf "%s\n" "${ipList[@]}" } # End of Function fncSubnetToIP # Function fncShowProgress # Progress bar maker function (based on https://www.baeldung.com/linux/command-line-progress-bar) function fncShowProgress { - barCharDone="=" - barCharTodo=" " - barSplitter='>' - barPercentageScale=2 - current="$1" - total="$2" - - barSize="$(($(tput cols)-70))" # 70 cols for description characters - - # calculate the progress in percentage - percent=$(bc <<< "scale=$barPercentageScale; 100 * $current / $total" ) - # The number of done and todo characters - done=$(bc <<< "scale=0; $barSize * $percent / 100" ) - todo=$(bc <<< "scale=0; $barSize - $done") - # build the done and todo sub-bars - doneSubBar=$(printf "%${done}s" | tr " " "${barCharDone}") - todoSubBar=$(printf "%${todo}s" | tr " " "${barCharTodo} - 1") # 1 for barSplitter - spacesSubBar=$(printf "%${todo}s" | tr " " " ") - - # output the bar - progressBar="| Progress bar of main IPs: [${doneSubBar}${barSplitter}${todoSubBar}] ${percent}%${spacesSubBar}" # Some end space for pretty formatting + barCharDone="=" + barCharTodo=" " + barSplitter='>' + barPercentageScale=2 + current="$1" + total="$2" + + barSize="$(($(tput cols) - 70))" # 70 cols for description characters + + # calculate the progress in percentage + percent=$(bc <<<"scale=$barPercentageScale; 100 * $current / $total") + # The number of done and todo characters + done=$(bc <<<"scale=0; $barSize * $percent / 100") + todo=$(bc <<<"scale=0; $barSize - $done") + # build the done and todo sub-bars + doneSubBar=$(printf "%${done}s" | tr " " "${barCharDone}") + todoSubBar=$(printf "%${todo}s" | tr " " "${barCharTodo} - 1") # 1 for barSplitter + spacesSubBar=$(printf "%${todo}s" | tr " " " ") + + # output the bar + progressBar="| Progress bar of main IPs: [${doneSubBar}${barSplitter}${todoSubBar}] ${percent}%${spacesSubBar}" # Some end space for pretty formatting } # End of Function showProgress # Function fncCheckIPList # Check Subnet function fncCheckIPList { - local ipList scriptDir resultFile timeoutCommand domainFronting downOK upOK - ipList="${1}" - resultFile="${3}" - scriptDir="${4}" - configId="${5}" - configHost="${6}" - configPort="${7}" - configPath="${8}" - fileSize="${9}" - osVersion="${10}" - clientCommand="${11}" - tryCount="${12}" - downThreshold="${13}" - upThreshold="${14}" - downloadOrUpload="${15}" - vpnOrNot="${16}" - quickOrNot="${17}" - binDir="$scriptDir/../bin" - tempConfigDir="$scriptDir/tempConfig" - uploadFile="$tempConfigDir/upload_file" - configPath=$(echo "$configPath" | sed 's/\//\\\//g') - # set proper command for linux - if command -v timeout >/dev/null 2>&1; - then - timeoutCommand="timeout" - else - # set proper command for mac - if command -v gtimeout >/dev/null 2>&1; - then - timeoutCommand="gtimeout" + local ipList scriptDir resultFile timeoutCommand domainFronting downOK upOK + ipList="${1}" + resultFile="${3}" + scriptDir="${4}" + configId="${5}" + configHost="${6}" + configPort="${7}" + configPath="${8}" + fileSize="${9}" + osVersion="${10}" + clientCommand="${11}" + tryCount="${12}" + downThreshold="${13}" + upThreshold="${14}" + downloadOrUpload="${15}" + vpnOrNot="${16}" + quickOrNot="${17}" + binDir="$scriptDir/../bin" + tempConfigDir="$scriptDir/tempConfig" + uploadFile="$tempConfigDir/upload_file" + configPath=$(echo "$configPath" | sed 's/\//\\\//g') + # set proper command for linux + if command -v timeout >/dev/null 2>&1; then + timeoutCommand="timeout" else - echo >&2 "I require 'timeout' command but it's not installed. Please install 'timeout' or an alternative command like 'gtimeout' and try again." - exit 1 - fi - fi - if [[ "$vpnOrNot" == "YES" ]] - then - for ip in ${ipList} - do - if [[ "$downloadOrUpload" == "BOTH" ]] - then - downOK="NO" - upOK="NO" - elif [[ "$downloadOrUpload" == "UP" ]] - then - downOK="YES" - upOK="NO" - elif [[ "$downloadOrUpload" == "DOWN" ]] - then - downOK="NO" - upOK="YES" + # set proper command for mac + if command -v gtimeout >/dev/null 2>&1; then + timeoutCommand="gtimeout" + else + echo >&2 "I require 'timeout' command but it's not installed. Please install 'timeout' or an alternative command like 'gtimeout' and try again." + exit 1 fi - if $timeoutCommand 1 bash -c " /dev/null 2>&1; - then - if [[ "$quickOrNot" == "NO" ]] - then - domainFronting=$($timeoutCommand 1 curl -k -s --tlsv1.2 -H "Host: speed.cloudflare.com" --resolve "speed.cloudflare.com:443:$ip" "https://speed.cloudflare.com/__down?bytes=10") - elif [[ "$quickOrNot" == "YES" ]] - then - domainFronting="0000000000" - fi - if [[ "$domainFronting" == "0000000000" ]] - then - mainDomain=$(echo "$configHost" | awk -F '.' '{ print $2"."$3}') - if [[ "$osVersion" == "Linux" ]] - then - randomUUID=$(cat /proc/sys/kernel/random/uuid) - elif [[ "$osVersion" == "Mac" ]] - then - randomUUID=$(uuidgen | tr '[:upper:]' '[:lower:]') - else - echo "OS not supported only Linux or Mac" - exit 1 - fi - configServerName="$randomUUID.$mainDomain" - ipConfigFile="$tempConfigDir/config.json.$ip".json - cp "$scriptDir"/config.json.temp "$ipConfigFile" - ipO1=$(echo "$ip" | awk -F '.' '{print $1}') - ipO2=$(echo "$ip" | awk -F '.' '{print $2}') - ipO3=$(echo "$ip" | awk -F '.' '{print $3}') - ipO4=$(echo "$ip" | awk -F '.' '{print $4}') - port=$((ipO1 + ipO2 + ipO3 + ipO4)) - if [[ "$osVersion" == "Mac" ]] - then - sed -i "" "s/IP.IP.IP.IP/$ip/g" "$ipConfigFile" - sed -i "" "s/PORTPORT/3$port/g" "$ipConfigFile" - sed -i "" "s/IDID/$configId/g" "$ipConfigFile" - sed -i "" "s/HOSTHOST/$configHost/g" "$ipConfigFile" - sed -i "" "s/CFPORTCFPORT/$configPort/g" "$ipConfigFile" - sed -i "" "s/ENDPOINTENDPOINT/$configPath/g" "$ipConfigFile" - sed -i "" "s/RANDOMHOST/$configServerName/g" "$ipConfigFile" - elif [[ "$osVersion" == "Linux" ]] - then - sed -i "s/IP.IP.IP.IP/$ip/g" "$ipConfigFile" - sed -i "s/PORTPORT/3$port/g" "$ipConfigFile" - sed -i "s/IDID/$configId/g" "$ipConfigFile" - sed -i "s/HOSTHOST/$configHost/g" "$ipConfigFile" - sed -i "s/CFPORTCFPORT/$configPort/g" "$ipConfigFile" - sed -i "s/ENDPOINTENDPOINT/$configPath/g" "$ipConfigFile" - sed -i "s/RANDOMHOST/$configServerName/g" "$ipConfigFile" - fi - # shellcheck disable=SC2009 - pid=$(ps aux | grep config.json."$ip" | grep -v grep | awk '{ print $2 }') - if [[ "$pid" ]] - then - kill -9 "$pid" > /dev/null 2>&1 + fi + if [[ "$vpnOrNot" == "YES" ]]; then + for ip in ${ipList}; do + if [[ "$downloadOrUpload" == "BOTH" ]]; then + downOK="NO" + upOK="NO" + elif [[ "$downloadOrUpload" == "UP" ]]; then + downOK="YES" + upOK="NO" + elif [[ "$downloadOrUpload" == "DOWN" ]]; then + downOK="NO" + upOK="YES" fi - downTotalTime=0 - upTotalTime=0 - downAvgStr="" - upAvgStr="" - downSuccessedCount=0 - upSuccessedCount=0 - nohup "$binDir"/"$clientCommand" -c "$ipConfigFile" > /dev/null & - sleep 2 - for i in $(seq 1 "$tryCount"); - do - downTimeMil=0 - upTimeMil=0 - if [[ "$downloadOrUpload" == "DOWN" ]] || [[ "$downloadOrUpload" == "BOTH" ]] - then - downTimeMil=$($timeoutCommand 2 curl -x "socks5://127.0.0.1:3$port" -s -w "TIME: %{time_total}\n" --resolve "speed.cloudflare.com:443:$ip" "https://speed.cloudflare.com/__down?bytes=$fileSize" --output /dev/null | grep "TIME" | tail -n 1 | awk '{print $2}' | xargs -I {} echo "{} * 1000 /1" | bc ) - if [[ $downTimeMil -gt 100 ]] - then - downSuccessedCount=$(( downSuccessedCount+1 )) - else - downTimeMil=0 + if $timeoutCommand 1 bash -c "/dev/null 2>&1; then + if [[ "$quickOrNot" == "NO" ]]; then + domainFronting=$($timeoutCommand 1 curl -k -s --tlsv1.2 -H "Host: speed.cloudflare.com" --resolve "speed.cloudflare.com:443:$ip" "https://speed.cloudflare.com/__down?bytes=10") + elif [[ "$quickOrNot" == "YES" ]]; then + domainFronting="0000000000" fi - fi - if [[ "$downloadOrUpload" == "UP" ]] || [[ "$downloadOrUpload" == "BOTH" ]] - then - result=$($timeoutCommand 2 curl -x "socks5://127.0.0.1:3$port" -s -w "\nTIME: %{time_total}\n" --resolve "speed.cloudflare.com:443:$ip" --data "@$uploadFile" https://speed.cloudflare.com/__up | grep "TIME" | tail -n 1 | awk '{print $2}' | xargs -I {} echo "{} * 1000 /1" | bc) - if [[ "$result" ]] - then - upTimeMil="$result" - if [[ $upTimeMil -gt 100 ]] - then - upSuccessedCount=$(( upSuccessedCount+1 )) - else - upTimeMil=0 - fi + if [[ "$domainFronting" == "0000000000" ]]; then + mainDomain=$(echo "$configHost" | awk -F '.' '{ print $2"."$3}') + if [[ "$osVersion" == "Linux" ]]; then + randomUUID=$(cat /proc/sys/kernel/random/uuid) + elif [[ "$osVersion" == "Mac" ]]; then + randomUUID=$(uuidgen | tr '[:upper:]' '[:lower:]') + else + echo "OS not supported only Linux or Mac" + exit 1 + fi + configServerName="$randomUUID.$mainDomain" + ipConfigFile="$tempConfigDir/config.json.$ip".json + cp "$scriptDir"/config.json.temp "$ipConfigFile" + ipO1=$(echo "$ip" | awk -F '.' '{print $1}') + ipO2=$(echo "$ip" | awk -F '.' '{print $2}') + ipO3=$(echo "$ip" | awk -F '.' '{print $3}') + ipO4=$(echo "$ip" | awk -F '.' '{print $4}') + port=$((ipO1 + ipO2 + ipO3 + ipO4)) + if [[ "$osVersion" == "Mac" ]]; then + sed -i "" "s/IP.IP.IP.IP/$ip/g" "$ipConfigFile" + sed -i "" "s/PORTPORT/3$port/g" "$ipConfigFile" + sed -i "" "s/IDID/$configId/g" "$ipConfigFile" + sed -i "" "s/HOSTHOST/$configHost/g" "$ipConfigFile" + sed -i "" "s/CFPORTCFPORT/$configPort/g" "$ipConfigFile" + sed -i "" "s/ENDPOINTENDPOINT/$configPath/g" "$ipConfigFile" + sed -i "" "s/RANDOMHOST/$configServerName/g" "$ipConfigFile" + elif [[ "$osVersion" == "Linux" ]]; then + sed -i "s/IP.IP.IP.IP/$ip/g" "$ipConfigFile" + sed -i "s/PORTPORT/3$port/g" "$ipConfigFile" + sed -i "s/IDID/$configId/g" "$ipConfigFile" + sed -i "s/HOSTHOST/$configHost/g" "$ipConfigFile" + sed -i "s/CFPORTCFPORT/$configPort/g" "$ipConfigFile" + sed -i "s/ENDPOINTENDPOINT/$configPath/g" "$ipConfigFile" + sed -i "s/RANDOMHOST/$configServerName/g" "$ipConfigFile" + fi + # shellcheck disable=SC2009 + pid=$(ps aux | grep config.json."$ip" | grep -v grep | awk '{ print $2 }') + if [[ "$pid" ]]; then + kill -9 "$pid" >/dev/null 2>&1 + fi + downTotalTime=0 + upTotalTime=0 + downAvgStr="" + upAvgStr="" + downSuccessedCount=0 + upSuccessedCount=0 + nohup "$binDir"/"$clientCommand" -c "$ipConfigFile" >/dev/null & + sleep 2 + for i in $(seq 1 "$tryCount"); do + downTimeMil=0 + upTimeMil=0 + if [[ "$downloadOrUpload" == "DOWN" ]] || [[ "$downloadOrUpload" == "BOTH" ]]; then + downTimeMil=$($timeoutCommand 2 curl -x "socks5://127.0.0.1:3$port" -s -w "TIME: %{time_total}\n" --resolve "speed.cloudflare.com:443:$ip" "https://speed.cloudflare.com/__down?bytes=$fileSize" --output /dev/null | grep "TIME" | tail -n 1 | awk '{print $2}' | xargs -I {} echo "{} * 1000 /1" | bc) + if [[ $downTimeMil -gt 100 ]]; then + downSuccessedCount=$((downSuccessedCount + 1)) + else + downTimeMil=0 + fi + fi + if [[ "$downloadOrUpload" == "UP" ]] || [[ "$downloadOrUpload" == "BOTH" ]]; then + result=$($timeoutCommand 2 curl -x "socks5://127.0.0.1:3$port" -s -w "\nTIME: %{time_total}\n" --resolve "speed.cloudflare.com:443:$ip" --data "@$uploadFile" https://speed.cloudflare.com/__up | grep "TIME" | tail -n 1 | awk '{print $2}' | xargs -I {} echo "{} * 1000 /1" | bc) + if [[ "$result" ]]; then + upTimeMil="$result" + if [[ $upTimeMil -gt 100 ]]; then + upSuccessedCount=$((upSuccessedCount + 1)) + else + upTimeMil=0 + fi + fi + fi + downTotalTime=$((downTotalTime + downTimeMil)) + upTotalTime=$((upTotalTime + upTimeMil)) + downAvgStr="$downAvgStr $downTimeMil" + upAvgStr="$upAvgStr $upTimeMil" + done + if [[ $downSuccessedCount -ge $downThreshold ]] && [[ "$downloadOrUpload" != "UP" ]]; then + downOK="YES" + downRealTime=$((downTotalTime / downSuccessedCount)) + else + downRealTime=0 + fi + if [[ $upSuccessedCount -ge $upThreshold ]] && [[ "$downloadOrUpload" != "DOWN" ]]; then + upOK="YES" + upRealTime=$((upTotalTime / upSuccessedCount)) + else + upRealTime=0 + fi + # shellcheck disable=SC2009 + pid=$(ps aux | grep config.json."$ip" | grep -v grep | awk '{ print $2 }') + if [[ "$pid" ]]; then + kill -9 "$pid" >/dev/null 2>&1 + fi + if [[ "$downOK" == "YES" ]] && [[ "$upOK" == "YES" ]]; then + if [[ "$downRealTime" && $downRealTime -gt 100 ]] || [[ "$upRealTime" && $upRealTime -gt 100 ]]; then + echo -e "${GREEN}OK${NC} $ip ${BLUE}DOWN: Avg $downRealTime $downAvgStr ${ORANGE}UP: Avg $upRealTime, $upAvgStr${NC}" + if [[ "$downRealTime" && $downRealTime -gt 100 ]]; then + #echo "${GREEN}OK${NC} $ip ${BLUE}DOWN: Avg $downRealTime $downAvgStr${NC}" + echo "$downRealTime, $downAvgStr DOWN FOR IP $ip" >>"$resultFile" + fi + if [[ "$upRealTime" && $upRealTime -gt 100 ]]; then + #echo "${GREEN}OK${NC} $ip ${BLUE}UP: $upRealTime, $upAvgStr${NC}" + echo "$upRealTime, $upAvgStr UP FOR IP $ip" >>"$resultFile" + fi + else + echo -e "${RED}FAILED${NC} $ip" + fi + else + echo -e "${RED}FAILED${NC} $ip" + fi + else + echo -e "${RED}FAILED${NC} $ip" fi - fi - downTotalTime=$(( downTotalTime+downTimeMil )) - upTotalTime=$(( upTotalTime+upTimeMil )) - downAvgStr="$downAvgStr $downTimeMil" - upAvgStr="$upAvgStr $upTimeMil" - done - if [[ $downSuccessedCount -ge $downThreshold ]] && [[ "$downloadOrUpload" != "UP" ]] - then - downOK="YES" - downRealTime=$(( downTotalTime/downSuccessedCount )) else - downRealTime=0 - fi - if [[ $upSuccessedCount -ge $upThreshold ]] && [[ "$downloadOrUpload" != "DOWN" ]] - then - upOK="YES" - upRealTime=$(( upTotalTime/upSuccessedCount )) - else - upRealTime=0 + echo -e "${RED}FAILED${NC} $ip" fi - # shellcheck disable=SC2009 - pid=$(ps aux | grep config.json."$ip" | grep -v grep | awk '{ print $2 }') - if [[ "$pid" ]] - then - kill -9 "$pid" > /dev/null 2>&1 + done + elif [[ "$vpnOrNot" == "NO" ]]; then + for ip in ${ipList}; do + if [[ "$downloadOrUpload" == "BOTH" ]]; then + downOK="NO" + upOK="NO" + elif [[ "$downloadOrUpload" == "UP" ]]; then + downOK="YES" + upOK="NO" + elif [[ "$downloadOrUpload" == "DOWN" ]]; then + downOK="NO" + upOK="YES" fi - if [[ "$downOK" == "YES" ]] && [[ "$upOK" == "YES" ]] - then - if [[ "$downRealTime" && $downRealTime -gt 100 ]] || [[ "$upRealTime" && $upRealTime -gt 100 ]] - then - echo -e "${GREEN}OK${NC} $ip ${BLUE}DOWN: Avg $downRealTime $downAvgStr ${ORANGE}UP: Avg $upRealTime, $upAvgStr${NC}" - if [[ "$downRealTime" && $downRealTime -gt 100 ]] - then - #echo "${GREEN}OK${NC} $ip ${BLUE}DOWN: Avg $downRealTime $downAvgStr${NC}" - echo "$downRealTime, $downAvgStr DOWN FOR IP $ip" >> "$resultFile" - fi - if [[ "$upRealTime" && $upRealTime -gt 100 ]] - then - #echo "${GREEN}OK${NC} $ip ${BLUE}UP: $upRealTime, $upAvgStr${NC}" - echo "$upRealTime, $upAvgStr UP FOR IP $ip" >> "$resultFile" + if $timeoutCommand 1 bash -c "/dev/null 2>&1; then + if [[ "$quickOrNot" == "NO" ]]; then + domainFronting=$($timeoutCommand 1 curl -k -s --tlsv1.2 -H "Host: speed.cloudflare.com" --resolve "speed.cloudflare.com:443:$ip" "https://speed.cloudflare.com/__down?bytes=10") + elif [[ "$quickOrNot" == "YES" ]]; then + domainFronting="0000000000" fi - else - echo -e "${RED}FAILED${NC} $ip" - fi - else - echo -e "${RED}FAILED${NC} $ip" - fi - else - echo -e "${RED}FAILED${NC} $ip" - fi - else - echo -e "${RED}FAILED${NC} $ip" - fi - done - elif [[ "$vpnOrNot" == "NO" ]] - then - for ip in ${ipList} - do - if [[ "$downloadOrUpload" == "BOTH" ]] - then - downOK="NO" - upOK="NO" - elif [[ "$downloadOrUpload" == "UP" ]] - then - downOK="YES" - upOK="NO" - elif [[ "$downloadOrUpload" == "DOWN" ]] - then - downOK="NO" - upOK="YES" - fi - if $timeoutCommand 1 bash -c " /dev/null 2>&1; - then - if [[ "$quickOrNot" == "NO" ]] - then - domainFronting=$($timeoutCommand 1 curl -k -s --tlsv1.2 -H "Host: speed.cloudflare.com" --resolve "speed.cloudflare.com:443:$ip" "https://speed.cloudflare.com/__down?bytes=10") - elif [[ "$quickOrNot" == "YES" ]] - then - domainFronting="0000000000" - fi - if [[ "$domainFronting" == "0000000000" ]] - then - downTotalTime=0 - upTotalTime=0 - downAvgStr="" - upAvgStr="" - downSuccessedCount=0 - upSuccessedCount=0 - for i in $(seq 1 "$tryCount"); - do - downTimeMil=0 - upTimeMil=0 - if [[ "$downloadOrUpload" == "DOWN" ]] || [[ "$downloadOrUpload" == "BOTH" ]] - then - downTimeMil=$($timeoutCommand 2 curl -s -w "TIME: %{time_total}\n" -H "Host: speed.cloudflare.com" --resolve "speed.cloudflare.com:443:$ip" "https://speed.cloudflare.com/__down?bytes=$fileSize" --output /dev/null | grep "TIME" | tail -n 1 | awk '{print $2}' | xargs -I {} echo "{} * 1000 /1" | bc ) - if [[ $downTimeMil -gt 100 ]] - then - downSuccessedCount=$(( downSuccessedCount+1 )) + if [[ "$domainFronting" == "0000000000" ]]; then + downTotalTime=0 + upTotalTime=0 + downAvgStr="" + upAvgStr="" + downSuccessedCount=0 + upSuccessedCount=0 + for i in $(seq 1 "$tryCount"); do + downTimeMil=0 + upTimeMil=0 + if [[ "$downloadOrUpload" == "DOWN" ]] || [[ "$downloadOrUpload" == "BOTH" ]]; then + downTimeMil=$($timeoutCommand 2 curl -s -w "TIME: %{time_total}\n" -H "Host: speed.cloudflare.com" --resolve "speed.cloudflare.com:443:$ip" "https://speed.cloudflare.com/__down?bytes=$fileSize" --output /dev/null | grep "TIME" | tail -n 1 | awk '{print $2}' | xargs -I {} echo "{} * 1000 /1" | bc) + if [[ $downTimeMil -gt 100 ]]; then + downSuccessedCount=$((downSuccessedCount + 1)) + else + downTimeMil=0 + fi + fi + if [[ "$downloadOrUpload" == "UP" ]] || [[ "$downloadOrUpload" == "BOTH" ]]; then + result=$($timeoutCommand 2 curl -s -w "\nTIME: %{time_total}\n" -H "Host: speed.cloudflare.com" --resolve "speed.cloudflare.com:443:$ip" --data "@$uploadFile" https://speed.cloudflare.com/__up | grep "TIME" | tail -n 1 | awk '{print $2}' | xargs -I {} echo "{} * 1000 /1" | bc) + if [[ "$result" ]]; then + upTimeMil="$result" + if [[ $upTimeMil -gt 100 ]]; then + upSuccessedCount=$((upSuccessedCount + 1)) + else + upTimeMil=0 + fi + fi + fi + downTotalTime=$((downTotalTime + downTimeMil)) + upTotalTime=$((upTotalTime + upTimeMil)) + downAvgStr="$downAvgStr $downTimeMil" + upAvgStr="$upAvgStr $upTimeMil" + done + if [[ $downSuccessedCount -ge $downThreshold ]] && [[ "$downloadOrUpload" != "UP" ]]; then + downOK="YES" + downRealTime=$((downTotalTime / downSuccessedCount)) + else + downRealTime=0 + fi + if [[ $upSuccessedCount -ge $upThreshold ]] && [[ "$downloadOrUpload" != "DOWN" ]]; then + upOK="YES" + upRealTime=$((upTotalTime / upSuccessedCount)) + else + upRealTime=0 + fi + if [[ "$downOK" == "YES" ]] && [[ "$upOK" == "YES" ]]; then + if [[ "$downRealTime" && $downRealTime -gt 100 ]] || [[ "$upRealTime" && $upRealTime -gt 100 ]]; then + echo -e "${GREEN}OK${NC} $ip ${BLUE}DOWN: Avg $downRealTime $downAvgStr ${ORANGE}UP: Avg $upRealTime, $upAvgStr${NC}" + if [[ "$downRealTime" && $downRealTime -gt 100 ]]; then + #echo -e "${GREEN}OK${NC} $ip ${BLUE}DOWN: Avg $downRealTime $downAvgStr${NC}" + echo "$downRealTime, $downAvgStr DOWN FOR IP $ip" >>"$resultFile" + fi + if [[ "$upRealTime" && $upRealTime -gt 100 ]]; then + #echo -e "${GREEN}OK${NC} $ip ${BLUE}UP: $upRealTime, $upAvgStr${NC}" + echo "$upRealTime, $upAvgStr UP FOR IP $ip" >>"$resultFile" + fi + else + echo -e "${RED}FAILED${NC} $ip" + fi + else + echo -e "${RED}FAILED${NC} $ip" + fi else - downTimeMil=0 + echo -e "${RED}FAILED${NC} $ip" fi - fi - if [[ "$downloadOrUpload" == "UP" ]] || [[ "$downloadOrUpload" == "BOTH" ]] - then - result=$($timeoutCommand 2 curl -s -w "\nTIME: %{time_total}\n" -H "Host: speed.cloudflare.com" --resolve "speed.cloudflare.com:443:$ip" --data "@$uploadFile" https://speed.cloudflare.com/__up | grep "TIME" | tail -n 1 | awk '{print $2}' | xargs -I {} echo "{} * 1000 /1" | bc) - if [[ "$result" ]] - then - upTimeMil="$result" - if [[ $upTimeMil -gt 100 ]] - then - upSuccessedCount=$(( upSuccessedCount+1 )) - else - upTimeMil=0 - fi - fi - fi - downTotalTime=$(( downTotalTime+downTimeMil )) - upTotalTime=$(( upTotalTime+upTimeMil )) - downAvgStr="$downAvgStr $downTimeMil" - upAvgStr="$upAvgStr $upTimeMil" - done - if [[ $downSuccessedCount -ge $downThreshold ]] && [[ "$downloadOrUpload" != "UP" ]] - then - downOK="YES" - downRealTime=$(( downTotalTime/downSuccessedCount )) - else - downRealTime=0 - fi - if [[ $upSuccessedCount -ge $upThreshold ]] && [[ "$downloadOrUpload" != "DOWN" ]] - then - upOK="YES" - upRealTime=$(( upTotalTime/upSuccessedCount )) else - upRealTime=0 - fi - if [[ "$downOK" == "YES" ]] && [[ "$upOK" == "YES" ]] - then - if [[ "$downRealTime" && $downRealTime -gt 100 ]] || [[ "$upRealTime" && $upRealTime -gt 100 ]] - then - echo -e "${GREEN}OK${NC} $ip ${BLUE}DOWN: Avg $downRealTime $downAvgStr ${ORANGE}UP: Avg $upRealTime, $upAvgStr${NC}" - if [[ "$downRealTime" && $downRealTime -gt 100 ]] - then - #echo -e "${GREEN}OK${NC} $ip ${BLUE}DOWN: Avg $downRealTime $downAvgStr${NC}" - echo "$downRealTime, $downAvgStr DOWN FOR IP $ip" >> "$resultFile" - fi - if [[ "$upRealTime" && $upRealTime -gt 100 ]] - then - #echo -e "${GREEN}OK${NC} $ip ${BLUE}UP: $upRealTime, $upAvgStr${NC}" - echo "$upRealTime, $upAvgStr UP FOR IP $ip" >> "$resultFile" - fi - else echo -e "${RED}FAILED${NC} $ip" - fi - else - echo -e "${RED}FAILED${NC} $ip" fi - else - echo -e "${RED}FAILED${NC} $ip" - fi - else - echo -e "${RED}FAILED${NC} $ip" - fi - done - fi + done + fi } # End of Function fncCheckIPList export -f fncCheckIPList @@ -478,231 +413,238 @@ export -f fncCheckIPList # Function fncCheckDpnd # Check for dipendencies function fncCheckDpnd { - osVersion="NULL" - if [[ "$(uname)" == "Linux" ]]; then - command -v jq >/dev/null 2>&1 || { echo >&2 "I require 'jq' but it's not installed. Please install it and try again."; kill -s 1 "$TOP_PID"; } - command -v parallel >/dev/null 2>&1 || { echo >&2 "I require 'parallel' but it's not installed. Please install it and try again."; kill -s 1 "$TOP_PID"; } - command -v bc >/dev/null 2>&1 || { echo >&2 "I require 'bc' but it's not installed. Please install it and try again."; kill -s 1 "$TOP_PID"; } - command -v timeout >/dev/null 2>&1 || { echo >&2 "I require 'timeout' but it's not installed. Please install it and try again."; kill -s 1 "$TOP_PID"; } - osVersion="Linux" - elif [[ "$(uname)" == "Darwin" ]];then - command -v jq >/dev/null 2>&1 || { echo >&2 "I require 'jq' but it's not installed. Please install it and try again."; kill -s 1 "$TOP_PID"; } - command -v parallel >/dev/null 2>&1 || { echo >&2 "I require 'parallel' but it's not installed. Please install it and try again."; kill -s 1 "$TOP_PID"; } - command -v bc >/dev/null 2>&1 || { echo >&2 "I require 'bc' but it's not installed. Please install it and try again."; kill -s 1 "$TOP_PID"; } - command -v gtimeout >/dev/null 2>&1 || { echo >&2 "I require 'gtimeout' but it's not installed. Please install it and try again."; kill -s 1 "$TOP_PID"; } - osVersion="Mac" - fi - echo "$osVersion" + osVersion="NULL" + if [[ "$(uname)" == "Linux" ]]; then + command -v jq >/dev/null 2>&1 || { + echo >&2 "I require 'jq' but it's not installed. Please install it and try again." + kill -s 1 "$TOP_PID" + } + command -v parallel >/dev/null 2>&1 || { + echo >&2 "I require 'parallel' but it's not installed. Please install it and try again." + kill -s 1 "$TOP_PID" + } + command -v bc >/dev/null 2>&1 || { + echo >&2 "I require 'bc' but it's not installed. Please install it and try again." + kill -s 1 "$TOP_PID" + } + command -v timeout >/dev/null 2>&1 || { + echo >&2 "I require 'timeout' but it's not installed. Please install it and try again." + kill -s 1 "$TOP_PID" + } + osVersion="Linux" + elif [[ "$(uname)" == "Darwin" ]]; then + command -v jq >/dev/null 2>&1 || { + echo >&2 "I require 'jq' but it's not installed. Please install it and try again." + kill -s 1 "$TOP_PID" + } + command -v parallel >/dev/null 2>&1 || { + echo >&2 "I require 'parallel' but it's not installed. Please install it and try again." + kill -s 1 "$TOP_PID" + } + command -v bc >/dev/null 2>&1 || { + echo >&2 "I require 'bc' but it's not installed. Please install it and try again." + kill -s 1 "$TOP_PID" + } + command -v gtimeout >/dev/null 2>&1 || { + echo >&2 "I require 'gtimeout' but it's not installed. Please install it and try again." + kill -s 1 "$TOP_PID" + } + osVersion="Mac" + fi + echo "$osVersion" } # End of Function fncCheckDpnd # Function fncValidateConfig # Install packages on destination host function fncValidateConfig { - local config - config="$1" - if [[ -f "$config" ]] - then - echo "reading config ..." - configId=$(jq --raw-output .id "$config") - configHost=$(jq --raw-output .host "$config") - configPort=$(jq --raw-output .port "$config") - configPath=$(jq --raw-output .path "$config") - if ! [[ "$configId" ]] || ! [[ $configHost ]] || ! [[ $configPort ]] || ! [[ $configPath ]] - then - echo "config is not correct" - exit 1 + local config + config="$1" + if [[ -f "$config" ]]; then + echo "reading config ..." + configId=$(jq --raw-output .id "$config") + configHost=$(jq --raw-output .host "$config") + configPort=$(jq --raw-output .port "$config") + configPath=$(jq --raw-output .path "$config") + if ! [[ "$configId" ]] || ! [[ $configHost ]] || ! [[ $configPort ]] || ! [[ $configPath ]]; then + echo "config is not correct" + exit 1 + fi + else + echo "config file does not exist $config" + exit 1 fi - else - echo "config file does not exist $config" - exit 1 - fi } # End of Function fncValidateConfig # Function fncCreateDir # creates needed directory function fncCreateDir { - local dirPath - dirPath="${1}" - if [ ! -d "$dirPath" ]; then - mkdir -p "$dirPath" - fi + local dirPath + dirPath="${1}" + if [ ! -d "$dirPath" ]; then + mkdir -p "$dirPath" + fi } # End of Function fncCreateDir # Function fncMainCFFindSubnet # main Function for Subnet function fncMainCFFindSubnet { - local threads progressBar resultFile scriptDir configId configHost configPort configPath fileSize osVersion parallelVersion subnetsFile breakedSubnets network netmask downloadOrUpload tryCount downThreshold upThreshold vpnOrNot quickOrNot - threads="${1}" - progressBar="${2}" - resultFile="${3}" - scriptDir="${4}" - configId="${5}" - configHost="${6}" - configPort="${7}" - configPath="${8}" - fileSize="${9}" - osVersion="${10}" - subnetsFile="${11}" - tryCount="${12}" - downThreshold="${13}" - upThreshold="${14}" - downloadOrUpload="${15}" - vpnOrNot="${16}" - quickOrNot="${17}" - - if [[ "$osVersion" == "Linux" ]] - then - if [[ "$clientCore" == "XRAY" ]] - then - clientCommand="xray" - else - clientCommand="v2ray" - fi - elif [[ "$osVersion" == "Mac" ]] - then - clientCommand="v2ray-mac" - else - echo "OS not supported only Linux or Mac" - exit 1 - fi - - parallelVersion=$(parallel --version | head -n1 | grep -Ewo '[0-9]{8}') - defaultSubnetsFileUrl="https://raw.githubusercontent.com/MortezaBashsiz/CFScanner/main/config/cf.local.iplist" - - if [[ "$subnetsFile" == "NULL" ]] - then - defaultSubnetsFileUrlResult=$(curl -I -L -s "$defaultSubnetsFileUrl" | grep "^HTTP" | grep 200 | awk '{ print $2 }') - if [[ "$defaultSubnetsFileUrlResult" == "200" ]] - then - defaultSubnetsFile=$(curl -s "$defaultSubnetsFileUrl") - echo "Reading subnets from $defaultSubnetsFileUrl" - cfSubnetList="$defaultSubnetsFile" + local threads progressBar resultFile scriptDir configId configHost configPort configPath fileSize osVersion parallelVersion subnetsFile breakedSubnets network netmask downloadOrUpload tryCount downThreshold upThreshold vpnOrNot quickOrNot + threads="${1}" + progressBar="${2}" + resultFile="${3}" + scriptDir="${4}" + configId="${5}" + configHost="${6}" + configPort="${7}" + configPath="${8}" + fileSize="${9}" + osVersion="${10}" + subnetsFile="${11}" + tryCount="${12}" + downThreshold="${13}" + upThreshold="${14}" + downloadOrUpload="${15}" + vpnOrNot="${16}" + quickOrNot="${17}" + + if [[ "$osVersion" == "Linux" ]]; then + if [[ "$clientCore" == "XRAY" ]]; then + clientCommand="xray" + else + clientCommand="v2ray" + fi + elif [[ "$osVersion" == "Mac" ]]; then + clientCommand="v2ray-mac" else - echo "URL $defaultSubnetsFileUrl is not available. This URL contains the latest subnet file" - echo "Reading subnets from file $scriptDir/../config/cf.local.iplist" - cfSubnetList=$(cat "$scriptDir/../config/cf.local.iplist") + echo "OS not supported only Linux or Mac" + exit 1 fi - else - echo "Reading subnets from file $subnetsFile" - cfSubnetList=$(cat "$subnetsFile") - fi - - ipListLength="0" - for subNet in ${cfSubnetList} - do - breakedSubnets= - maxSubnet=24 - network=${subNet%/*} - netmask=${subNet#*/} - if [[ ${netmask} -ge ${maxSubnet} ]] - then - breakedSubnets="${breakedSubnets} ${network}/${netmask}" + + parallelVersion=$(parallel --version | head -n1 | grep -Ewo '[0-9]{8}') + defaultSubnetsFileUrl="https://raw.githubusercontent.com/MortezaBashsiz/CFScanner/main/config/cf.local.iplist" + + if [[ "$subnetsFile" == "NULL" ]]; then + defaultSubnetsFileUrlResult=$(curl -I -L -s "$defaultSubnetsFileUrl" | grep "^HTTP" | grep 200 | awk '{ print $2 }') + if [[ "$defaultSubnetsFileUrlResult" == "200" ]]; then + defaultSubnetsFile=$(curl -s "$defaultSubnetsFileUrl") + echo "Reading subnets from $defaultSubnetsFileUrl" + cfSubnetList="$defaultSubnetsFile" + else + echo "URL $defaultSubnetsFileUrl is not available. This URL contains the latest subnet file" + echo "Reading subnets from file $scriptDir/../config/cf.local.iplist" + cfSubnetList=$(cat "$scriptDir/../config/cf.local.iplist") + fi else - for i in $(seq 0 $(( $(( 2 ** (maxSubnet - netmask) )) - 1 )) ) - do - breakedSubnets="${breakedSubnets} $( fncLongIntToStr $(( $( fncIpToLongInt "${network}" ) + $(( 2 ** ( 32 - maxSubnet ) * i )) )) )/${maxSubnet}" - done + echo "Reading subnets from file $subnetsFile" + cfSubnetList=$(cat "$subnetsFile") fi - breakedSubnets=$(echo "${breakedSubnets}"|tr ' ' '\n') - for breakedSubnet in ${breakedSubnets} - do - ipListLength=$(( ipListLength+1 )) + + ipListLength="0" + for subNet in ${cfSubnetList}; do + breakedSubnets= + maxSubnet=24 + network=${subNet%/*} + netmask=${subNet#*/} + if [[ ${netmask} -ge ${maxSubnet} ]]; then + breakedSubnets="${breakedSubnets} ${network}/${netmask}" + else + for i in $(seq 0 $(($((2 ** (maxSubnet - netmask))) - 1))); do + breakedSubnets="${breakedSubnets} $(fncLongIntToStr $(($(fncIpToLongInt "${network}") + $((2 ** (32 - maxSubnet) * i)))))/${maxSubnet}" + done + fi + breakedSubnets=$(echo "${breakedSubnets}" | tr ' ' '\n') + for breakedSubnet in ${breakedSubnets}; do + ipListLength=$((ipListLength + 1)) + done done - done - - passedIpsCount=0 - for subNet in ${cfSubnetList} - do - breakedSubnets= - maxSubnet=24 - network=${subNet%/*} - netmask=${subNet#*/} - if [[ ${netmask} -ge ${maxSubnet} ]] - then - breakedSubnets="${breakedSubnets} ${network}/${netmask}" - else - for i in $(seq 0 $(( $(( 2 ** (maxSubnet - netmask) )) - 1 )) ) - do - breakedSubnets="${breakedSubnets} $( fncLongIntToStr $(( $( fncIpToLongInt "${network}" ) + $(( 2 ** ( 32 - maxSubnet ) * i )) )) )/${maxSubnet}" - done - fi - breakedSubnets=$(echo "${breakedSubnets}"|tr ' ' '\n') - for breakedSubnet in ${breakedSubnets} - do - fncShowProgress "$passedIpsCount" "$ipListLength" - killall v2ray > /dev/null 2>&1 - ipList=$(fncSubnetToIP "$breakedSubnet") - tput cuu1; tput ed # rewrites Parallel's bar - if [[ $parallelVersion -gt 20220515 ]]; - then - parallel --ll --bar -j "$threads" fncCheckIPList ::: "$ipList" ::: "$progressBar" ::: "$resultFile" ::: "$scriptDir" ::: "$configId" ::: "$configHost" ::: "$configPort" ::: "$configPath" ::: "$fileSize" ::: "$osVersion" ::: "$clientCommand" ::: "$tryCount" ::: "$downThreshold" ::: "$upThreshold" ::: "$downloadOrUpload" ::: "$vpnOrNot" ::: "$quickOrNot" - else - echo -e "${RED}$progressBar${NC}" - parallel -j "$threads" fncCheckIPList ::: "$ipList" ::: "$progressBar" ::: "$resultFile" ::: "$scriptDir" ::: "$configId" ::: "$configHost" ::: "$configPort" ::: "$configPath" ::: "$fileSize" ::: "$osVersion" ::: "$clientCommand" ::: "$tryCount" ::: "$downThreshold" ::: "$upThreshold" ::: "$downloadOrUpload" ::: "$vpnOrNot" ::: "$quickOrNot" - fi - killall v2ray > /dev/null 2>&1 - passedIpsCount=$(( passedIpsCount+1 )) + + + passedIpsCount=0 + for subNet in ${cfSubnetList}; do + breakedSubnets= + maxSubnet=24 + network=${subNet%/*} + netmask=${subNet#*/} + if [[ ${netmask} -ge ${maxSubnet} ]]; then + breakedSubnets="${breakedSubnets} ${network}/${netmask}" + else + for i in $(seq 0 $(($((2 ** (maxSubnet - netmask))) - 1))); do + breakedSubnets="${breakedSubnets} $(fncLongIntToStr $(($(fncIpToLongInt "${network}") + $((2 ** (32 - maxSubnet) * i)))))/${maxSubnet}" + done + fi + breakedSubnets=$(echo "${breakedSubnets}" | tr ' ' '\n') + for breakedSubnet in ${breakedSubnets}; do + fncShowProgress "$passedIpsCount" "$ipListLength" + killall v2ray >/dev/null 2>&1 + ipList=$(fncSubnetToIP "$breakedSubnet") + tput cuu1 + tput ed # rewrites Parallel's bar + if [[ $parallelVersion -gt 20220515 ]]; then + parallel --ll --bar -j "$threads" fncCheckIPList ::: "$ipList" ::: "$progressBar" ::: "$resultFile" ::: "$scriptDir" ::: "$configId" ::: "$configHost" ::: "$configPort" ::: "$configPath" ::: "$fileSize" ::: "$osVersion" ::: "$clientCommand" ::: "$tryCount" ::: "$downThreshold" ::: "$upThreshold" ::: "$downloadOrUpload" ::: "$vpnOrNot" ::: "$quickOrNot" + else + echo -e "${RED}$progressBar${NC}" + parallel -j "$threads" fncCheckIPList ::: "$ipList" ::: "$progressBar" ::: "$resultFile" ::: "$scriptDir" ::: "$configId" ::: "$configHost" ::: "$configPort" ::: "$configPath" ::: "$fileSize" ::: "$osVersion" ::: "$clientCommand" ::: "$tryCount" ::: "$downThreshold" ::: "$upThreshold" ::: "$downloadOrUpload" ::: "$vpnOrNot" ::: "$quickOrNot" + fi + killall v2ray >/dev/null 2>&1 + passedIpsCount=$((passedIpsCount + 1)) + done done - done - sort -n -k1 -t, "$resultFile" -o "$resultFile" + sort -n -k1 -t, "$resultFile" -o "$resultFile" } # End of Function fncMainCFFindSubnet # Function fncMainCFFindIP # main Function for IP function fncMainCFFindIP { - local threads progressBar resultFile scriptDir configId configHost configPort configPath fileSize osVersion parallelVersion IPFile downloadOrUpload downThreshold upThreshold vpnOrNot quickOrNot - threads="${1}" - progressBar="${2}" - resultFile="${3}" - scriptDir="${4}" - configId="${5}" - configHost="${6}" - configPort="${7}" - configPath="${8}" - fileSize="${9}" - osVersion="${10}" - IPFile="${11}" - tryCount="${12}" - downThreshold="${13}" - upThreshold="${14}" - downloadOrUpload="${15}" - vpnOrNot="${16}" - quickOrNot="${17}" - - if [[ "$osVersion" == "Linux" ]] - then - if [[ "$clientCore" == "XRAY" ]] - then - clientCommand="xray" + local threads progressBar resultFile scriptDir configId configHost configPort configPath fileSize osVersion parallelVersion IPFile downloadOrUpload downThreshold upThreshold vpnOrNot quickOrNot + threads="${1}" + progressBar="${2}" + resultFile="${3}" + scriptDir="${4}" + configId="${5}" + configHost="${6}" + configPort="${7}" + configPath="${8}" + fileSize="${9}" + osVersion="${10}" + IPFile="${11}" + tryCount="${12}" + downThreshold="${13}" + upThreshold="${14}" + downloadOrUpload="${15}" + vpnOrNot="${16}" + quickOrNot="${17}" + + if [[ "$osVersion" == "Linux" ]]; then + if [[ "$clientCore" == "XRAY" ]]; then + clientCommand="xray" + else + clientCommand="v2ray" + fi + elif [[ "$osVersion" == "Mac" ]]; then + clientCommand="v2ray-mac" else - clientCommand="v2ray" + echo "OS not supported only Linux or Mac" + exit 1 fi - elif [[ "$osVersion" == "Mac" ]] - then - clientCommand="v2ray-mac" - else - echo "OS not supported only Linux or Mac" - exit 1 - fi - - parallelVersion=$(parallel --version | head -n1 | grep -Ewo '[0-9]{8}') - - cfIPList=$(cat "$IPFile") - killall v2ray > /dev/null 2>&1 - tput cuu1; tput ed # rewrites Parallel's bar - if [[ $parallelVersion -gt 20220515 ]]; - then - parallel --ll --bar -j "$threads" fncCheckIPList ::: "$cfIPList" ::: "$progressBar" ::: "$resultFile" ::: "$scriptDir" ::: "$configId" ::: "$configHost" ::: "$configPort" ::: "$configPath" ::: "$fileSize" ::: "$osVersion" ::: "$clientCommand" ::: "$tryCount" ::: "$downThreshold" ::: "$upThreshold" ::: "$downloadOrUpload" ::: "$vpnOrNot" ::: "$quickOrNot" - else - echo -e "${RED}$progressBar${NC}" - parallel -j "$threads" fncCheckIPList ::: "$cfIPList" ::: "$progressBar" ::: "$resultFile" ::: "$scriptDir" ::: "$configId" ::: "$configHost" ::: "$configPort" ::: "$configPath" ::: "$fileSize" ::: "$osVersion" ::: "$clientCommand" ::: "$tryCount" ::: "$downThreshold" ::: "$upThreshold" ::: "$downloadOrUpload" ::: "$vpnOrNot" ::: "$quickOrNot" - fi - killall v2ray > /dev/null 2>&1 - sort -n -k1 -t, "$resultFile" -o "$resultFile" + + parallelVersion=$(parallel --version | head -n1 | grep -Ewo '[0-9]{8}') + + cfIPList=$(cat "$IPFile") + killall v2ray >/dev/null 2>&1 + tput cuu1 + tput ed # rewrites Parallel's bar + if [[ $parallelVersion -gt 20220515 ]]; then + parallel --ll --bar -j "$threads" fncCheckIPList ::: "$cfIPList" ::: "$progressBar" ::: "$resultFile" ::: "$scriptDir" ::: "$configId" ::: "$configHost" ::: "$configPort" ::: "$configPath" ::: "$fileSize" ::: "$osVersion" ::: "$clientCommand" ::: "$tryCount" ::: "$downThreshold" ::: "$upThreshold" ::: "$downloadOrUpload" ::: "$vpnOrNot" ::: "$quickOrNot" + else + echo -e "${RED}$progressBar${NC}" + parallel -j "$threads" fncCheckIPList ::: "$cfIPList" ::: "$progressBar" ::: "$resultFile" ::: "$scriptDir" ::: "$configId" ::: "$configHost" ::: "$configPort" ::: "$configPath" ::: "$fileSize" ::: "$osVersion" ::: "$clientCommand" ::: "$tryCount" ::: "$downThreshold" ::: "$upThreshold" ::: "$downloadOrUpload" ::: "$vpnOrNot" ::: "$quickOrNot" + fi + killall v2ray >/dev/null 2>&1 + sort -n -k1 -t, "$resultFile" -o "$resultFile" } # End of Function fncMainCFFindIP @@ -712,10 +654,9 @@ subnetIPFile="NULL" # Function fncUsage # usage function function fncUsage { - if [[ "$osVersion" == "Mac" ]] - then - echo -e "Usage: cfScanner [ -v YES/NO ] - [ -m SUBNET/IP ] + if [[ "$osVersion" == "Mac" ]]; then + echo -e "Usage: cfScanner [ -v YES/NO ] + [ -m SUBNET/IP ] [ -t DOWN/UP/BOTH ] [ -p ] threads [ -n ] trycount @@ -727,25 +668,24 @@ function fncUsage { [ -f (if you chose IP mode)] [ -q YES/NO] [ -h ] help\n" - exit 2 - elif [[ "$osVersion" == "Linux" ]] - then - echo -e "Usage: cfScanner [ -x|--core V2RAY/XRAY ] + exit 2 + elif [[ "$osVersion" == "Linux" ]]; then + echo -e "Usage: cfScanner [ -x|--core V2RAY/XRAY ] [ -v|--vpn-mode YES/NO ] - [ -m|--mode SUBNET/IP ] + [ -m|--mode SUBNET/IP ] [ -t|--test-type DOWN/UP/BOTH ] [ -p|--thread ] [ -n|--tryCount ] [ -c|--config ] - [ -s|--speed ] + [ -s|--speed ] [ -r|--random ] [ -d|--down-threshold ] [ -u|--up-threshold ] [ -f|--file (if you chose IP mode)] [ -q|--quick YES/NO] [ -h|--help ]\n" - exit 2 - fi + exit 2 + fi } # End of Function fncUsage @@ -763,102 +703,175 @@ config="NULL" speed="100" quickOrNot="NO" -if [[ "$osVersion" == "Mac" ]] -then - parsedArguments=$(getopt v:m:t:p:n:c:s:r:d:u:f:q:h "$@") -elif [[ "$osVersion" == "Linux" ]] -then - parsedArguments=$(getopt -a -n cfScanner -o v:m:t:p:n:c:s:r:d:u:f:q:h --long vpn-mode:,mode:,test-type:,thread:,tryCount:,config:,speed:,random:,down-threshold:,up-threshold:,file:,quick:,help -- "$@") +if [[ "$osVersion" == "Mac" ]]; then + parsedArguments=$(getopt v:m:t:p:n:c:s:r:d:u:f:q:h "$@") +elif [[ "$osVersion" == "Linux" ]]; then + parsedArguments=$(getopt -a -n cfScanner -o v:m:t:p:n:c:s:r:d:u:f:q:h --long vpn-mode:,mode:,test-type:,thread:,tryCount:,config:,speed:,random:,down-threshold:,up-threshold:,file:,quick:,help -- "$@") fi eval set -- "$parsedArguments" -if [[ "$osVersion" == "Mac" ]] -then - while : - do - case "$1" in - -v) vpnOrNot="$2" ; shift 2 ;; - -m) subnetOrIP="$2" ; shift 2 ;; - -t) downloadOrUpload="$2" ; shift 2 ;; - -p) threads="$2" ; shift 2 ;; - -n) tryCount="$2" ; shift 2 ;; - -c) config="$2" ; shift 2 ;; - -s) speed="$2" ; shift 2 ;; - -r) randomNumber="$2" ; shift 2 ;; - -d) downThreshold="$2" ; shift 2 ;; - -u) upThreshold="$2" ; shift 2 ;; - -f) subnetIPFile="$2" ; shift 2 ;; - -q) quickOrNot="$2" ; shift 2 ;; - -h) fncUsage ;; - --) shift; break ;; - *) echo "Unexpected option: $1 is not acceptable" - fncUsage ;; - esac - done -elif [[ "$osVersion" == "Linux" ]] -then - while : - do - case "$1" in - -x|--core) clientCore="$2" ; shift 2 ;; - -v|--vpn-mode) vpnOrNot="$2" ; shift 2 ;; - -m|--mode) subnetOrIP="$2" ; shift 2 ;; - -t|--test-type) downloadOrUpload="$2" ; shift 2 ;; - -p|--thread) threads="$2" ; shift 2 ;; - -n|--tryCount) tryCount="$2" ; shift 2 ;; - -c|--config) config="$2" ; shift 2 ;; - -s|--speed) speed="$2" ; shift 2 ;; - -r|--random) randomNumber="$2" ; shift 2 ;; - -d|--down-threshold) downThreshold="$2" ; shift 2 ;; - -u|--up-threshold) upThreshold="$2" ; shift 2 ;; - -f|--file) subnetIPFile="$2" ; shift 2 ;; - -q|--quick) quickOrNot="$2" ; shift 2 ;; - -h|--help) fncUsage ;; - --) shift; break ;; - *) echo "Unexpected option: $1 is not acceptable" - fncUsage ;; - esac - done +if [[ "$osVersion" == "Mac" ]]; then + while :; do + case "$1" in + -v) + vpnOrNot="$2" + shift 2 + ;; + -m) + subnetOrIP="$2" + shift 2 + ;; + -t) + downloadOrUpload="$2" + shift 2 + ;; + -p) + threads="$2" + shift 2 + ;; + -n) + tryCount="$2" + shift 2 + ;; + -c) + config="$2" + shift 2 + ;; + -s) + speed="$2" + shift 2 + ;; + -r) + randomNumber="$2" + shift 2 + ;; + -d) + downThreshold="$2" + shift 2 + ;; + -u) + upThreshold="$2" + shift 2 + ;; + -f) + subnetIPFile="$2" + shift 2 + ;; + -q) + quickOrNot="$2" + shift 2 + ;; + -h) fncUsage ;; + --) + shift + break + ;; + *) + echo "Unexpected option: $1 is not acceptable" + fncUsage + ;; + esac + done +elif [[ "$osVersion" == "Linux" ]]; then + while :; do + case "$1" in + -x | --core) + clientCore="$2" + shift 2 + ;; + -v | --vpn-mode) + vpnOrNot="$2" + shift 2 + ;; + -m | --mode) + subnetOrIP="$2" + shift 2 + ;; + -t | --test-type) + downloadOrUpload="$2" + shift 2 + ;; + -p | --thread) + threads="$2" + shift 2 + ;; + -n | --tryCount) + tryCount="$2" + shift 2 + ;; + -c | --config) + config="$2" + shift 2 + ;; + -s | --speed) + speed="$2" + shift 2 + ;; + -r | --random) + randomNumber="$2" + shift 2 + ;; + -d | --down-threshold) + downThreshold="$2" + shift 2 + ;; + -u | --up-threshold) + upThreshold="$2" + shift 2 + ;; + -f | --file) + subnetIPFile="$2" + shift 2 + ;; + -q | --quick) + quickOrNot="$2" + shift 2 + ;; + -h | --help) fncUsage ;; + --) + shift + break + ;; + *) + echo "Unexpected option: $1 is not acceptable" + fncUsage + ;; + esac + done fi validArguments=$? if [ "$validArguments" != "0" ]; then - echo "error validate" - exit 2 + echo "error validate" + exit 2 fi -if [[ "$clientCore" != "XRAY" && "$clientCore" != "V2RAY" ]] -then - echo "Wrong value: $clientCore Must be XRAY or V2RAY" - exit 2 +if [[ "$clientCore" != "XRAY" && "$clientCore" != "V2RAY" ]]; then + echo "Wrong value: $clientCore Must be XRAY or V2RAY" + exit 2 fi -if [[ "$vpnOrNot" != "YES" && "$vpnOrNot" != "NO" ]] -then - echo "Wrong value: $vpnOrNot Must be YES or NO" - exit 2 +if [[ "$vpnOrNot" != "YES" && "$vpnOrNot" != "NO" ]]; then + echo "Wrong value: $vpnOrNot Must be YES or NO" + exit 2 fi -if [[ "$subnetOrIP" != "SUBNET" && "$subnetOrIP" != "IP" ]] -then - echo "Wrong value: $subnetOrIP Must be SUBNET or IP" - exit 2 +if [[ "$subnetOrIP" != "SUBNET" && "$subnetOrIP" != "IP" ]]; then + echo "Wrong value: $subnetOrIP Must be SUBNET or IP" + exit 2 fi -if [[ "$downloadOrUpload" != "DOWN" && "$downloadOrUpload" != "UP" && "$downloadOrUpload" != "BOTH" ]] -then - echo "Wrong value: $downloadOrUpload Must be DOWN or UP or BOTH" - exit 2 +if [[ "$downloadOrUpload" != "DOWN" && "$downloadOrUpload" != "UP" && "$downloadOrUpload" != "BOTH" ]]; then + echo "Wrong value: $downloadOrUpload Must be DOWN or UP or BOTH" + exit 2 fi -if [[ "$subnetIPFile" != "NULL" ]] -then - if ! [[ -f "$subnetIPFile" ]] - then - echo "file does not exists: $subnetIPFile" - exit 1 - fi +if [[ "$subnetIPFile" != "NULL" ]]; then + if ! [[ -f "$subnetIPFile" ]]; then + echo "file does not exists: $subnetIPFile" + exit 1 + fi fi now=$(date +"%Y%m%d-%H%M%S") -scriptDir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +scriptDir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) resultDir="$scriptDir/result" resultFile="$resultDir/$now-result.cf" tempConfigDir="$scriptDir/tempConfig" @@ -882,55 +895,49 @@ export NC='\033[0m' fncCreateDir "${resultDir}" fncCreateDir "${tempConfigDir}" -echo "" > "$resultFile" - -if [[ "$config" == "NULL" ]] -then - echo "updating config" - configRealUrlResult=$(curl -I -L -s "$clientConfigFile" | grep "^HTTP" | grep 200 | awk '{ print $2 }') - if [[ "$configRealUrlResult" == "200" ]] - then - curl -s "$clientConfigFile" -o "$scriptDir"/config.default - echo "config.default updated with $clientConfigFile" +echo "" >"$resultFile" + +if [[ "$config" == "NULL" ]]; then + echo "updating config" + configRealUrlResult=$(curl -I -L -s "$clientConfigFile" | grep "^HTTP" | grep 200 | awk '{ print $2 }') + if [[ "$configRealUrlResult" == "200" ]]; then + curl -s "$clientConfigFile" -o "$scriptDir"/config.default + echo "config.default updated with $clientConfigFile" + echo "" + config="$scriptDir/config.default" + cat "$config" + else + echo "" + echo "config file is not available $clientConfigFile" + echo "use your own" + echo "" + exit 1 + fi +else echo "" - config="$scriptDir/config.default" + echo "using your own config $config" cat "$config" - else echo "" - echo "config file is not available $clientConfigFile" - echo "use your own" - echo "" - exit 1 - fi -else - echo "" - echo "using your own config $config" - cat "$config" - echo "" fi -fileSize="$(( 2*speed*1024 ))" -if [[ "$downloadOrUpload" == "DOWN" || "$downloadOrUpload" == "BOTH" ]] -then - echo "You are testing download" +fileSize="$((2 * speed * 1024))" +if [[ "$downloadOrUpload" == "DOWN" || "$downloadOrUpload" == "BOTH" ]]; then + echo "You are testing download" fi -if [[ "$downloadOrUpload" == "UP" || "$downloadOrUpload" == "BOTH" ]] -then - echo "You are testing upload" - echo "making upload file by size $fileSize Bytes in $uploadFile" - ddSize="$(( 2*speed ))" - dd if=/dev/random of="$uploadFile" bs=1024 count="$ddSize" > /dev/null 2>&1 +if [[ "$downloadOrUpload" == "UP" || "$downloadOrUpload" == "BOTH" ]]; then + echo "You are testing upload" + echo "making upload file by size $fileSize Bytes in $uploadFile" + ddSize="$((2 * speed))" + dd if=/dev/random of="$uploadFile" bs=1024 count="$ddSize" >/dev/null 2>&1 fi fncValidateConfig "$config" -if [[ "$subnetOrIP" == "SUBNET" ]] -then - fncMainCFFindSubnet "$threads" "$progressBar" "$resultFile" "$scriptDir" "$configId" "$configHost" "$configPort" "$configPath" "$fileSize" "$osVersion" "$subnetIPFile" "$tryCount" "$downThreshold" "$upThreshold" "$downloadOrUpload" "$vpnOrNot" "$quickOrNot" -elif [[ "$subnetOrIP" == "IP" ]] -then - fncMainCFFindIP "$threads" "$progressBar" "$resultFile" "$scriptDir" "$configId" "$configHost" "$configPort" "$configPath" "$fileSize" "$osVersion" "$subnetIPFile" "$tryCount" "$downThreshold" "$upThreshold" "$downloadOrUpload" "$vpnOrNot" "$quickOrNot" +if [[ "$subnetOrIP" == "SUBNET" ]]; then + fncMainCFFindSubnet "$threads" "$progressBar" "$resultFile" "$scriptDir" "$configId" "$configHost" "$configPort" "$configPath" "$fileSize" "$osVersion" "$subnetIPFile" "$tryCount" "$downThreshold" "$upThreshold" "$downloadOrUpload" "$vpnOrNot" "$quickOrNot" +elif [[ "$subnetOrIP" == "IP" ]]; then + fncMainCFFindIP "$threads" "$progressBar" "$resultFile" "$scriptDir" "$configId" "$configHost" "$configPort" "$configPath" "$fileSize" "$osVersion" "$subnetIPFile" "$tryCount" "$downThreshold" "$upThreshold" "$downloadOrUpload" "$vpnOrNot" "$quickOrNot" else - echo "$subnetOrIP is not correct choose one SUBNET or IP" - exit 1 + echo "$subnetOrIP is not correct choose one SUBNET or IP" + exit 1 fi