diff --git a/CloudFlare.py b/CloudFlare.py
new file mode 100644
index 0000000..1ad11cb
--- /dev/null
+++ b/CloudFlare.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+# encoding:utf-8
+
+import json
+import math
+import os
+import platform
+import re
+import shutil
+import subprocess
+import sys
+import time
+from multiprocessing import Manager, Pool
+
+import requests
+
+original_host = []
+
+
+def main():
+ cf_ips = get_cf_ips()
+ ping_test_dict = {}
+ ping_test_pool = {}
+ print('测试 ICMP 丢包率\n')
+ re_cmp = re.compile('(\d+\.\d+\.\d+\.\d+)[^\(]*\(\d+ avg, (\d+)\% loss\)', re.I)
+ r = check_icmp(cf_ips)
+ re_findall = re_cmp.findall(r)
+ for i in re_findall:
+ ping_test_dict[i[0]] = int(i[1])
+ no_loss_ping = filter(lambda x: ping_test_dict[x] == 0, ping_test_dict)
+ no_loss_ping = list(no_loss_ping)
+
+ if len(no_loss_ping) > 0:
+ print('测试完成,无丢包的 IP 总共有 {} 个,分别是:\n{}\n'.format(len(no_loss_ping), '\n'.join(no_loss_ping)))
+ check_speed(no_loss_ping)
+ else:
+ print('\n测试完成,选择 10 个丢包最低的 IP 进行速度测试\n')
+ ping_test_sorted = sorted(ping_test_dict.items(), key=lambda x: x[1])
+ ping_test_cf_selected = [i[0] for i in ping_test_sorted[0:10]]
+ print('选择的 10 个丢包最低的 IP 分别是:\n{}\n'.format('\n'.join(ping_test_cf_selected)))
+ check_speed(ping_test_cf_selected)
+
+
+def get_cf_ips():
+ print('获取 CloudFlare 节点 IP 列表\n')
+ ret = requests.get('https://service.freecdn.workers.dev', timeout=30)
+ ret = ret.text.split('\n')
+ return ret[5:]
+
+
+def check_icmp(ip):
+ re_cmp = re.compile('\(\d+ avg, (\d+)\% loss\)', re.I)
+ fping_list = []
+ page_size = 600
+ pages = int(math.ceil(len(ip) * 1.0 / page_size))
+ page_list = range(1, pages + 1)
+ for i in page_list:
+ list_start = (i - 1) * page_size
+ list_end = i * page_size
+ ip_file = os.path.abspath(os.path.join(os.getcwd(), 'ip-{}.txt'.format(i)))
+ with open(ip_file, 'w') as f:
+ f.write('\n'.join(ip[list_start:list_end]))
+ cmd = 'fping -f {} -c 30 -i 1 -s 2>&1'.format(ip_file)
+ p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False)
+ fping_list.append(p)
+ ping = ''
+ while True:
+ fping_end = []
+ for p in fping_list:
+ if p.poll() is None:
+ r = p.stdout.readline()
+ r = r.decode('utf-8')
+ if re_cmp.findall(r):
+ ping += r
+ print(r.replace('\n', ''))
+ else:
+ fping_end.append(True)
+ if len(fping_end) == len(fping_list) and list(set(fping_end)) == [True]:
+ break
+ time.sleep(0.01)
+ for i in page_list:
+ ip_file = os.path.abspath(os.path.join(os.getcwd(), 'ip-{}.txt'.format(i)))
+ if os.path.exists(ip_file):
+ os.remove(ip_file)
+ return ping
+
+
+def check_speed(ping_test_cf_selected):
+ print('开始对选中的 IP 进行速度测试...\n')
+ if os.path.exists(os.path.abspath(os.path.join(os.getcwd(), 'temp'))):
+ shutil.rmtree(os.path.abspath(os.path.join(os.getcwd(), 'temp')))
+ os.makedirs(os.path.abspath(os.path.join(os.getcwd(), 'temp')))
+
+ for i in ping_test_cf_selected:
+ print('开始对 {} 进行速度测试'.format(i))
+ cmd = 'curl --resolve speed.cloudflare.com:443:{0} https://speed.cloudflare.com/__down?bytes=1000000000 -o temp/{0} -s --connect-timeout 2 --max-time 10'.format(
+ i)
+ p = subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ while p.poll() is None:
+ time.sleep(0.1)
+
+ print('\n测试完成,选择5个速度最快的 IP 进行源地址速度测试...\n')
+ speed_test_ips_list = []
+ file_size_dict = {}
+
+ for root, dirs, files in os.walk('temp'):
+ for i in files:
+ file_size_dict[i] = os.path.getsize(os.path.join('temp', i))
+
+ file_size_dict_sorted = sorted(
+ file_size_dict.items(), key=lambda x: x[1], reverse=True)
+ for i in range(5):
+ speed_test_ips_list.append(file_size_dict_sorted[i][0])
+ print('选择的 5 个速度最快的 IP 分别是:\n{}'.format('\n'.join(speed_test_ips_list)))
+ for i in original_host:
+ check_speed_original(speed_test_ips_list, i)
+
+
+def check_speed_original(speed_test_ips_list, original_address):
+ print('\n通过选中的 IP 开始对源地址 {} 进行速度测试...\n'.format(original_address))
+ cf_speed_test_ips_dict = {}
+ for i in speed_test_ips_list:
+ print('开始对 {:15} 进行源地址速度测试'.format(i))
+ if platform.system() == 'Windows':
+ cmd = 'curl --resolve {1}:443:{0} https://{1}/cf_speed_test -o nul --connect-timeout 5 --max-time 15'.format(i, original_address)
+ else:
+ cmd = 'curl --resolve {1}:443:{0} https://{1}/cf_speed_test -o /dev/null --connect-timeout 5 --max-time 15'.format(i, original_address)
+ p = subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ ret = ''
+ while p.poll() is None:
+ r = p.stdout.readline().decode('utf-8')
+ if r:
+ ret += r
+ time.sleep(0.01)
+ ret = ret.split('\n')
+ ret = ret[2]
+ ret = ret.split('\r')
+ ret = ret[-2]
+ while True:
+ if ' ' in ret:
+ ret = ret.replace(' ', ' ')
+ else:
+ break
+ ret = ret.split(' ')
+ ret = ret[7]
+ if 'M' in ret:
+ ret = '{}k'.format(float(ret.replace('M', '')) * 1024)
+ if 'k' in ret:
+ ret = float(ret.replace('k', '')) * 1024
+ ret = float(ret)
+ cf_speed_test_ips_dict[i] = ret
+ print('\n源地址速度测试完成\n')
+ print('对 https://{}/cf_speed_test 进行的下载速度测试结果如下:\n'.format(original_address))
+ cf_speed_test_ips_list = sorted(cf_speed_test_ips_dict.items(), key=lambda x: x[1], reverse=True)
+ for i in cf_speed_test_ips_list:
+ ret = 'IP {:15} Speed {:10}k'.format(i[0], round(i[1] * 1.0 / 1024, 2))
+ print(ret)
+
+ if os.path.exists(os.path.abspath(os.path.join(os.getcwd(), 'temp'))):
+ shutil.rmtree(os.path.abspath(os.path.join(os.getcwd(), 'temp')))
+
+
+if __name__ == '__main__':
+ original_host = input('请输入测试地址,如果有多个地址请以半角空格分割:')
+ original_host = original_host.split(' ')
+ if len(original_host) > 0:
+ start_time = time.time()
+ main()
+ print('累计测试时间: {} 秒'.format(int(time.time() - start_time)))
+ else:
+ print('输入错误!请重新运行此脚本!')
\ No newline at end of file
diff --git a/README.md b/README.md
index 61194cb..7dae20a 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,70 @@
-# better-cloudflare-ip
-shell脚本,适合中国大陆用户查找适合自己当前网络环境的优选cloudflare anycast IP
+## 感谢
+
+本项目Fork自 badafans/better-cloudflare-ip
+
+感谢 badafans 提供 Cloudflare Anycast 节点汇总
+
+## 使用申明
+本项目侧重于研究任播技术中丢包率与网速的相互关系,仅供学习使用
+
+### 禁止使用范围准则如下
+
+a) 相关机构提示网页有威胁的,有非法信息提示的网站。
+
+b)医院类型网站(流产,皮肤病,性病等医院),未获得卫生部资质的网站。
+
+c)网站主体内容含有色情(视频交友,一夜情交友)、违法(办假证,贩卖仿真枪)、封建迷信、游戏私服、游戏外挂、网赚、两性、美女贴图和动漫贴图(尺度过大)、赌博(含贩卖赌博工具。)、博彩等内容。
+
+d)网站存在恶意流氓广告(存在非法内容视频链接,非法网页内容链接)。
+
+e)网站存在任何破坏或试图破坏网络安全的行为,以病毒、木马、恶意代码、钓鱼等方式,试图对网站、网络相关软硬件进行恶意扫描、非法侵入系统、非法获取数据等内容。
+
+f)网站内容存在版权风险的网站(视频,小说,音乐等网站)。
+
+g)网站含有药品销售、保健品销售,但未取得资质的,或严重夸大药效事实。
+
+h)网站主要业务为向非法网站提供支付、交易平台、担保,代理外国金融理财(炒股,炒现货,炒黄金)等服务的网站。
+
+i)网站中大量存在影响社会和谐稳定的内容的网站(涉嫌攻击国家,攻击领导人,攻击人民,言论煽动性质网站)。
+
+j)网站内容含有国家相关法律法规不允许的其他内容。
+
+k)网站内容含有VPN,网络代理等内容。
+
+l) 通过技术手段或非技术手段干扰Cloudflare所有产品正常运营的网站。
+
+m)网站内容为发布虚假不实消息行为,或侵害了他人的合法权益行为的网站。
+
+n) 获取网站内容需要通过登录等方式,无法直接查看造成内容无法审核的网站。
+
+o) 提供影视、软件和应用等下载服务的网站。
+
+## 介绍
+
+* 用 Python3 重写了测试脚本;
+
+* 使用多线程优化 Ping 测试,大大缩短测试时间;
+
+* 不再设置测速阀值,而是择优选择数个 IP 进行速度测试;
+
+* 新增通过 anycast IP 进行原始服务器测速,获取真实下载速度;
+
+## 说明
+
++ 继续使用 badafans/better-cloudflare-ip 项目中的 curl 和 fping 工具
+
++ 需要安装 Python3 (Windows / Linux 通用)
+
++ 通过 pip3 安装 requests
+
++ 在原始服务器的网站根目录下生成测试文件
+
+ + dd if=/dev/zero of=cf_speed_test bs=1M count=100
+
+ + 要能以 https://(cf中分配或者解析的域名)/cf_speed_test 访问并下载
+
+ + 测试下载速度时将进行 15 秒的下载操作
+
++ 在脚本中配置 original_host 参数
+
++ 运行脚本进行测速
diff --git a/better-cloudflare-ip-win32.zip b/better-cloudflare-ip-win32.zip
new file mode 100644
index 0000000..8f05924
Binary files /dev/null and b/better-cloudflare-ip-win32.zip differ
diff --git a/cf.sh b/cf.sh
new file mode 100644
index 0000000..20b1306
--- /dev/null
+++ b/cf.sh
@@ -0,0 +1,313 @@
+#!/bin/bash
+# random cloudflare anycast ip
+declare -i bandwidth
+declare -i speed
+read -p "请设置期望到 CloudFlare 服务器的带宽大小(单位 Mbps):" bandwidth
+speed=bandwidth*128*1024
+starttime=`date +'%Y-%m-%d %H:%M:%S'`
+while true
+do
+ while true
+ do
+ declare -i n
+ declare -i per
+ declare -i count
+ rm -rf icmp temp log.txt data.txt anycast.txt
+ mkdir icmp
+ curl --ipv4 https://service.freecdn.workers.dev -# -o data.txt
+ publicip=$(cat data.txt | grep publicip: | cut -f 2- -d':')
+ domain=$(cat data.txt | grep domain: | cut -f 2- -d':')
+ file=$(cat data.txt | grep file: | cut -f 2- -d':')
+ url=$(cat data.txt | grep url: | cut -f 2- -d':')
+ version=$(cat data.txt | grep version: | cut -f 2- -d':')
+ if [ "$version" != "20201108" ]
+ then
+ echo 发现新版本: $version
+ echo 更新地址: $url
+ echo 更新后才可以使用
+ exit
+ fi
+ n=0
+ count=$(($RANDOM%5))
+ for i in `cat data.txt | sed '1,5d'`
+ do
+ if [ $n -eq $count ]
+ then
+ echo $i>>anycast.txt
+ count+=4
+ else
+ n+=1
+ fi
+ done
+ rm -rf data.txt
+ n=0
+ m=$(cat anycast.txt | wc -l)
+ count=m/30+1
+ for i in `cat anycast.txt`
+ do
+ ping -c $count -i 0.2 -n -q $i > icmp/$n.log&
+ n=$[$n+1]
+ per=$n*100/$m
+ while true
+ do
+ p=$(ps -ef | grep ping | grep -v "grep" | wc -l)
+ if [ $p -ge 200 ]
+ then
+ echo 正在测试 ICMP 丢包率:进程数 $p,已完成 $per %
+ sleep 0.5
+ else
+ echo 正在测试 ICMP 丢包率:进程数 $p,已完成 $per %
+ break
+ fi
+ done
+ done
+ rm -rf anycast.txt
+ while true
+ do
+ p=$(ps -ef | grep ping | grep -v "grep" | wc -l)
+ if [ $p -ne 0 ]
+ then
+ echo 等待 ICMP 进程结束:剩余进程数 $p
+ sleep 1
+ else
+ echo ICMP 丢包率测试完成
+ break
+ fi
+ done
+ cat icmp/*.log | sed -n '3~5p;4~5p' | sed -n '{N;s/\n/\t/p}' | cut -f 1 -d'%' | awk '{print $2,$NF}' | sort -k 2 -n | awk '{print $1}' | sed '31,$d' > ip.txt
+ rm -rf icmp
+ echo 选取30个丢包率最少的IP地址下载测速
+ mkdir temp
+ for i in `cat ip.txt`
+ do
+ echo $i 启动测速
+ curl --resolve $domain:443:$i https://$domain/$file -o temp/$i -s --connect-timeout 2 --max-time 10&
+ done
+ echo 等待测速进程结束,筛选出三个优选的IP
+ sleep 15
+ echo 测速完成
+ ls -S temp > ip.txt
+ rm -rf temp
+ n=$(wc -l ip.txt | awk '{print $1}')
+ if [ $n -ge 3 ]; then
+ first=$(sed -n '1p' ip.txt)
+ second=$(sed -n '2p' ip.txt)
+ third=$(sed -n '3p' ip.txt)
+ rm -rf ip.txt
+ echo 优选的IP地址为 $first - $second - $third
+ echo 第一次测试 $first
+ curl --resolve $domain:443:$first https://$domain/$file -o /dev/null --connect-timeout 5 --max-time 10 > log.txt 2>&1
+ cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep -v 'k\|M' >> speed.txt
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep k | sed 's/k//g'`
+ do
+ declare -i k
+ k=$i
+ k=k*1024
+ echo $k >> speed.txt
+ done
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep M | sed 's/M//g'`
+ do
+ i=$(echo | awk '{print '$i'*10 }')
+ declare -i M
+ M=$i
+ M=M*1024*1024/10
+ echo $M >> speed.txt
+ done
+ declare -i max
+ max=0
+ for i in `cat speed.txt`
+ do
+ max=$i
+ if [ $i -ge $max ]; then
+ max=$i
+ fi
+ done
+ rm -rf log.txt speed.txt
+ if [ $max -ge $speed ]; then
+ anycast=$first
+ break
+ fi
+ max=$[$max/1024]
+ echo 峰值速度 $max kB/s
+ echo 第二次测试 $first
+ curl --resolve $domain:443:$first https://$domain/$file -o /dev/null --connect-timeout 5 --max-time 10 > log.txt 2>&1
+ cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep -v 'k\|M' >> speed.txt
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep k | sed 's/k//g'`
+ do
+ declare -i k
+ k=$i
+ k=k*1024
+ echo $k >> speed.txt
+ done
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep M | sed 's/M//g'`
+ do
+ i=$(echo | awk '{print '$i'*10 }')
+ declare -i M
+ M=$i
+ M=M*1024*1024/10
+ echo $M >> speed.txt
+ done
+ declare -i max
+ max=0
+ for i in `cat speed.txt`
+ do
+ max=$i
+ if [ $i -ge $max ]; then
+ max=$i
+ fi
+ done
+ rm -rf log.txt speed.txt
+ if [ $max -ge $speed ]; then
+ anycast=$first
+ break
+ fi
+ max=$[$max/1024]
+ echo 峰值速度 $max kB/s
+ echo 第一次测试 $second
+ curl --resolve $domain:443:$second https://$domain/$file -o /dev/null --connect-timeout 5 --max-time 10 > log.txt 2>&1
+ cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep -v 'k\|M' >> speed.txt
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep k | sed 's/k//g'`
+ do
+ declare -i k
+ k=$i
+ k=k*1024
+ echo $k >> speed.txt
+ done
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep M | sed 's/M//g'`
+ do
+ i=$(echo | awk '{print '$i'*10 }')
+ declare -i M
+ M=$i
+ M=M*1024*1024/10
+ echo $M >> speed.txt
+ done
+ declare -i max
+ max=0
+ for i in `cat speed.txt`
+ do
+ max=$i
+ if [ $i -ge $max ]; then
+ max=$i
+ fi
+ done
+ rm -rf log.txt speed.txt
+ if [ $max -ge $speed ]; then
+ anycast=$second
+ break
+ fi
+ max=$[$max/1024]
+ echo 峰值速度 $max kB/s
+ echo 第二次测试 $second
+ curl --resolve $domain:443:$second https://$domain/$file -o /dev/null --connect-timeout 5 --max-time 10 > log.txt 2>&1
+ cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep -v 'k\|M' >> speed.txt
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep k | sed 's/k//g'`
+ do
+ declare -i k
+ k=$i
+ k=k*1024
+ echo $k >> speed.txt
+ done
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep M | sed 's/M//g'`
+ do
+ i=$(echo | awk '{print '$i'*10 }')
+ declare -i M
+ M=$i
+ M=M*1024*1024/10
+ echo $M >> speed.txt
+ done
+ declare -i max
+ max=0
+ for i in `cat speed.txt`
+ do
+ max=$i
+ if [ $i -ge $max ]; then
+ max=$i
+ fi
+ done
+ rm -rf log.txt speed.txt
+ if [ $max -ge $speed ]; then
+ anycast=$second
+ break
+ fi
+ max=$[$max/1024]
+ echo 峰值速度 $max kB/s
+ echo 第一次测试 $third
+ curl --resolve $domain:443:$third https://$domain/$file -o /dev/null --connect-timeout 5 --max-time 10 > log.txt 2>&1
+ cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep -v 'k\|M' >> speed.txt
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep k | sed 's/k//g'`
+ do
+ declare -i k
+ k=$i
+ k=k*1024
+ echo $k >> speed.txt
+ done
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep M | sed 's/M//g'`
+ do
+ i=$(echo | awk '{print '$i'*10 }')
+ declare -i M
+ M=$i
+ M=M*1024*1024/10
+ echo $M >> speed.txt
+ done
+ declare -i max
+ max=0
+ for i in `cat speed.txt`
+ do
+ max=$i
+ if [ $i -ge $max ]; then
+ max=$i
+ fi
+ done
+ rm -rf log.txt speed.txt
+ if [ $max -ge $speed ]; then
+ anycast=$third
+ break
+ fi
+ max=$[$max/1024]
+ echo 峰值速度 $max kB/s
+ echo 第二次测试 $third
+ curl --resolve $domain:443:$third https://$domain/$file -o /dev/null --connect-timeout 5 --max-time 10 > log.txt 2>&1
+ cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep -v 'k\|M' >> speed.txt
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep k | sed 's/k//g'`
+ do
+ declare -i k
+ k=$i
+ k=k*1024
+ echo $k >> speed.txt
+ done
+ for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep M | sed 's/M//g'`
+ do
+ i=$(echo | awk '{print '$i'*10 }')
+ declare -i M
+ M=$i
+ M=M*1024*1024/10
+ echo $M >> speed.txt
+ done
+ declare -i max
+ max=0
+ for i in `cat speed.txt`
+ do
+ max=$i
+ if [ $i -ge $max ]; then
+ max=$i
+ fi
+ done
+ rm -rf log.txt speed.txt
+ if [ $max -ge $speed ]; then
+ anycast=$third
+ break
+ fi
+ max=$[$max/1024]
+ echo 峰值速度 $max kB/s
+ fi
+ done
+ break
+done
+ max=$[$max/1024]
+ endtime=`date +'%Y-%m-%d %H:%M:%S'`
+ start_seconds=$(date --date="$starttime" +%s)
+ end_seconds=$(date --date="$endtime" +%s)
+ clear
+ echo 优选IP $anycast 满足 $bandwidth Mbps带宽需求
+ echo 峰值速度 $max kB/s
+ echo 出口IP $publicip 总计用时 $((end_seconds-start_seconds)) 秒
\ No newline at end of file
diff --git a/curl.zip b/curl.zip
new file mode 100644
index 0000000..f0e8702
Binary files /dev/null and b/curl.zip differ
diff --git a/fping-4.2.tar.gz b/fping-4.2.tar.gz
new file mode 100644
index 0000000..d0fc6fe
Binary files /dev/null and b/fping-4.2.tar.gz differ