10 Commits

Author SHA1 Message Date
xiu2
c8ef175207 优化 IP 段子网掩码解析 2020-12-11 03:12:28 +08:00
xiu2
31dc7aed3c update 2020-12-10 10:13:26 +08:00
xiu2
e3a6f80a14 update 2020-12-10 10:05:05 +08:00
xiu2
38e1d26341 update 2020-12-10 10:02:35 +08:00
xiu2
166d9abe7c 修复 上个版本更新导致的 IPv6 测速报错的问题。 2020-12-09 16:42:50 +08:00
xiu2
f9c310bfb4 update 2020-12-06 08:20:57 +08:00
xiu2
0d54b65f33 新增 测速全部 IP、检查版本更新 2020-12-05 16:03:21 +08:00
xiu2
9f2e5b5b5e add ipv6.txt 2020-11-30 18:10:41 +08:00
XIU2
7b4f6944be 优化 打印帮助时末尾换行(避免在命令行和下一行命令混在一起)
Merge pull request #13 from zhangsean/master
2020-11-30 17:10:07 +08:00
zhangsean
00b569d649 打印帮助换行 2020-11-30 17:05:07 +08:00
6 changed files with 947 additions and 829 deletions

View File

@@ -5,8 +5,24 @@ import (
"log" "log"
"net" "net"
"os" "os"
"strconv"
"strings"
) )
func getCidrHostNum(maskLen int) int {
cidrIpNum := int(0)
if maskLen < 32 {
var i int = int(32 - maskLen - 1)
for ; i >= 1; i-- {
cidrIpNum += 1 << i
}
cidrIpNum += 2
} else {
cidrIpNum = 1
}
return cidrIpNum
}
func loadFirstIPOfRangeFromFile(ipFile string) []net.IPAddr { func loadFirstIPOfRangeFromFile(ipFile string) []net.IPAddr {
file, err := os.Open(ipFile) file, err := os.Open(ipFile)
if err != nil { if err != nil {
@@ -18,60 +34,69 @@ func loadFirstIPOfRangeFromFile(ipFile string) []net.IPAddr {
for scanner.Scan() { for scanner.Scan() {
IPString := scanner.Text() IPString := scanner.Text()
firstIP, IPRange, err := net.ParseCIDR(IPString) firstIP, IPRange, err := net.ParseCIDR(IPString)
//fmt.Println(firstIP)
//fmt.Println(IPRange)
Mask, _ := strconv.Atoi(strings.Split(scanner.Text(), "/")[1])
MaxIPNum := getCidrHostNum(Mask)
if MaxIPNum > 255 {
MaxIPNum = 255
}
//fmt.Println(MaxIPNum)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
if ipv6Mode { // IPv6 if ipv6Mode { // IPv6
var tempIP uint8 var tempIP uint8
MaxIPNum = 255
for IPRange.Contains(firstIP) { for IPRange.Contains(firstIP) {
//fmt.Println(firstIP) //fmt.Println(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]) //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])
firstIP[15] = randipEndWith() // 随机 IP 的最后一段 firstIP[15] = randipEndWith(MaxIPNum) // 随机 IP 的最后一段
firstIP[14] = randipEndWith() // 随机 IP 的最后一段 firstIP[14] = randipEndWith(MaxIPNum) // 随机 IP 的最后一段
firstIPCopy := make([]byte, len(firstIP)) firstIPCopy := make([]byte, len(firstIP))
copy(firstIPCopy, firstIP) copy(firstIPCopy, firstIP)
firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy}) firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy})
tempIP = firstIP[13] tempIP = firstIP[13]
firstIP[13] += randipEndWith() firstIP[13] += randipEndWith(MaxIPNum)
if firstIP[13] < tempIP { if firstIP[13] < tempIP {
tempIP = firstIP[12] tempIP = firstIP[12]
firstIP[12] += randipEndWith() firstIP[12] += randipEndWith(MaxIPNum)
if firstIP[12] < tempIP { if firstIP[12] < tempIP {
tempIP = firstIP[11] tempIP = firstIP[11]
firstIP[11] += randipEndWith() firstIP[11] += randipEndWith(MaxIPNum)
if firstIP[11] < tempIP { if firstIP[11] < tempIP {
tempIP = firstIP[10] tempIP = firstIP[10]
firstIP[10] += randipEndWith() firstIP[10] += randipEndWith(MaxIPNum)
if firstIP[10] < tempIP { if firstIP[10] < tempIP {
tempIP = firstIP[9] tempIP = firstIP[9]
firstIP[9] += randipEndWith() firstIP[9] += randipEndWith(MaxIPNum)
if firstIP[9] < tempIP { if firstIP[9] < tempIP {
tempIP = firstIP[8] tempIP = firstIP[8]
firstIP[8] += randipEndWith() firstIP[8] += randipEndWith(MaxIPNum)
if firstIP[8] < tempIP { if firstIP[8] < tempIP {
tempIP = firstIP[7] tempIP = firstIP[7]
firstIP[7] += randipEndWith() firstIP[7] += randipEndWith(MaxIPNum)
if firstIP[7] < tempIP { if firstIP[7] < tempIP {
tempIP = firstIP[6] tempIP = firstIP[6]
firstIP[6] += randipEndWith() firstIP[6] += randipEndWith(MaxIPNum)
if firstIP[6] < tempIP { if firstIP[6] < tempIP {
tempIP = firstIP[5] tempIP = firstIP[5]
firstIP[5] += randipEndWith() firstIP[5] += randipEndWith(MaxIPNum)
if firstIP[5] < tempIP { if firstIP[5] < tempIP {
tempIP = firstIP[4] tempIP = firstIP[4]
firstIP[4] += randipEndWith() firstIP[4] += randipEndWith(MaxIPNum)
if firstIP[4] < tempIP { if firstIP[4] < tempIP {
tempIP = firstIP[3] tempIP = firstIP[3]
firstIP[3] += randipEndWith() firstIP[3] += randipEndWith(MaxIPNum)
if firstIP[3] < tempIP { if firstIP[3] < tempIP {
tempIP = firstIP[2] tempIP = firstIP[2]
firstIP[2] += randipEndWith() firstIP[2] += randipEndWith(MaxIPNum)
if firstIP[2] < tempIP { if firstIP[2] < tempIP {
tempIP = firstIP[1] tempIP = firstIP[1]
firstIP[1] += randipEndWith() firstIP[1] += randipEndWith(MaxIPNum)
if firstIP[1] < tempIP { if firstIP[1] < tempIP {
tempIP = firstIP[0] tempIP = firstIP[0]
firstIP[0] += randipEndWith() firstIP[0] += randipEndWith(MaxIPNum)
} }
} }
} }
@@ -88,10 +113,31 @@ func loadFirstIPOfRangeFromFile(ipFile string) []net.IPAddr {
} }
} else { //IPv4 } else { //IPv4
for IPRange.Contains(firstIP) { for IPRange.Contains(firstIP) {
firstIP[15] = randipEndWith() // 随机 IP 的最后一段 0.0.0.X //fmt.Println(firstIP)
firstIPCopy := make([]byte, len(firstIP)) //fmt.Println(firstIP[15])
copy(firstIPCopy, firstIP) if allip {
firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy}) if firstIP[15] == 0 { // 当 IP 最后一段为 0 时会按顺序生成 IP
for i := 0; i < MaxIPNum; i++ {
firstIP[15] = uint8(i) // 按顺序生成 IP 的最后一段 0.0.0.X
//fmt.Println(firstIP)
firstIPCopy := make([]byte, len(firstIP))
copy(firstIPCopy, firstIP)
firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy})
}
} else { // 当 IP 最后一段不为 0 时,则保留 IP 最后一段
firstIPCopy := make([]byte, len(firstIP))
copy(firstIPCopy, firstIP)
firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy})
}
} else {
if firstIP[15] == 0 {
firstIP[15] = randipEndWith(MaxIPNum) // 随机 IP 的最后一段 0.0.0.X
}
firstIPCopy := make([]byte, len(firstIP))
copy(firstIPCopy, firstIP)
firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy})
}
firstIP[15] = 0
firstIP[14]++ // 0.0.(X+1).X firstIP[14]++ // 0.0.(X+1).X
if firstIP[14] == 0 { if firstIP[14] == 0 {
firstIP[13]++ // 0.(X+1).X.X firstIP[13]++ // 0.(X+1).X.X

View File

@@ -9,10 +9,9 @@
国外很多网站都在使用 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 (IPv4+IPv6)**!觉得好用请**点个⭐鼓励一下下~**
将 IP 添加到 `Hosts` 文件或 DNS 程序中,以提高访问使用 Cloudflare CDN 的网站速度!
> 本项目也**适用于其他 CDN**,但是需要自行寻找 **CDN IP 段及下载测速地址**(否则只能延迟测速) > 本项目也**适用于其他 CDN**,但是需要自行寻找 **CDN IP 段及下载测速地址**(否则只能延迟测速)
**** ****
## 快速使用 ## 快速使用
@@ -22,11 +21,11 @@
1. 下载编译好的可执行文件 [蓝奏云](https://xiu.lanzoux.com/b0742hkxe) / [Github](https://github.com/XIU2/CloudflareSpeedTest/releases) 并解压。 1. 下载编译好的可执行文件 [蓝奏云](https://xiu.lanzoux.com/b0742hkxe) / [Github](https://github.com/XIU2/CloudflareSpeedTest/releases) 并解压。
2. 双击运行 `CloudflareST.exe`文件Windows等待测速... 2. 双击运行 `CloudflareST.exe`文件Windows等待测速...
> **注意Linux 系统**请先赋予执行权限 `chmod +x CloudflareST` ,然后再执行 `./CloudflareST` > **提示Linux 系统**请先赋予执行权限 `chmod +x CloudflareST` ,然后再执行 `./CloudflareST`
### 结果示例 ### 结果示例
测速完毕后,会直接显示**最快的 20 个 IP**,示例: 测速完毕后,默认会显示**最快的 20 个 IP**,示例:
``` ```
IP 地址 已发送 已接收 丢包率 平均延迟 下载速度 (MB/s) IP 地址 已发送 已接收 丢包率 平均延迟 下载速度 (MB/s)
@@ -43,20 +42,20 @@ IP 地址 已发送 已接收 丢包率 平均延迟 下载速度
... ...
``` ```
选择一个平均延迟与下载速度都不错的 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.198.101, 4, 4, 0.00, 126.52, 12.71
``` ```
> 大家可以按照自己的需求,对完整测速数据**进一步筛选处理** > 大家可以按照自己的需求,对完整结果**进一步筛选处理**,或者去看一看进阶使用(如设定测速条件)
选择一个平均延迟与下载速度都不错的 IP 放到 `Hosts` 文件中(指向使用 Cloudflare CDN 的网站域名)。
**** ****
## 进阶使用 ## 进阶使用
直接双击运行使用的是默认参数,如果想要测试速度更快、测试结果更全面,可以自定义参数。 直接运行使用的是默认参数,如果想要测速结果更全面、更符合自己的要求,可以自定义参数。
``` cmd ``` cmd
C:\>CloudflareST.exe -h C:\>CloudflareST.exe -h
@@ -92,13 +91,15 @@ https://github.com/XIU2/CloudflareSpeedTest
禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用) 禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用)
-ipv6 -ipv6
IPv6 测速模式;请确保 IP 数据文件内只包含 IPv6 IP段软件不支持同时测速 IPv4+IPv6(默认 IPv4) IPv6 测速模式;请确保 IP 数据文件内只包含 IPv6 IP段软件不支持同时测速 IPv4+IPv6(默认 IPv4)
-allip
测速全部 IP如果带上该参数将会对每个 IP (仅 IPv4) 进行测速;(默认 每个 IP 段随机测速一个 IP)
-v -v
打印程序版本 打印程序版本+检查版本更新
-h -h
打印帮助说明 打印帮助说明
``` ```
> 如果**下载速度都是 0.00**,那说明默认的**下载测速地址**用的人太多到上限了,**请去这个 [Issues](https://github.com/XIU2/CloudflareSpeedTest/issues/6) 获得解决方法!** > 如果**下载速度都是 0.00**,那可能默认的**下载测速地址**用的人太多到上限了,**请去这个 [Issues](https://github.com/XIU2/CloudflareSpeedTest/issues/6) 获得解决方法!**
### 使用示例 ### 使用示例
@@ -154,8 +155,6 @@ CloudflareST.exe -tl 200 -sl 5 -dn 10
## 感谢项目 ## 感谢项目
* https://github.com/Spedoske/CloudflareScanner * https://github.com/Spedoske/CloudflareScanner
意外发现了这个项目,看了之后发现正好解决了我的问题,但是我更喜欢用户命令行方式运行,这样会更方便、有更多使用姿势,于是我临时学了下 Golang 并 Fork 按照我自己的需求修改了一下(包括但不限于命令行方式交互、直接输出结果等),如果有什么问题可以告诉我,虽然我不一定会~
**** ****
## 许可证 ## 许可证
The GPL-3.0 License. The GPL-3.0 License.

42
ipv6.txt Normal file
View File

@@ -0,0 +1,42 @@
2606:4700:10::6814:0/112
2606:4700:10::ac43:0/112
2606:4700:3000::/48
2606:4700:3001::/48
2606:4700:3002::/48
2606:4700:3003::/48
2606:4700:3004::/48
2606:4700:3005::/48
2606:4700:3006::/48
2606:4700:3007::/48
2606:4700:3008::/48
2606:4700:3009::/48
2606:4700:3010::/48
2606:4700:3011::/48
2606:4700:3012::/48
2606:4700:3013::/48
2606:4700:3014::/48
2606:4700:3015::/48
2606:4700:3016::/48
2606:4700:3017::/48
2606:4700:3018::/48
2606:4700:3019::/48
2606:4700:3020::/48
2606:4700:3021::/48
2606:4700:3022::/48
2606:4700:3023::/48
2606:4700:3024::/48
2606:4700:3025::/48
2606:4700:3026::/48
2606:4700:3027::/48
2606:4700:3028::/48
2606:4700:3029::/48
2606:4700:3030::/48
2606:4700:3031::/48
2606:4700:3032::/48
2606:4700:3033::/48
2606:4700:3034::/48
2606:4700:3035::/48
2606:4700:3036::/48
2606:4700:3037::/48
2606:4700:3038::/48
2606:4700:3039::/48

54
main.go
View File

@@ -3,6 +3,8 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"io/ioutil"
"net/http"
"os" "os"
"runtime" "runtime"
"sort" "sort"
@@ -13,15 +15,9 @@ import (
"github.com/cheggaaa/pb/v3" "github.com/cheggaaa/pb/v3"
) )
var version string var version, ipFile, outputFile, versionNew string
var disableDownload bool var disableDownload, ipv6Mode, allip bool
var ipv6Mode bool var tcpPort, printResultNum, timeLimit, speedLimit int
var tcpPort int
var ipFile string
var outputFile string
var printResultNum int
var timeLimit int
var speedLimit int
func init() { func init() {
var downloadSecond int64 var downloadSecond int64
@@ -55,13 +51,16 @@ https://github.com/XIU2/CloudflareSpeedTest
-o result.csv -o result.csv
输出结果文件;如含有空格请加上引号;为空格时不输出结果文件(-o " ");允许其他后缀;(默认 result.csv) 输出结果文件;如含有空格请加上引号;为空格时不输出结果文件(-o " ");允许其他后缀;(默认 result.csv)
-dd -dd
禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用下载测速) 禁用下载测速;如果带上该参数将会禁用下载测速;(默认 启用下载测速)
-ipv6 -ipv6
IPv6 测速模式;请确保 IP 数据文件内只包含 IPv6 IP段软件不支持同时测速 IPv4+IPv6(默认 IPv4) IPv6 测速模式;请确保 IP 数据文件内只包含 IPv6 IP段软件不支持同时测速 IPv4+IPv6(默认 IPv4)
-allip
测速全部 IP如果带上该参数将会对每个 IP (仅 IPv4) 进行测速;(默认 每个 IP 段随机测速一个 IP)
-v -v
打印程序版本 打印程序版本+检查版本更新
-h -h
打印帮助说明` 打印帮助说明
`
flag.IntVar(&pingRoutine, "n", 500, "测速线程数量") flag.IntVar(&pingRoutine, "n", 500, "测速线程数量")
flag.IntVar(&pingTime, "t", 4, "延迟测速次数") flag.IntVar(&pingTime, "t", 4, "延迟测速次数")
@@ -74,6 +73,7 @@ https://github.com/XIU2/CloudflareSpeedTest
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.BoolVar(&ipv6Mode, "ipv6", false, "禁用下载测速")
flag.BoolVar(&allip, "allip", false, "测速全部 IP")
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, "打印程序版本")
@@ -84,6 +84,13 @@ https://github.com/XIU2/CloudflareSpeedTest
flag.Parse() flag.Parse()
if printVersion { if printVersion {
println(version) println(version)
fmt.Println("检查版本更新中...")
checkUpdate()
if versionNew != "" {
fmt.Println("发现新版本 [" + versionNew + "]!请前往 [https://github.com/XIU2/CloudflareSpeedTest] 更新!")
} else {
fmt.Println("当前为最新版本 [" + version + "]")
}
os.Exit(0) os.Exit(0)
} }
if pingRoutine <= 0 { if pingRoutine <= 0 {
@@ -122,6 +129,7 @@ https://github.com/XIU2/CloudflareSpeedTest
} }
func main() { func main() {
go checkUpdate() // 检查版本更新
initRandSeed() // 置随机数种子 initRandSeed() // 置随机数种子
failTime = pingTime // 设置接收次数 failTime = pingTime // 设置接收次数
ips := loadFirstIPOfRangeFromFile(ipFile) // 读入IP ips := loadFirstIPOfRangeFromFile(ipFile) // 读入IP
@@ -220,6 +228,10 @@ func printResult(data []CloudflareIPData) {
} }
} }
if versionNew != "" {
fmt.Println("\n发现新版本 [" + versionNew + "]!请前往 [https://github.com/XIU2/CloudflareSpeedTest] 更新!")
}
if sysType == "windows" { // 如果是 Windows 系统,则需要按下 回车键 或 Ctrl+C 退出 if sysType == "windows" { // 如果是 Windows 系统,则需要按下 回车键 或 Ctrl+C 退出
if outputFile != "" { if outputFile != "" {
fmt.Printf("\n完整测速结果已写入 %v 文件,请使用记事本/表格软件查看。\n按下 回车键 或 Ctrl+C 退出。", outputFile) fmt.Printf("\n完整测速结果已写入 %v 文件,请使用记事本/表格软件查看。\n按下 回车键 或 Ctrl+C 退出。", outputFile)
@@ -240,3 +252,21 @@ func printResult(data []CloudflareIPData) {
fmt.Println("\n完整测速结果已写入 " + outputFile + " 文件,请使用记事本/表格软件查看。") fmt.Println("\n完整测速结果已写入 " + outputFile + " 文件,请使用记事本/表格软件查看。")
} }
} }
// 检查更新
func checkUpdate() {
timeout := time.Duration(10 * time.Second)
client := http.Client{Timeout: timeout}
res, err := client.Get("https://api.xiuer.pw/ver/cloudflarespeedtest.txt")
if err == nil {
// 读取资源数据 body: []byte
body, err := ioutil.ReadAll(res.Body)
// 关闭资源流
res.Body.Close()
if err == nil {
if string(body) != version {
versionNew = string(body)
}
}
}
}

View File

@@ -16,6 +16,7 @@ import (
func tcping(ip net.IPAddr, tcpPort int) (bool, float32) { func tcping(ip net.IPAddr, tcpPort int) (bool, float32) {
startTime := time.Now() startTime := time.Now()
var fullAddress string var fullAddress string
//fmt.Println(ip.String())
if ipv6Mode { // IPv6 需要加上 [] if ipv6Mode { // IPv6 需要加上 []
fullAddress = "[" + ip.String() + "]:" + strconv.Itoa(tcpPort) fullAddress = "[" + ip.String() + "]:" + strconv.Itoa(tcpPort)
} else { } else {

View File

@@ -91,8 +91,8 @@ func initRandSeed() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
} }
func randipEndWith() uint8 { func randipEndWith(num int) uint8 {
return uint8(rand.Intn(254) + 1) return uint8(rand.Intn(num))
} }
func GetRandomString() string { func GetRandomString() string {