Skip to content

Instantly share code, notes, and snippets.

@zhpjy
Created March 27, 2024 09:02
Show Gist options
  • Select an option

  • Save zhpjy/01a141cdf2624d00db1b005fc342db4b to your computer and use it in GitHub Desktop.

Select an option

Save zhpjy/01a141cdf2624d00db1b005fc342db4b to your computer and use it in GitHub Desktop.
get better cf ip
#!/usr/bin/bash
CIDR_LIST=${CIDR_LIST:-}
CIDR_URL=${CIDR_URL:-"https://www.cloudflare.com/ips-v4"}
fping_shuf=
fping_interval=1
fping_count=3
fping_period=1000
st_url=https://speed.cloudflare.com/__down?bytes=125000000
st_parallel=10
st_line=100
st_time=10
print_line=10
quiet=false
function parse_args() {
while getopts "f:c:u:p:s:t:l:q" opt; do
case "$opt" in
f)
fping_shuf=$OPTARG
;;
c)
fping_count=$OPTARG
;;
u)
st_url=$OPTARG
;;
p)
st_parallel=$OPTARG
;;
s)
st_line=$OPTARG
;;
t)
st_time=$OPTARG
;;
l)
print_line=$OPTARG
;;
q)
quiet=true
;;
*) ;;
esac
done
shift $((OPTIND - 1))
}
function inet_aton() {
echo $1 | awk -F'.' '{printf ("%d\n", $1 * 16777216 + $2 * 65536 + $3 * 256 + $4)}'
}
function inet_ntoa() {
echo $(($1 / 16777216 % 256)).$(($1 / 65536 % 256)).$(($1 / 256 % 256)).$(($1 % 256))
}
# Get 1 random effective IP per class C from CIDR
function cidr_to_iplist() {
base=$(inet_aton ${1%/*})
mask=${1#*/}
if [ "$mask" -lt 24 ]; then
# /0 - /23
count=$((2 ** (32 - mask) - 2))
end=$((base + count))
inet_ntoa $((base + 1 + RANDOM % 255)) # base address plus a random number between [1, 255] in 1st Class C
base=$((base + 256))
while ((base + 254 < end)); do
inet_ntoa $((base + RANDOM % 256)) # base address plus a random number between [0, 255] in Class C between 1st and last
base=$((base + 256))
done
inet_ntoa $((base + RANDOM % 255)) # base address plus a random number between [0, 254] in last Class C
elif [ "$mask" -lt 31 ]; then
# /24 - /30
count=$((2 ** (32 - mask) - 2))
inet_ntoa $((base + 1 + RANDOM % count)) # base address plus a random number between [1, count-1]
elif [ "$mask" -lt 32 ]; then
# /31
inet_ntoa $((base + RANDOM % 2)) # base address plus a random number between [0, 1]
else
# /32
inet_ntoa $base # base address is the only IP we can fetch
fi
}
function get_iplist() {
#cidr_to_iplist "1.0.0.0/24"
#cidr_to_iplist "1.1.1.0/24"
if [ -n "$CIDR_LIST" ]; then
for cidr in $CIDR_LIST; do
cidr_to_iplist "$cidr"
done
elif [ -n "$CIDR_URL" ]; then
local domain=$(echo $CIDR_URL | awk -F/ '{print $3}')
local ip=$(dig +short $domain @1.1.1.1 | head -1)
local scheme=$(echo $CIDR_URL | awk -F/ '{print $1}')
local port=$([[ "$scheme" =~ "https" ]] && echo 443 || echo 80)
curl -sSL --retry 3 --resolve $domain:$port:$ip $CIDR_URL | while read -r line; do
cidr_to_iplist "$line"
done
fi
}
function check_file_exists() {
for file in "$@"; do
[ -f "$file" ] || exit 1
done
}
function process_fping() {
check_file_exists $1
fping_list=$1
[ -n "$5" ] && {
cat $1 | shuf | head -n $5 >ips_shuf
fping_list=ips_shuf
}
fping -f $fping_list -q -i ${2:-10} -c ${3:-1} -p ${4:-5000} |& awk '{split($5,a,"/"); split($8,b,"/"); if($8) print $1,a[2],b[2]}' | sort -k2,2rn -k3,3n
}
function speedtest() {
check_file_exists $1
rm -rf speedtest_tmpdir || :
mkdir speedtest_tmpdir
local url=${2:-"https://speed.cloudflare.com/__down?bytes=125000000"}
local domain=$(echo $url | awk -F/ '{print $3}')
local scheme=$(echo $url | awk -F/ '{print $1}')
local port=$([[ "$scheme" =~ "https" ]] && echo 443 || echo 80)
head -n ${4:-100} $1 | xargs -L 1 -P ${3:-10} sh -c "curl --resolve $domain:$port:\$0 --url $url -o speedtest_tmpdir/\$0 --connect-timeout 2 -m ${5:-10} || :"
find -path './speedtest_tmpdir/*' -type f -printf '%f %s\n' | sort -k2,2rn
}
function print_result() {
check_file_exists $1 $2
local format='%s\r\033[18Cpackets received: %s\033[3Cping: %s\033[3Cspeed: %.2f MB/s\n'
local values='$1,a[$1],b[$1],$2/1048576/'$st_time
if [ -n "$3" ]; then
awk 'NR==FNR{a[$1]=$2;b[$1]=$3;next}{printf "'"$format"'",'$values'}' $1 $2 | head -n $3
else
awk 'NR==FNR{a[$1]=$2;b[$1]=$3;next}{printf "'"$format"'",'$values'}' $1 $2
fi
}
function main() {
parse_args "$@"
local workdir=$(mktemp -d) && trap "rm -rf $workdir; exit 130" SIGINT
cd $workdir
$quiet || echo "Working directory: $workdir"
local ip_result=${workdir:-.}/ips
local fping_result=${workdir:-.}/ips_fping
local speedtest_result=${workdir:-.}/ips_speedtest
get_iplist >$ip_result
$quiet || echo "$(wc -l <$ip_result) ips have been generate"
process_fping $ip_result $fping_interval $fping_count $fping_period $fping_shuf >$fping_result
$quiet || echo "$(wc -l <$fping_result) ips have been ping"
speedtest $fping_result $st_url $st_parallel $st_line $st_time >$speedtest_result
$quiet || echo "$(wc -l <$speedtest_result) ips have been speedtest"
print_result $fping_result $speedtest_result $print_line
#rm -rf ${workdir:-"$(pwd)"}
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment