4 Commits

Author SHA1 Message Date
xiu2
4b4426c195 新增 IPv6 支持 2020-11-30 16:41:01 +08:00
xiu2
ff3a6d1d56 update 2020-11-25 12:31:57 +08:00
xiu2
a78c6e6270 update 2020-11-15 18:30:39 +08:00
xiu2
6b52fbf5ea update 2020-11-13 14:42:06 +08:00
5 changed files with 139 additions and 31 deletions

View File

@@ -21,17 +21,83 @@ func loadFirstIPOfRangeFromFile(ipFile string) []net.IPAddr {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
for IPRange.Contains(firstIP) { if ipv6Mode { // IPv6
randipEndWith() // 随机 IP 的最后一段 var tempIP uint8
firstIP[15] = ipEndWith for IPRange.Contains(firstIP) {
firstIPCopy := make([]byte, len(firstIP)) //fmt.Println(firstIP)
copy(firstIPCopy, firstIP) //fmt.Println(firstIP[0], firstIP[1], firstIP[2], firstIP[3], firstIP[4], firstIP[5], firstIP[6], firstIP[7], firstIP[8], firstIP[9], firstIP[10], firstIP[11], firstIP[12], firstIP[13], firstIP[14], firstIP[15])
firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy}) firstIP[15] = randipEndWith() // 随机 IP 的最后一段
firstIP[14]++ firstIP[14] = randipEndWith() // 随机 IP 的最后一段
if firstIP[14] == 0 { firstIPCopy := make([]byte, len(firstIP))
firstIP[13]++ copy(firstIPCopy, firstIP)
if firstIP[13] == 0 { firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy})
firstIP[12]++ tempIP = firstIP[13]
firstIP[13] += randipEndWith()
if firstIP[13] < tempIP {
tempIP = firstIP[12]
firstIP[12] += randipEndWith()
if firstIP[12] < tempIP {
tempIP = firstIP[11]
firstIP[11] += randipEndWith()
if firstIP[11] < tempIP {
tempIP = firstIP[10]
firstIP[10] += randipEndWith()
if firstIP[10] < tempIP {
tempIP = firstIP[9]
firstIP[9] += randipEndWith()
if firstIP[9] < tempIP {
tempIP = firstIP[8]
firstIP[8] += randipEndWith()
if firstIP[8] < tempIP {
tempIP = firstIP[7]
firstIP[7] += randipEndWith()
if firstIP[7] < tempIP {
tempIP = firstIP[6]
firstIP[6] += randipEndWith()
if firstIP[6] < tempIP {
tempIP = firstIP[5]
firstIP[5] += randipEndWith()
if firstIP[5] < tempIP {
tempIP = firstIP[4]
firstIP[4] += randipEndWith()
if firstIP[4] < tempIP {
tempIP = firstIP[3]
firstIP[3] += randipEndWith()
if firstIP[3] < tempIP {
tempIP = firstIP[2]
firstIP[2] += randipEndWith()
if firstIP[2] < tempIP {
tempIP = firstIP[1]
firstIP[1] += randipEndWith()
if firstIP[1] < tempIP {
tempIP = firstIP[0]
firstIP[0] += randipEndWith()
}
}
}
}
}
}
}
}
}
}
}
}
}
}
} else { //IPv4
for IPRange.Contains(firstIP) {
firstIP[15] = randipEndWith() // 随机 IP 的最后一段 0.0.0.X
firstIPCopy := make([]byte, len(firstIP))
copy(firstIPCopy, firstIP)
firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy})
firstIP[14]++ // 0.0.(X+1).X
if firstIP[14] == 0 {
firstIP[13]++ // 0.(X+1).X.X
if firstIP[13] == 0 {
firstIP[12]++ // (X+1).X.X.X
}
} }
} }
} }

View File

@@ -9,8 +9,10 @@
国外很多网站都在使用 Cloudflare CDN但分配给中国访客的 IP 并不友好。 国外很多网站都在使用 Cloudflare CDN但分配给中国访客的 IP 并不友好。
虽然 Cloudflare 公开了所有 [IP 段](https://www.cloudflare.com/ips/) ,但想要在这么多 IP 中找到适合自己的,怕是要累死,所以就有了这个软件。 虽然 Cloudflare 公开了所有 [IP 段](https://www.cloudflare.com/ips/) ,但想要在这么多 IP 中找到适合自己的,怕是要累死,所以就有了这个软件。
该软件可以**测试 Cloudflare CDN 所有 IP 的延迟和速度,获得最快 IP**!觉得好用请**点个⭐~** 该软件可以**测试 Cloudflare CDN 所有 IP 的延迟和速度,获得最快 IP**!觉得好用请**点个⭐鼓励一下下~**
你可以将 IP 添加到 `Hosts` 文件中,以提高访问使用 Cloudflare CDN 的网站速度! 将 IP 添加到 `Hosts` 文件或 DNS 程序中,以提高访问使用 Cloudflare CDN 的网站速度!
> 本项目也**适用于其他 CDN**,但是需要自行寻找 **CDN IP 段及下载测速地址**(否则只能延迟测速)!
**** ****
## 快速使用 ## 快速使用
@@ -43,12 +45,11 @@ IP 地址 已发送 已接收 丢包率 平均延迟 下载速度
完整结果保存在当前目录下的 `result.csv` 文件中,用**记事本/表格软件**打开,排序为**延迟由低到高**,分别是: 完整结果保存在当前目录下的 `result.csv` 文件中,用**记事本/表格软件**打开,排序为**延迟由低到高**,分别是:
> 大家可以按照自己的需求,对完整测速数据**进一步筛选处理**
``` ```
IP 地址, 已发送, 已接收, 丢包率, 平均延迟, 下载速度 (MB/s) IP 地址, 已发送, 已接收, 丢包率, 平均延迟, 下载速度 (MB/s)
104.27.199.141, 4, 4, 0.00, 139.52, 11.71 104.27.199.141, 4, 4, 0.00, 139.52, 11.71
``` ```
> 大家可以按照自己的需求,对完整测速数据**进一步筛选处理**
选择一个平均延迟与下载速度都不错的 IP 放到 `Hosts` 文件中(指向使用 Cloudflare CDN 的网站域名)。 选择一个平均延迟与下载速度都不错的 IP 放到 `Hosts` 文件中(指向使用 Cloudflare CDN 的网站域名)。
@@ -89,6 +90,8 @@ https://github.com/XIU2/CloudflareSpeedTest
输出结果文件;如含有空格请加上引号;为空格时不输出结果文件(-o " ");允许其他后缀;(默认 result.csv) 输出结果文件;如含有空格请加上引号;为空格时不输出结果文件(-o " ");允许其他后缀;(默认 result.csv)
-dd -dd
禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用) 禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用)
-ipv6
IPv6 测速模式;请确保 IP 数据文件内只包含 IPv6 IP段软件不支持同时测速 IPv4+IPv6(默认 IPv4)
-v -v
打印程序版本 打印程序版本
-h -h
@@ -106,16 +109,19 @@ https://github.com/XIU2/CloudflareSpeedTest
# 注意:各参数均有默认值,只有不使用默认值时,才需要手动指定参数的值(按需选择),参数不分前后顺序。 # 注意:各参数均有默认值,只有不使用默认值时,才需要手动指定参数的值(按需选择),参数不分前后顺序。
# 提示: Linux 系统只需要把下面命令中的 CloudflareST.exe 改为 ./CloudflareST 即可。 # 提示: Linux 系统只需要把下面命令中的 CloudflareST.exe 改为 ./CloudflareST 即可。
# 指定 IP数据文件不显示结果直接退出-p 值为 0 # 指定 IPv4 数据文件,不显示结果直接退出(-p 值为 0
CloudflareST.exe -p 0 -f ip.txt -dd CloudflareST.exe -p 0 -f ip.txt -dd
# 指定 IP数据文件,不输出结果到文件,直接显示结果-p 值为 10 条 # 指定 IPv6 数据文件( ipv6.txt ),不显示结果直接退出-p 值为 0
CloudflareST.exe -p 0 -f ipv6.txt -dd -ipv6
# 指定 IPv4 数据文件,不输出结果到文件,直接显示结果(-p 值为 10 条)
CloudflareST.exe -p 10 -f ip.txt -o " " -dd CloudflareST.exe -p 10 -f ip.txt -o " " -dd
# 指定 IP数据文件 及 输出结果到文件(相对路径,即当前目录下,如果包含空格请加上引号) # 指定 IPv4 数据文件 及 输出结果到文件(相对路径,即当前目录下,如果包含空格请加上引号)
CloudflareST.exe -f ip.txt -o result.csv -dd CloudflareST.exe -f ip.txt -o result.csv -dd
# 指定 IP数据文件 及 输出结果到文件(绝对路径,即 C:\abc\ 目录下,如果包含空格请加上引号) # 指定 IPv4 数据文件 及 输出结果到文件(绝对路径,即 C:\abc\ 目录下,如果包含空格请加上引号)
CloudflareST.exe -f C:\abc\ip.txt -o C:\abc\result.csv -dd CloudflareST.exe -f C:\abc\ip.txt -o C:\abc\result.csv -dd
# 指定下载测速地址(要求:可以直接下载、文件大小超过 200MB、用的是 Cloudflare CDN如果包含空格请加上引号 # 指定下载测速地址(要求:可以直接下载、文件大小超过 200MB、用的是 Cloudflare CDN如果包含空格请加上引号
@@ -140,6 +146,7 @@ CloudflareST.exe -tl 200 -sl 5 -dn 10
``` cmd ``` cmd
# Windows 快捷方式示例(右键快捷方式 - 目标) # Windows 快捷方式示例(右键快捷方式 - 目标)
## 如果有引号就放在引号外面,记得引号和 - 之间有空格。 ## 如果有引号就放在引号外面,记得引号和 - 之间有空格。
### 如果要不输出结果文件,那么请加上 -o " ",引号里的是空格。
"D:\Program Files\CloudflareST\CloudflareST.exe" -n 500 -t 4 -dn 20 -dt 5 "D:\Program Files\CloudflareST\CloudflareST.exe" -n 500 -t 4 -dn 20 -dt 5
``` ```

26
main.go
View File

@@ -15,6 +15,7 @@ import (
var version string var version string
var disableDownload bool var disableDownload bool
var ipv6Mode bool
var tcpPort int var tcpPort int
var ipFile string var ipFile string
var outputFile string var outputFile string
@@ -54,7 +55,9 @@ https://github.com/XIU2/CloudflareSpeedTest
-o result.csv -o result.csv
输出结果文件;如含有空格请加上引号;为空格时不输出结果文件(-o " ");允许其他后缀;(默认 result.csv) 输出结果文件;如含有空格请加上引号;为空格时不输出结果文件(-o " ");允许其他后缀;(默认 result.csv)
-dd -dd
禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用) 禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用下载测速)
-ipv6
IPv6 测速模式;请确保 IP 数据文件内只包含 IPv6 IP段软件不支持同时测速 IPv4+IPv6(默认 IPv4)
-v -v
打印程序版本 打印程序版本
-h -h
@@ -70,6 +73,7 @@ https://github.com/XIU2/CloudflareSpeedTest
flag.IntVar(&speedLimit, "sl", 0, "下载速度下限") flag.IntVar(&speedLimit, "sl", 0, "下载速度下限")
flag.IntVar(&printResultNum, "p", 20, "显示结果数量") flag.IntVar(&printResultNum, "p", 20, "显示结果数量")
flag.BoolVar(&disableDownload, "dd", false, "禁用下载测速") flag.BoolVar(&disableDownload, "dd", false, "禁用下载测速")
flag.BoolVar(&ipv6Mode, "ipv6", false, "禁用下载测速")
flag.StringVar(&ipFile, "f", "ip.txt", "IP 数据文件") flag.StringVar(&ipFile, "f", "ip.txt", "IP 数据文件")
flag.StringVar(&outputFile, "o", "result.csv", "输出结果文件") flag.StringVar(&outputFile, "o", "result.csv", "输出结果文件")
flag.BoolVar(&printVersion, "v", false, "打印程序版本") flag.BoolVar(&printVersion, "v", false, "打印程序版本")
@@ -129,7 +133,11 @@ func main() {
var data_2 = make([]CloudflareIPData, 0) var data_2 = make([]CloudflareIPData, 0)
fmt.Println("# XIU2/CloudflareSpeedTest " + version + "\n") fmt.Println("# XIU2/CloudflareSpeedTest " + version + "\n")
fmt.Println("开始延迟测速模式TCP端口" + strconv.Itoa(tcpPort) + "") if ipv6Mode {
fmt.Println("开始延迟测速模式TCP IPv6端口" + strconv.Itoa(tcpPort) + "")
} else {
fmt.Println("开始延迟测速模式TCP IPv4端口" + strconv.Itoa(tcpPort) + "")
}
control := make(chan bool, pingRoutine) control := make(chan bool, pingRoutine)
for _, ip := range ips { for _, ip := range ips {
wg.Add(1) wg.Add(1)
@@ -148,7 +156,6 @@ func main() {
if len(data) < downloadTestCount { // 如果IP数组长度(IP数量) 小于 下载测速次数则次数改为IP数 if len(data) < downloadTestCount { // 如果IP数组长度(IP数量) 小于 下载测速次数则次数改为IP数
//fmt.Println("\n[信息] IP 数量小于下载测速次数(" + strconv.Itoa(downloadTestCount) + " < " + strconv.Itoa(len(data)) + "下载测速次数改为IP数。\n") //fmt.Println("\n[信息] IP 数量小于下载测速次数(" + strconv.Itoa(downloadTestCount) + " < " + strconv.Itoa(len(data)) + "下载测速次数改为IP数。\n")
downloadTestCount = len(data) downloadTestCount = len(data)
} }
var downloadTestCount_2 int // 临时的下载测速次数 var downloadTestCount_2 int // 临时的下载测速次数
if timeLimit == 9999 && speedLimit == 0 { if timeLimit == 9999 && speedLimit == 0 {
@@ -201,9 +208,16 @@ func printResult(data []CloudflareIPData) {
//fmt.Println("\n[信息] IP 数量小于显示结果数量(" + strconv.Itoa(printResultNum) + " < " + strconv.Itoa(len(dateString)) + "显示结果数量改为IP数量。\n") //fmt.Println("\n[信息] IP 数量小于显示结果数量(" + strconv.Itoa(printResultNum) + " < " + strconv.Itoa(len(dateString)) + "显示结果数量改为IP数量。\n")
printResultNum = len(dateString) printResultNum = len(dateString)
} }
fmt.Printf("%-16s%-5s%-5s%-5s%-6s%-11s\n", "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)") if ipv6Mode { // IPv6 太长了,所以需要调整一下间隔
for i := 0; i < printResultNum; i++ { fmt.Printf("%-40s%-5s%-5s%-5s%-6s%-11s\n", "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)")
fmt.Printf("%-18s%-8s%-8s%-8s%-10s%-15s\n", ipPadding(dateString[i][0]), dateString[i][1], dateString[i][2], dateString[i][3], dateString[i][4], dateString[i][5]) for i := 0; i < printResultNum; i++ {
fmt.Printf("%-42s%-8s%-8s%-8s%-10s%-15s\n", ipPadding(dateString[i][0]), dateString[i][1], dateString[i][2], dateString[i][3], dateString[i][4], dateString[i][5])
}
} else {
fmt.Printf("%-16s%-5s%-5s%-5s%-6s%-11s\n", "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)")
for i := 0; i < printResultNum; i++ {
fmt.Printf("%-18s%-8s%-8s%-8s%-10s%-15s\n", ipPadding(dateString[i][0]), dateString[i][1], dateString[i][2], dateString[i][3], dateString[i][4], dateString[i][5])
}
} }
if sysType == "windows" { // 如果是 Windows 系统,则需要按下 回车键 或 Ctrl+C 退出 if sysType == "windows" { // 如果是 Windows 系统,则需要按下 回车键 或 Ctrl+C 退出

View File

@@ -15,7 +15,13 @@ import (
//bool connectionSucceed float32 time //bool connectionSucceed float32 time
func tcping(ip net.IPAddr, tcpPort int) (bool, float32) { func tcping(ip net.IPAddr, tcpPort int) (bool, float32) {
startTime := time.Now() startTime := time.Now()
conn, err := net.DialTimeout("tcp", ip.String()+":"+strconv.Itoa(tcpPort), tcpConnectTimeout) var fullAddress string
if ipv6Mode { // IPv6 需要加上 []
fullAddress = "[" + ip.String() + "]:" + strconv.Itoa(tcpPort)
} else {
fullAddress = ip.String() + ":" + strconv.Itoa(tcpPort)
}
conn, err := net.DialTimeout("tcp", fullAddress, tcpConnectTimeout)
if err != nil { if err != nil {
return false, 0 return false, 0
} else { } else {
@@ -107,8 +113,14 @@ func DownloadSpeedHandler(ip net.IPAddr) (bool, float32) {
Jar: nil, Jar: nil,
Timeout: 0, Timeout: 0,
} }
var fullAddress string
if ipv6Mode { // IPv6 需要加上 []
fullAddress = "[" + ip.String() + "]:443"
} else {
fullAddress = ip.String() + ":443"
}
client.Transport = &http.Transport{ client.Transport = &http.Transport{
DialContext: GetDialContextByAddr(ip.String() + ":443"), DialContext: GetDialContextByAddr(fullAddress),
} }
response, err := client.Get(url) response, err := client.Get(url)

17
util.go
View File

@@ -64,8 +64,6 @@ func convertToString(data []CloudflareIPData) [][]string {
var pingTime int var pingTime int
var pingRoutine int var pingRoutine int
var ipEndWith uint8 = 0
type progressEvent int type progressEvent int
const ( const (
@@ -93,8 +91,19 @@ func initRandSeed() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
} }
func randipEndWith() { func randipEndWith() uint8 {
ipEndWith = uint8(rand.Intn(254) + 1) return uint8(rand.Intn(254) + 1)
}
func GetRandomString() string {
str := "0123456789abcdef"
bytes := []byte(str)
result := []byte{}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < 4; i++ {
result = append(result, bytes[r.Intn(len(bytes))])
}
return string(result)
} }
func ipPadding(ip string) string { func ipPadding(ip string) string {