75 Commits

Author SHA1 Message Date
xiu2
2de42f8d30 README.md 2026-03-02 23:43:02 +08:00
XIU2
bcbf7f0e2a Merge pull request #632 from jysz/patch-1
修复 Linux 安装步骤中的错误镜像链接文件名
2026-03-02 23:37:44 +08:00
jysz
f735c0f5b3 修复可能错误的链接
前面wget github下载写的是amd64,解压步骤写的也是amd64.但是镜像写的变成arm 64了,无脑复制运行会因为文件名不匹配导致错误
2026-03-02 23:25:26 +08:00
xiu2
7fbe1d1b56 README.md 2026-02-26 14:58:22 +08:00
xiu2
6eaacd6b2c 修复 CFST新版本下获取不到第一行 IP 的问题 2025-12-15 13:29:48 +08:00
xiu2
b955387787 README.md 2025-11-23 18:05:12 +08:00
xiu2
e57e9d3897 README.md 2025-10-22 17:23:34 +08:00
xiu2
801dd53774 README.md 2025-09-13 10:01:23 +08:00
xiu2
e03a371e19 README.me 2025-07-25 09:50:26 +08:00
xiu2
346b27f011 README.md 2025-07-22 19:51:54 +08:00
xiu2
4f9ca03008 修复 部分情况下无法显示彩色文字的问题 2025-07-22 19:51:05 +08:00
xiu2
d76a8bc749 更新 依赖版本及最低编译版本 2025-07-22 15:14:21 +08:00
xiu2
3cd9a35994 完善 注释说明 2025-07-21 22:42:17 +08:00
xiu2
574e419ee1 补充 调试模式下,更多下载测速失败报错原因 2025-07-21 22:18:39 +08:00
xiu2
d66b2aa1f0 README.md 2025-07-21 21:53:36 +08:00
xiu2
a392fddd3a 修复 没有设置下载速度下限条件时输出测速结果数量异常的问题 2025-07-21 21:13:20 +08:00
xiu2
2bb2f509d9 README.md 2025-07-21 15:00:01 +08:00
xiu2
3cf898701f README.md 2025-07-14 20:16:24 +08:00
xiu2
74267eb2ac README.md 2025-07-09 20:50:03 +08:00
xiu2
bf1bd561da README.md 2025-07-09 20:48:11 +08:00
xiu2
b5e741ea3e README.md 2025-07-09 20:42:44 +08:00
xiu2
6099b48007 README.md 2025-07-09 20:39:42 +08:00
xiu2
397cfd25d3 修复 调试模式下因重定向后的地址出错导致下载测速失败时输出的最终地址不准确的问题 2025-07-09 20:26:01 +08:00
xiu2
db40924a32 README.md 2025-07-09 11:53:41 +08:00
xiu2
1bacd92f6a 调整 帮助文本开头的一句话描述内容 2025-07-08 23:56:39 +08:00
xiu2
2fe4e41a9e 调整 CloudflareST 为简写的 cfst 2025-07-08 23:36:45 +08:00
xiu2
c14627725c 新增 地区码支持 Fastly、Gcore、CDN77、Bunny 等 CDN 2025-07-08 23:00:26 +08:00
xiu2
6c599ed1a6 新增 调试模式支持在 HTTPing 测速过程中输出更多日志 2025-07-08 23:00:18 +08:00
xiu2
e236a24a0c 完善 调试模式 2025-07-08 20:29:14 +08:00
xiu2
fc5cd11867 README.md 2025-07-03 20:04:17 +08:00
xiu2
e9699196ef 考虑 对其他 CDN 的地区码支持(先加上相关注释方便后续完善) 2025-07-03 20:04:12 +08:00
xiu2
66912dd657 新增 支持显示地区码(机场三字码,仅限 Cloudflare、AWS CloudFront,HTTPing 和 下载测速(无论是哪个测速模式)过程中都会自动获取);
新增 调试模式运行参数(-debug 方便排查下载测速过程中遇到的问题);
新增 彩色输出内容;
调整 当没找到符合速度条件的 IP 时,默认不再直接忽略条件输出所有 IP 测速结果了,而是只有在调试模式下才会输出;
2025-06-29 00:30:05 +08:00
XIU2
04da9f5659 Merge pull request #538 from ipcjs/patch-1
chore: 添加通过scoop安装的命令
2025-05-11 14:49:04 +08:00
xiu2
013c27c059 README.md 2025-03-25 13:17:30 +08:00
xiu2
c7f8170485 README.md 2025-01-22 23:58:37 +08:00
XIU2
d6818fa60c Merge pull request #570 from Sving1024/master
修复 cfst_dnsmasq.sh IPv6 的问题
2025-01-22 23:56:45 +08:00
Sving1024
b15fe2c899 fix IPv6 2025-01-22 23:45:04 +08:00
xiu2
551f753323 README.md 2025-01-08 09:14:32 +08:00
xiu2
8acc095cd9 README.md 2025-01-04 16:40:21 +08:00
xiu2
ee31cff5c3 README.md 2024-12-28 20:22:38 +08:00
XIU2
b85ae8edec Merge pull request #565 from Sving1024/master
add scripts to auto update config file for dnsmasq
2024-12-28 20:18:29 +08:00
Sving1024
25fc2921e2 reset version 2024-12-28 19:30:36 +08:00
Sving1024
5e39f2612f add scripts to auto update config file for dnsmasq 2024-12-28 19:02:31 +08:00
xiu2
dbceab3418 README.md 2024-12-17 09:10:30 +08:00
xiu2
6c9d336d01 README.md 2024-12-17 09:09:40 +08:00
xiu2
a438fc6c93 README.md 2024-12-10 23:06:17 +08:00
xiu2
1d9d742bca README.md 2024-12-06 21:49:26 +08:00
xiu2
209c7100ff README.md 2024-12-06 21:44:27 +08:00
ipcjs
c74168a10d Update README.md 2024-11-15 01:57:34 +08:00
xiu2
66c0923bf7 README.md 2024-10-09 10:10:22 +08:00
xiu2
bbe762c46f 新增 支持 API 令牌方式 2024-10-06 14:13:18 +08:00
xiu2
887a55ce77 README.md 2024-09-12 16:32:51 +08:00
ipcjs
570a710446 Update README.md 2024-08-22 19:31:31 +08:00
ipcjs
0033f96e5d Update README.md 2024-08-22 19:28:12 +08:00
ipcjs
b3036eb1ef Update README.md 2024-08-22 17:33:00 +08:00
xiu2
84cbd2995c README.md 2024-08-09 20:49:35 +08:00
xiu2
1995d088ec README.md 2024-08-06 20:55:22 +08:00
xiu2
13f0c322a8 README.md 2024-08-06 20:54:00 +08:00
Taylor Lottner
a5cf1fdc05 新增 cfst_dnspod.sh 脚本用于 dnspod 自动更新域名解析最优 IP (#533) 2024-08-06 20:13:15 +08:00
xiu2
8a6670b67a README.md 2024-07-27 23:46:38 +08:00
xiu2
e815a60867 README.md 2024-07-25 22:57:46 +08:00
xiu2
bf832c5a4e 更新 import "io/ioutil" -> "io" 2024-07-22 11:29:36 +08:00
xiu2
f2e87d38d7 README.md 2024-07-09 19:45:58 +08:00
xiu2
63234aeb98 Update issue templates 2024-07-09 19:45:51 +08:00
xiu2
23b4f260e7 Update issue templates 2024-06-20 07:14:31 +08:00
XIU2
dbb5864235 Update README.md 2024-06-17 17:59:44 +08:00
xiu2
d96281af1f README.md 2024-02-13 22:47:06 +08:00
xiu2
6d12e7bac9 README.md 2024-02-12 13:00:38 +08:00
xiu2
9d9d71fa04 README.md 2024-02-12 12:03:00 +08:00
xiu2
176271d5bb README.md 2024-01-20 10:26:48 +08:00
xiu2
216d0f5f6b README.md 2023-12-15 21:35:45 +08:00
xiu2
7534e34ae2 README.md 2023-12-15 21:33:21 +08:00
xiu2
b3010e21fd README.md 2023-11-30 16:30:05 +08:00
xiu2
aa52d607bc README.md 2023-11-30 16:24:13 +08:00
xiu2
ca5564c56e README.md 2023-11-26 12:35:30 +08:00
21 changed files with 939 additions and 344 deletions

View File

@@ -7,7 +7,8 @@ body:
value: |
发之前,请先搜下有没有类似的 [**Issues**](https://github.com/XIU2/CloudflareSpeedTest/issues)、[**Discussions**](https://github.com/XIU2/CloudflareSpeedTest/discussions) 问题(包括[**已关闭**](https://github.com/XIU2/CloudflareSpeedTest/issues?q=is%3Aissue+is%3Aclosed)的),请勿重复发起!
注意!如果你反馈的问题和 CloudflareST **软件本身功能无关**(如关于 Cloudflare CDN 的网络问题),请**前往讨论区** (💬 [**Discussions**](https://github.com/XIU2/CloudflareSpeedTest/discussions)) 发帖交流!(不合适的 Issues 会被转过去
> [!NOTE]
> 注意!如果你反馈的问题和 CFST **软件本身功能无关**(如关于 Cloudflare CDN 的网络问题),请**前往讨论区** (💬 [**Discussions**](https://github.com/XIU2/CloudflareSpeedTest/discussions)) 发帖交流!(不合适的 Issues 会被转过去
****
- type: textarea
id: description

View File

@@ -7,9 +7,11 @@ body:
value: |
发之前,请先搜下有没有类似的 [**Issues**](https://github.com/XIU2/CloudflareSpeedTest/issues)、[**Discussions**](https://github.com/XIU2/CloudflareSpeedTest/discussions) 问题(包括[**已关闭**](https://github.com/XIU2/CloudflareSpeedTest/issues?q=is%3Aissue+is%3Aclosed)的),请勿重复发起!
注意!如果你提的功能建议和 CloudflareST **软件本身功能无关**,请**前往讨论区** (💬 [**Discussions**](https://github.com/XIU2/CloudflareSpeedTest/discussions)) 发帖交流!
> [!NOTE]
> 注意!如果你提的功能建议和 CFST **软件本身功能无关**,请**前往讨论区** (💬 [**Discussions**](https://github.com/XIU2/CloudflareSpeedTest/discussions)) 发帖交流!
> 另外,不接受**个性化**的功能请求(即 **很少人** 或 **只有你自己** 才会用到的功能)
> [!TIP]
> 另外,不接受**个性化**的小众功能请求(即 **很少人** 或 **只有你自己** 才会用到的功能)
****
- type: textarea
id: description

View File

@@ -2,4 +2,4 @@ blank_issues_enabled: false
contact_links:
- name: 前往讨论区 (💬 Discussions)
url: https://github.com/XIU2/CloudflareSpeedTest/discussions
about: Issues 仅用于反馈问题、功能建议,其他话题请到 💬 Discussions 发帖讨论(不合适的 Issues 会被转过去
about: Issues 仅用于对 CFST 本身的反馈问题、功能建议,其他话题请到 💬 Discussions 发帖讨论(不合适的 Issues 会被转过去

461
README.md
View File

@@ -15,17 +15,34 @@
> _[**UserScript** - 🐵 Github 高速下载、知乎增强、自动无缝翻页、护眼模式 等十几个**油猴脚本**~](https://github.com/XIU2/UserScript) <img src="https://img.shields.io/github/stars/XIU2/UserScript.svg?style=flat-square&label=Star&color=4285dd&logo=github" height="16px" />_
> _[**SNIProxy** - 🧷 自用的简单 SNI Proxy支持全平台、全系统、前置代理、配置简单等~](https://github.com/XIU2/SNIProxy) <img src="https://img.shields.io/github/stars/XIU2/SNIProxy.svg?style=flat-square&label=Star&color=4285dd&logo=github" height="16px" />_
> 本项目也支持对**其他 CDN / 网站 IP** 延迟测速(如:[CloudFront](https://github.com/XIU2/CloudflareSpeedTest/discussions/304)、[Gcore](https://github.com/XIU2/CloudflareSpeedTest/discussions/303) CDN下载测速需自行寻找地址
当然了,本项目也支持对 **`其他 CDN / 多个解析 IP 的网站`** 延迟测速,但相对应的下载测速地址需自行寻找
> 对于**代理套 Cloudflare CDN** 的用户,须知这应为**备用方案**,而不应该是**唯一方案**,请勿过度依赖 [#382](https://github.com/XIU2/CloudflareSpeedTest/discussions/382) [#383](https://github.com/XIU2/CloudflareSpeedTest/discussions/383)
> [!IMPORTANT]
> Cloudflare CDN 已**明文禁止代理**方式使用,对于**代理套 CDN** 的自行承担风险,请勿过度依赖 [#382](https://github.com/XIU2/CloudflareSpeedTest/discussions/382) [#383](https://github.com/XIU2/CloudflareSpeedTest/discussions/383)
****
## \# 快速使用
### 下载运行
1. 下载编译好的可执行文件( [Github Releases](https://github.com/XIU2/CloudflareSpeedTest/releases) / [蓝奏云](https://pan.lanzouj.com/b0742hkxe) )并解压。
2. 双击运行 `CloudflareST.exe` 文件Windows 系统),等待测速完成...
1. 下载编译好的可执行文件( [Github Releases](https://github.com/XIU2/CloudflareSpeedTest/releases) / [蓝奏云](https://xiu.lanzoub.com/b0742hkxe) )并解压。
2. 双击运行 `cfst.exe` 文件Windows 系统),等待测速完成...
<details>
<summary><code><strong>「 点击查看 Windows 系统下其他安装方式」</strong></code></summary>
****
如果你有 scoop(Windows 下的命令行安装程序),则可以这样安装:
```sh
# 添加最多人使用的中文软件包仓库dorado
scoop bucket add dorado https://github.com/chawyehsu/dorado
# 安装cloudflare-speedtest
scoop install dorado/cloudflare-speedtest
```
</details>
<details>
<summary><code><strong>「 点击查看 Linux 系统下的使用示例 」</strong></code></summary>
@@ -36,62 +53,65 @@
``` yaml
# 如果是第一次使用,则建议创建新文件夹(后续更新时,跳过该步骤)
mkdir CloudflareST
mkdir cfst
# 进入文件夹(后续更新,只需要从这里重复下面的下载、解压命令即可)
cd CloudflareST
cd cfst
# 下载 CloudflareST 压缩包(自行根据需求替换 URL 中 [版本号] 和 [文件名]
wget -N https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.2.4/CloudflareST_linux_amd64.tar.gz
# 如果你是在国内服务器上下载,那么请使用下面这几个镜像加速:
# wget -N https://download.fgit.ml/XIU2/CloudflareSpeedTest/releases/download/v2.2.4/CloudflareST_linux_amd64.tar.gz
# wget -N https://download.fgit.gq/XIU2/CloudflareSpeedTest/releases/download/v2.2.4/CloudflareST_linux_amd64.tar.gz
# wget -N https://ghproxy.com/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.2.4/CloudflareST_linux_amd64.tar.gz
# 如果下载失败的话,尝试删除 -N 参数(如果是为了更新,则记得提前删除旧压缩包 rm CloudflareST_linux_amd64.tar.gz
# 下载 CFST 压缩包(自行根据需求替换 URL 中 [版本号] 和 [文件名]
wget -N https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.4/cfst_linux_amd64.tar.gz
# 如果你是在国内网络环境中下载,那么请使用下面这几个镜像加速之一
# wget -N https://wget.la/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.4/cfst_linux_amd64.tar.gz
# wget -N https://ghfast.top/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.4/cfst_linux_amd64.tar.gz
# wget -N https://ghproxy.it/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.4/cfst_linux_amd64.tar.gz
# wget -N https://gh-proxy.org/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.4/cfst_linux_amd64.tar.gz
# wget -N https://cdn.gh-proxy.org/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.4/cfst_linux_amd64.tar.gz
# 如果下载失败的话,尝试删除 -N 参数(如果是为了更新,则记得提前删除旧压缩包 rm cfst_linux_amd64.tar.gz
# 解压(不需要删除旧文件,会直接覆盖,自行根据需求替换 文件名)
tar -zxf CloudflareST_linux_amd64.tar.gz
tar -zxf cfst_linux_amd64.tar.gz
# 赋予执行权限
chmod +x CloudflareST
chmod +x cfst
# 运行(不带参数)
./CloudflareST
./cfst
# 运行(带参数示例)
./CloudflareST -dd -tll 90
./cfst -tl 200 -dn 20
```
> 如果平**均延迟非常低**(如 0.xx则说明 CloudflareST **测速时走了代理**,请先关闭代理软件后再测速。
> 如果平**均延迟非常低**(如 0.xx则说明 CFST **测速时走了代理**,请先关闭代理软件后再测速。
> 如果在**路由器**上运行,建议先关闭路由器内的代理(或将其排除),否则测速结果可能会**不准确/无法使用**。
</details>
****
> _在**手机**上独立运行 CloudflareST 测速的简单教程:**[Android](https://github.com/XIU2/CloudflareSpeedTest/discussions/61)、[Android APP](https://github.com/xianshenglu/cloudflare-ip-tester-app)、[IOS](https://github.com/XIU2/CloudflareSpeedTest/discussions/321)**_
> _在**手机**上独立运行 CFST 测速的简单教程:**[Android](https://github.com/XIU2/CloudflareSpeedTest/discussions/61)、[Android APP](https://github.com/xianshenglu/cloudflare-ip-tester-app)、[IOS](https://github.com/XIU2/CloudflareSpeedTest/discussions/321)**_
> 注意!本软件仅适用于网站,**不支持给 Cloudflare WARP 优选 IP**,具体见:[#392](https://github.com/XIU2/CloudflareSpeedTest/discussions/392)
> [!NOTE]
> 注意!本软件仅适用于网站,**不支持给使用 UDP 协议的 Cloudflare WARP 优选 IP**,具体见:[#392](https://github.com/XIU2/CloudflareSpeedTest/discussions/392)
### 结果示例
测速完毕后,默认会显示**最快的 10 个 IP**,示例:
测速完毕后,默认会显示**最快的 10 个 IP**,示例(仅为输出内容示例)
``` bash
IP 地址 已发送 已接收 丢包率 平均延迟 下载速度 (MB/s)
104.27.200.69 4 4 0.00 146.23 28.64
172.67.60.78 4 4 0.00 139.82 15.02
104.25.140.153 4 4 0.00 146.49 14.90
104.27.192.65 4 4 0.00 140.28 14.07
172.67.62.214 4 4 0.00 139.29 12.71
104.27.207.5 4 4 0.00 145.92 11.95
172.67.54.193 4 4 0.00 146.71 11.55
104.22.66.8 4 4 0.00 147.42 11.11
104.27.197.63 4 4 0.00 131.29 10.26
172.67.58.91 4 4 0.00 140.19 9.14
IP 地址 已发送 已接收 丢包率 平均延迟 下载速度(MB/s) 地区码
104.27.200.69 4 4 0.00 146.23 28.64 LAX
172.67.60.78 4 4 0.00 139.82 15.02 SEA
104.25.140.153 4 4 0.00 146.49 14.90 SJC
104.27.192.65 4 4 0.00 140.28 14.07 LAX
172.67.62.214 4 4 0.00 139.29 12.71 LAX
104.27.207.5 4 4 0.00 145.92 11.95 LAX
172.67.54.193 4 4 0.00 146.71 11.55 LAX
104.22.66.8 4 4 0.00 147.42 11.11 SEA
104.27.197.63 4 4 0.00 131.29 10.26 FRA
172.67.58.91 4 4 0.00 140.19 9.14 SJC
...
# 如果平均延迟非常低(如 0.xx则说明 CloudflareST 测速时走了代理,请先关闭代理软件后再测速。
# 如果平均延迟非常低(如 0.xx则说明 CFST 测速时走了代理,请先关闭代理软件后再测速。
# 如果在路由器上运行,请先关闭路由器内的代理(或将其排除),否则测速结果可能会不准确/无法使用。
# 因为每次测速都是在每个 IP 段中随机 IP所以每次的测速结果都不可能相同这是正常的
@@ -101,10 +121,12 @@ IP 地址 已发送 已接收 丢包率 平均延迟 下载速度
# 软件在 默认参数 下的整个流程大概步骤:
# 1. 延迟测速(默认 TCPing 模式HTTPing 模式需要手动加上参数)
# 2. 延迟排序(延迟从低到高排序并按条件过滤,不同丢包率会分开独立排序,因此可能会有一些延迟低但丢包的 IP 排到后面)
# 2. 延迟排序(延迟 从低到高 排序并按条件过滤,不同丢包率会分开排序,因此可能会有一些延迟低但丢包的 IP 排到后面)
# 3. 下载测速(从延迟最低的 IP 开始依次下载测速,默认测够 10 个就会停止)
# 4. 速度排序(速度从高到低排序)
# 5. 输出结果(通过参数控制是否输出到命令行(-p 0)或输出到文件(-o "")
# 注意:输出的结果文件 result.csv 通过微软 Excel 表格打开会中文乱码,这是正常的,其他表格软件/记事本都显示正常
```
测速结果第一行就是**既下载速度最快、又平均延迟最低的最快 IP**
@@ -112,10 +134,13 @@ IP 地址 已发送 已接收 丢包率 平均延迟 下载速度
完整结果保存在当前目录下的 `result.csv` 文件中,用**记事本/表格软件**打开,格式如下:
```
IP 地址, 已发送, 已接收, 丢包率, 平均延迟, 下载速度 (MB/s)
104.27.200.69,4,4,0.00,146.23,28.64
IP 地址,已发送,已接收,丢包率,平均延迟,下载速度(MB/s),地区码
104.27.200.69,4,4,0.00,146.23,28.64,LAX
```
> [!NOTE]
> _如果你发现**下载速度为 0.00**,那么可以用**调试模式 `-debug`** 排查一下,详见:[**# 下载测速都是 0.00 **](https://github.com/XIU2/CloudflareSpeedTest#-%E4%B8%8B%E8%BD%BD%E6%B5%8B%E9%80%9F%E9%83%BD%E6%98%AF-000-)_
> _大家可以按自己需求对完整结果**进一步筛选处理**,或者去看一看进阶使用**指定过滤条件**_
****
@@ -123,11 +148,11 @@ IP 地址, 已发送, 已接收, 丢包率, 平均延迟, 下载速度 (MB/s)
直接运行使用的是默认参数,如果想要测速结果更全面、更符合自己的要求,可以自定义参数。
```css
C:\>CloudflareST.exe -h
```Dart
C:\>cfst.exe -h
CloudflareSpeedTest vX.X.X
测试 Cloudflare CDN 所有 IP 的延迟和速度,获取最快 IP (IPv4+IPv6)
测试各个 CDN 或网站所有 IP 的延迟和速度,获取最快 IP (IPv4+IPv6)
https://github.com/XIU2/CloudflareSpeedTest
参数:
@@ -143,15 +168,22 @@ https://github.com/XIU2/CloudflareSpeedTest
指定测速端口;延迟测速/下载测速时使用的端口;(默认 443 端口)
-url https://cf.xiu2.xyz/url
指定测速地址;延迟测速(HTTPing)/下载测速时使用的地址,默认地址不保证可用性,建议自建;
当下载测速时,软件会从 HTTP 响应头中获取该 IP 当前地区码(支持 Cloudflare、AWS CloudFront、Fastly、Gcore、CDN77、Bunny 等 CDN并显示出来。
-httping
切换测速模式;延迟测速模式改为 HTTP 协议,所用测试地址为 [-url] 参数;(默认 TCPing)
当使用 HTTP 测速模式时,软件会从 HTTP 响应头中获取该 IP 当前地区码(支持 Cloudflare、AWS CloudFront、Fastly、Gcore、CDN77、Bunny 等 CDN并显示出来。
注意HTTPing 本质上也算一种 网络扫描 行为,因此如果你在服务器上面运行,需要降低并发(-n),否则可能会被一些严格的商家暂停服务。
如果你遇到 HTTPing 首次测速可用 IP 数量正常,后续测速越来越少甚至直接为 0但停一段时间后又恢复了的情况那么也可能是被 运营商、Cloudflare CDN 认为你在网络扫描而 触发临时限制机制,因此才会过一会儿就恢复了,建议降低并发(-n)减少这种情况的发生。
-httping-code 200
有效状态代码HTTPing 延迟测速时网页返回的有效 HTTP 状态码,仅限一个;(默认 200 301 302)
-cfcolo HKG,KHH,NRT,LAX,SEA,SJC,FRA,MAD
匹配指定地区;地区名为当地机场三字码,英文逗号分隔,支持小写,支持 Cloudflare、AWS CloudFront,仅 HTTPing 模式可用;(默认 所有地区)
匹配指定地区;IATA 机场地区码或国家/城市码,英文逗号分隔,大小写均可,仅 HTTPing 模式可用;(默认 所有地区)
支持 Cloudflare、AWS CloudFront、Fastly、Gcore、CDN77、Bunny 等 CDN
其中 Cloudflare、AWS CloudFront、Fastly 使用的是 IATA 三字机场地区码HKG,LAX
其中 CDN77、Bunny 使用的是 二字国家/区域码US,CN
其中 Gcore 使用的是 二字城市码FR,AM
因此大家使用 -cfcolo 指定地区码时要根据不同的 CDN 来指定不同类型的地区码。
-tl 200
平均延迟上限;只输出低于指定平均延迟的 IP各上下限条件可搭配使用(默认 9999 ms)
@@ -170,12 +202,19 @@ https://github.com/XIU2/CloudflareSpeedTest
指定IP段数据直接通过参数指定要测速的 IP 段数据,英文逗号分隔;(默认 空)
-o result.csv
写入结果文件;如路径含有空格请加上引号;值为空时不写入文件 [-o ""](默认 result.csv)
注意:在一些环境下使用 -o "" 可能会被忽略掉这个空参数导致报错,可加个空格 -o " " 解决
-dd
禁用下载测速;禁用后测速结果会按延迟排序 (默认按下载速度排序)(默认 启用)
-allip
测速全部的IP对 IP 段中的每个 IP (仅支持 IPv4) 进行测速;(默认 每个 /24 段随机测速一个 IP)
-debug
调试输出模式;会在一些非预期情况下输出更多日志以便判断原因;(默认 关闭)
目前该功能仅针对 HTTPing 延迟测速过程 及 下载测速过程,当过程中因为各种原因导致当前 IP 测速中断都会输出错误原因
例如HTTPing 延迟测速过程中,因为 HTTP 状态码不符合或测速地址有问题或超时等原因而终止测速
例如下载测速过程中因为下载测速地址有问题被阻断、403状态码、超时等原因而终止测速导致显示 0.00
-v
打印程序版本 + 检查版本更新
-h
@@ -184,35 +223,37 @@ https://github.com/XIU2/CloudflareSpeedTest
### 界面解释
为了避免大家对 CloudflareST 测速过程中的界面内容有所误解(可用、队列等数字),我特意做个示例解释下。
为了避免大家对测速过程中的**输出内容产生误解(可用、队列等数字,下载测速一半就"中断"?下载测速"卡住"不动?)**,我特意解释下。
<details>
<summary><code><strong>「 点击展开 查看内容 」</strong></code></summary>
****
> 该例把常用参数都给加上了,即为:`-ttl 40 -tl 150 -sl 1 -dn 5`,最后输出结果如下:
> 该例把常用参数都给加上了,即为:`-tll 40 -tl 150 -sl 1 -dn 5`,最后输出结果如下:
``` bash
```python
# XIU2/CloudflareSpeedTest vX.X.X
开始延迟测速模式TCP, 端口443, 范围40 ~ 150 ms, 丢包1.00)
321 / 321 [----------------------------------------------------------------------------------] 可用: 30
321 / 321 [-----------------------------------------------------------] 可用: 30
开始下载测速下限1.00 MB/s, 数量5, 队列10
3 / 5 [---------------------------------------------------------↗---------------------------]
IP 地址 已发送 已接收 丢包率 平均延迟 下载速度 (MB/s)
XXX.XXX.XXX.XXX 4 4 0.00 83.32 3.66
XXX.XXX.XXX.XXX 4 4 0.00 107.81 2.49
XXX.XXX.XXX.XXX 4 3 0.25 149.59 1.04
3 / 5 [-------------------------------------------------------------]
IP 地址 已发送 已接收 丢包率 平均延迟 下载速度(MB/s) 地区码
XXX.XXX.XXX.XXX 4 4 0.00 83.32 3.66 LAX
XXX.XXX.XXX.XXX 4 4 0.00 107.81 2.49 LAX
XXX.XXX.XXX.XXX 4 3 0.25 149.59 1.04 N/A
完整测速结果已写入 result.csv 文件,可使用记事本/表格软件查看。
按下 回车键 或 Ctrl+C 退出。
```
> 刚接触 CloudflareST 的人,可能会迷惑明明延迟测速可用 IP 有 30 个,怎么最后只剩下 3 个了呢?
****
> 刚接触 CFST 的人,可能会迷惑**明明延迟测速可用 IP 有 30 个,怎么最后只剩下 3 个了呢?**
> 下载测速里的队列又是什么意思?难道我下载测速还要排队?
CloudflareST 会先延迟测速,在这过程中进度条右侧会实时显示可用 IP 数量(`可用: 30`),但注意该可用数量指的是**测试通过没有超时的 IP 数量**,和延迟上下限、丢包条件无关。当延迟测速完成后,因为还指定了**延迟上下限、丢包**的条件,所以按照条件过滤后只剩下 `10` 个了(也就是等待下载测速的 `队列10`)。
CFST 会先延迟测速,在这过程中进度条右侧会实时显示可用 IP 数量(`可用: 30`),但注意该可用数量指的是**测试通过没有超时的 IP 数量**,和延迟上下限、丢包条件无关。当延迟测速完成后,因为还指定了**延迟上下限、丢包**的条件,所以按照条件过滤后只剩下 `10` 个了(也就是等待下载测速的 `队列10`)。
即以上示例中,`321` 个 IP 延迟测速完成后,只有 `30` 个 IP 测试通过没有超时,然后根据延迟上下限范围:`40 ~ 150 ms` 及丢包上限条件过滤后,只剩下 `10` 个满足要求的 IP 了。如果你 `-dd` 禁用了下载测速,那么就会直接输出这 `10` 个 IP 了。当然该示例并未禁用,因此接下来软件会继续对这 `10` 个 IP 进行下载测速(`队列10`)。
@@ -220,7 +261,7 @@ CloudflareST 会先延迟测速,在这过程中进度条右侧会实时显示
****
> 你可能注意到了,明明指定了要找到 5 个满足下载速度条件的 IP怎么才 3 个就 “中断” 了呢?
> 你可能注意到了,**明明指定了要找到 5 个满足下载速度条件的 IP怎么才 3 个就 “中断” 了呢?**
下载测速进度条中的 `3 / 5`,前者指的是找到了 `3` 个满足下载速度下限条件的 IP即下载速度高于 `1 MB/s` ),后者 `5` 指的是你要求找到 `5` 个满足下载速度下限条件的 IP`-dn 5`)。
@@ -230,6 +271,28 @@ CloudflareST 会先延迟测速,在这过程中进度条右侧会实时显示
因此,这不是 `“每次测速都不到 5 就中断了”`,而是所有 IP 都下载测速完了,但却只找到了 `3` 个满足条件的。
****
还有一种情况,那就是当可用 IP 很多时(几百几千),你还设置了下载速度条件,那么可能就会遇到:**怎么下载测速进度条老是卡在 `X / 5` 了呢?**
这其实并不是卡住了,而是只有当找到一个满足条件的 IP 时,进度条才会 +1因此如果一直找不到那么 CFST 就会一直下载测速下去,因此在表现为进度条卡住不动,但这也是在提醒你:你设置的下载速度条件对你来说已经高于实际了,你需要适当调低预期。
****
如果不想遇到这种全部测速一遍都没几个满足条件的情况,那么就要**调低下载速度上限参数 `-sl`**,或者移除。
因为只要指定了 `-sl` 参数,那么只要没有凑够 `-dn` 的数量(默认 10 个),就会一直测速下去,直到凑够或全部测速完。移除 `-sl` 并添加 `-dn 20` 参数,这样就是只测速延迟最低的前 20 个 IP测速完就停止节省时间。
****
另外,如果全部队列 IP 都测速完了,但一个满足下载速度条件的 IP 都没有,你可能需要调低预期的下载测速下限条件,但你需要知道当前的大概测速速度都在什么范围,那么你就可以加上 `-debug` 参数开启调试模式,这样再遇到这种情况时,就会**忽略条件返回所有测速结果**,你就能看到这些 IP 的下载速度都有多少,心里也就有数了,然后**适当调低 `-sl` 再试试**。
> 注意,如果你**没有指定**下载测速下限 `-sl` 条件,那么无论什么情况下 CFST 都会**输出所有测速结果**。
同样,延迟测速方面,`可用: 30`、`队列10` 这两个数值也可以让你清楚,你设置的延迟条件对你来说是否过于苛刻。如果可用 IP 一大堆,但条件过滤后只剩下 2、3 个,那不用说就知道需要**调低预期的延迟/丢包条件**了。
这两个机制,一个是告诉你**延迟丢包条件**是否合适的,一个是告诉你**下载速度条件**是否合适的。
</details>
****
@@ -238,13 +301,14 @@ CloudflareST 会先延迟测速,在这过程中进度条右侧会实时显示
Windows 要指定参数需要在 CMD 中运行,或者把参数添加到快捷方式目标中。
> **注意**:各参数均有**默认值**,使用默认值的参数是可以省略的(**按需选择**),参数**不分前后顺序**。
> **提示**Windows **PowerShell** 只需把下面命令中的 `CloudflareST.exe` 改为 `.\CloudflareST.exe` 即可
> **提示**Linux 系统只需把下面命令中的 `CloudflareST.exe` 改为 `./CloudflareST` 即可。
> [!TIP]
> - 各参数均有**默认值**,当使用默认值时参数可以省略(**按需选择**),参数**不分前后顺序**
> - Windows **PowerShell** 只需把下面命令中的 `cfst.exe` 改为 `.\cfst.exe` 即可。
> - Linux / macOS 系统只需要把下面命令中的 `cfst.exe` 改为 `./cfst` 即可。
****
#### \# CMD 带参数运行 CloudflareST
#### \# CMD 带参数运行
对命令行程序不熟悉的人,可能不知道该如何带参数运行,我就简单说一下。
@@ -253,28 +317,29 @@ Windows 要指定参数需要在 CMD 中运行,或者把参数添加到快捷
****
很多人打开 CMD 以**绝对路径**运行 CloudflareST 会报错,这是因为默认的 `-f ip.txt` 参数是相对路径,需要指定绝对路径的 ip.txt 才行,但这样毕竟太麻烦了,因此还是建议进入 CloudflareST 程序目录下,以**相对路径**方式运行:
很多人打开 CMD 直接就以**绝对路径**运行 CFST 会报错,这是因为默认的 `-f ip.txt` 参数是相对路径,需要指定绝对路径的 ip.txt 才行,但这样毕竟太麻烦了,因此还是建议进入 CFST 程序目录下,以**相对路径**方式运行:
**方式 一**
1. 打开 CloudflareST 程序所在目录
1. 打开 CFST 程序所在目录
2. 空白处按下 <kbd>Shift + 鼠标右键</kbd> 显示右键菜单
3. 选择 **\[在此处打开命令窗口\]** 来打开 CMD 窗口,此时默认就位于当前目录下
4. 输入带参数的命令,如:`CloudflareST.exe -tll 50 -tl 200`即可运行
4. 输入带参数的命令,如:`cfst.exe -tl 200 -dn 20` 即可运行
**方式 二**
1. 打开 CloudflareST 程序所在目录
2. 直接在文件夹地址栏中全选并输入 `cmd` 回车打开 CMD 窗口,此时默认就位于当前目录下
4. 输入带参数的命令,如:`CloudflareST.exe -tll 50 -tl 200`即可运行
1. 打开 CFST 程序所在目录
2. 直接在文件夹地址栏中全选(或清空)并输入 `cmd` 回车就能打开 CMD 窗口,此时默认就位于当前目录下
4. 输入带参数的命令,如:`cfst.exe -tl 200 -dn 20` 即可运行
> 当然你也可以随便打开一个 CMD 窗口,然后输入如 `cd /d "D:\Program Files\CloudflareST"` 来进入程序目录
> 当然你也可以随便打开一个 CMD 窗口,然后输入如 `cd /d "D:\Program Files\cfst"` 来进入程序目录
> **提示**:如果用的是 **PowerShell** 只需把命令中的 `CloudflareST.exe` 改为 `.\CloudflareST.exe` 即可。
> **提示**:如果用的是 **PowerShell** 只需把命令中的 `cfst.exe` 改为 `.\cfst.exe` 即可。
> **注意**:在 **PowerShell** 下使用 `-o ""` 会被忽略掉空参数导致报错,可加个空格 `-o " "` 解决
</details>
****
#### \# Windows 快捷方式带参数运行 CloudflareST
#### \# Windows 快捷方式带参数运行
如果不经常修改运行参数(比如平时都是直接双击运行)的人,建议使用快捷方式,更方便点。
@@ -283,14 +348,14 @@ Windows 要指定参数需要在 CMD 中运行,或者把参数添加到快捷
****
右键 `CloudflareST.exe` 文件 - **\[创建快捷方式\]**,然后右键该快捷方式 - **\[属性\]**,修改其**目标**
右键 `cfst.exe` 文件 - **\[创建快捷方式\]**,然后右键该快捷方式 - **\[属性\]**,修改其**目标**
``` bash
# 如果要不输出结果文件,那么请加上 -o " ",引号里的是空格(没有空格会导致该参数被省略)。
D:\ABC\CloudflareST\CloudflareST.exe -n 500 -t 4 -dn 20 -dt 5 -o " "
# 如果要不输出结果文件,那么请加上 -o " ",引号里的是空格(不加空格会导致该参数被忽略从而报错)。
D:\ABC\cfst\cfst.exe -tl 200 -dn 20 -o " "
# 如果文件路径包含引号,则需要把启动参数放在引号外面,记得引号和 - 之间有空格。
"D:\Program Files\CloudflareST\CloudflareST.exe" -n 500 -t 4 -dn 20 -dt 5 -o " "
"D:\Program Files\cfst\cfst.exe" -tl 200 -dn 20 -o " "
# 注意!快捷方式 - 起始位置 不能是空的,否则就会因为绝对路径而找不到 ip.txt 文件
```
@@ -307,14 +372,14 @@ D:\ABC\CloudflareST\CloudflareST.exe -n 500 -t 4 -dn 20 -dt 5 -o " "
****
``` bash
# 指定自带的 IPv4 数据文件可测速这些 IPv4 地址(-f 默认值就是 ip.txt所以该参数可省略
CloudflareST.exe -f ip.txt
cfst.exe -f ip.txt
# 指定自带的 IPv6 数据文件可测速这些 IPv6 地址
# 另外v2.1.0 版本后支持 IPv4+IPv6 混合测速并移除了 -ipv6 参数,因此一个文件内可以同时包含 IPv4+IPv6 地址
CloudflareST.exe -f ipv6.txt
cfst.exe -f ipv6.txt
# 也可以直接通过参数指定要测速的 IP
CloudflareST.exe -ip 1.1.1.1,2606:4700::/32
cfst.exe -ip 1.1.1.1,2606:4700::/32
```
> 测速 IPv6 时,可能会注意到每次测速数量都不一样,了解原因: [#120](https://github.com/XIU2/CloudflareSpeedTest/issues/120)
@@ -340,46 +405,71 @@ HTTP 协议适用于快速测试某域名指向某 IP 时是否可以访问,
> 另外,本软件 HTTPing 仅获取**响应头(response headers)**,并不获取正文内容(即 URL 文件大小不影响 HTTPing 测试,但如果你还要下载测速的话,那么还是需要一个大文件的),类似于 curl -i 功能。
> 另外HTTPing 过程中,软件会从 HTTP 响应头中获取该 IP 当前地区码(支持 Cloudflare、AWS CloudFront、Fastly、Gcore、CDN77、Bunny 等 CDN并显示出来而 TCPing 过程中无法这样做(但 下载测速 时也会这样做来获取地区码,毕竟下载测速也是个 HTTP 链接)
``` bash
# 只需加上 -httping 参数即可切换到 HTTP 协议延迟测速模式
CloudflareST.exe -httping
cfst.exe -httping
# 软件会根据访问时网页返回的有效 HTTP 状态码来判断可用性(当然超时也算),默认对返回 200 301 302 这三个 HTTP 状态码的视为有效,可以手动指定认为有效的 HTTP 状态码,但只能指定一个(你需要提前确定测试地址正常情况下会返回哪个状态码)
CloudflareST.exe -httping -httping-code 200
cfst.exe -httping -httping-code 200
# 通过 -url 参数来指定 HTTPing 测试地址(可以是任意网页 URL不局限于具体文件地址
CloudflareST.exe -httping -url https://cf.xiu2.xyz/url
cfst.exe -httping -url https://cf.xiu2.xyz/url
# 如果你要 HTTPing 测试其他网站/CDN那么指定一个该网站/使用该 CDN 的地址(因为软件默认地址是 Cloudflare 的,只能用于测试 Cloudflare 的 IP
# 注意:如果测速地址为 HTTP 协议,记得加上 -tp 80这个参数会影响 延迟测速/下载测速 时使用的端口)
# 同理,如果要测速 80 端口,那么也需要加上 -url 参数来指定一个 http:// 协议的地址才行(且该地址不会强制重定向至 HTTPS如果是非 80 443 端口,那么需要确定该下载测速地址是否支持通过该端口访问。
CloudflareST.exe -httping -tp 80 -url http://cdn.cloudflare.steamstatic.com/steam/apps/5952/movie_max.webm
cfst.exe -httping -tp 80 -url http://cdn.cloudflare.steamstatic.com/steam/apps/5952/movie_max.webm
```
</details>
****
#### \# 匹配指定地区(colo 机场三字码)
#### \# 匹配指定地区
<details>
<summary><code><strong>「 点击展开 查看内容 」</strong></code></summary>
****
Cloudflare CDN 的节点 IP 是 Anycast IP即每个 IP 对应的服务器节点及地区不是固定的,而是动态变化的,**不同地区、不同运营商、不同时间段**访问**同一个 IP** 分配到的服务器节点地区和路线也都是不一样的(比如同一个 IP美国人访问就是分配到就近的美国节点服务器日本人访问则就又变成了就近的日本节点服务器了国内内地就比较特殊了只能给你分配到其他国家当然不同的 IP 段路由变化/分配逻辑也是不同的,有的 IP 段会较为固定)。
> **注意**!虽然 Cloudflare CDN 有很多亚洲节点,但**不代表你就能用上**,新加坡人测速可能随便一抓一大把的新加坡节点,但你全部扫一遍可能都遇不到一个,因为这是由 CDN 控制的。Anycast IP 的路由是经常变的,同一个 IP 今天可能是美国,明天你再访问可能就又分配到欧洲节点了(当然这只是个例子,一般没有那么频繁,这也和很多因素有关,比如线路拥塞程度,成本变动等),因此**不要对该功能有过高期待**~
或者你随便找个 Cloudflare CDN 的 IP比如官网域名的解析 IP `104.16.123.96`),然后去那些有全球节点的[在线 Ping 测试](https://ping.sx/ping?t=104.16.123.96)网站,你就会发现这个 IP 在全球大部分地区的延迟都是个位数(而且很多都是 0.X ms就算一些地方延迟高一些但也基本都控制在 几十ms只有在国内才会发现突然变成了 上百ms 了。
这就是 Anycast 技术,也就只有国内大陆这种特殊的网络情况,才需要对 Anycast 的 CDN IP 进行优选。
因此,对于这种 Anycast IP 的实际服务器位置,就不能靠那些在线 IP 地址位置查询网站来判断了。
除了通过 **HTTP 响应头**获取地区码外(该功能的实现方式),还可以手动访问 `http://CloudflareIP/cdn-cgi/trace` 来获知 CDN 分配给你的实际节点地区码。
> 该功能支持 **Cloudflare、AWS CloudFront、Fastly、Gcore、CDN77、Bunny** 等 CDN。
> 但注意,不是所有 CDN 都支持 Anycast 技术的,很多 CDN 会限制一个网站能使用的 IP 范围。
> 其中 **Cloudflare、AWS CloudFront、Fastly** 都使用的是 **`IATA 三字机场地区码`**HKG,LAX
> 而 **CDN77、Bunny** 使用的是 **`二字国家/区域码`**US,CN
> **Gcore** 则使用的是 **`二字城市码`**FR,AM
> 因此大家使用 `-cfcolo` 指定地区码时要根据不同的 CDN 来指定不同类型的地区码。
> **注意**:如果你要用于筛选 AWS CloudFront CDN 地区,那么要通过 `-url` 参数指定一个使用 AWS CloudFront CDN 的下载测速地址(因为软件默认下载测速地址是 Cloudflare CDN 的),另外有时候 HTTPing 模式测速一些 AWS CloudFront 地址会返回 403 错误,这种情况下需要加上 `-httping-code 403` 才能正确获取地区码。
``` bash
# 该功能支持 Cloudflare CDN、AWS CloudFront CDN且这两个 CDN 的机场三字码是通用的
# 注意:如果你要用于筛选 AWS CloudFront CDN 地区,那么要通过 -url 参数指定一个使用该 CDN 的地址(因为软件默认地址是 Cloudflare 的)
# 指定地区名后,延迟测速后得到的结果就都是指定地区的 IP 了(如果没有指定 -dd 的话则会继续进行下载测速)
# 如果延迟测速后结果为 0则说明没有找到任何一个未超时可用的指定地区的 IP。
# 节点地区名为当地 IATA 机场地区码或国家/城市码指定多个时用英文逗号分隔v2.2.3 版本后支持小写
# 指定地区名后,延迟测速后得到的结果就都是指定地区的 IP 了(也可以继续进行下载测速)
# 节点地区名为当地 机场三字码指定多个时用英文逗号分隔v2.2.3 版本后支持小写
cfst.exe -httping -cfcolo HKG,KHH,NRT,LAX,SEA,SJC,FRA,MAD
CloudflareST.exe -cfcolo HKG,KHH,NRT,LAX,SEA,SJC,FRA,MAD
# 注意,该参数只有在 HTTPing 延迟测速模式下才可用(因为软件是通过 HTTP 链接中的响应头来获得该 IP 的实际地区码)
# 注意,该参数只有在 HTTPing 延迟测速模式下才可用(因为要访问网页来获得
# 另外HTTPing 过程中,软件会从 HTTP 响应头中获取该 IP 当前地区码(支持 Cloudflare、AWS CloudFront、Fastly、Gcore、CDN77、Bunny 等 CDN并显示出来而 TCPing 过程中无法这样做(但 下载测速 时也会这样做来获取地区码,毕竟下载测速也是个 HTTP 链接
```
> 两个 CDN 机场三字码通用,因此各地区名可见https://www.cloudflarestatus.com/
> **`IATA 三字机场地区码`**可见https://www.cloudflarestatus.com/
> **`二字国家码`**,可见:[https://zh.wikipedia.org/wiki/ISO_3166-1二位字母代码#正式分配代码](https://zh.wikipedia.org/wiki/ISO_3166-1%E4%BA%8C%E4%BD%8D%E5%AD%97%E6%AF%8D%E4%BB%A3%E7%A0%81#%E6%AD%A3%E5%BC%8F%E5%88%86%E9%85%8D%E4%BB%A3%E7%A0%81)
</details>
@@ -394,37 +484,37 @@ CloudflareST.exe -cfcolo HKG,KHH,NRT,LAX,SEA,SJC,FRA,MAD
``` bash
# 指定 IPv4 数据文件,不显示结果直接退出,输出结果到文件(-p 值为 0
CloudflareST.exe -f 1.txt -p 0 -dd
cfst.exe -f 1.txt -p 0 -dd
# 指定 IPv4 数据文件,不输出结果到文件,直接显示结果(-p 值为 10 条,-o 值为空但引号不能少)
CloudflareST.exe -f 2.txt -o "" -p 10 -dd
cfst.exe -f 2.txt -o "" -p 10 -dd
# 指定 IPv4 数据文件 及 输出结果到文件(相对路径,即当前目录下,如含空格请加上引号)
CloudflareST.exe -f 3.txt -o result.txt -dd
cfst.exe -f 3.txt -o result.txt -dd
# 指定 IPv4 数据文件 及 输出结果到文件(相对路径,即当前目录内的 abc 文件夹下,如含空格请加上引号)
# LinuxCloudflareST 程序所在目录内的 abc 文件夹下)
./CloudflareST -f abc/3.txt -o abc/result.txt -dd
# LinuxCFST 程序所在目录内的 abc 文件夹下)
./cfst -f abc/3.txt -o abc/result.txt -dd
# Windows注意是反斜杠
CloudflareST.exe -f abc\3.txt -o abc\result.txt -dd
cfst.exe -f abc\3.txt -o abc\result.txt -dd
# 指定 IPv4 数据文件 及 输出结果到文件(绝对路径,即 C:\abc\ 目录下,如含空格请加上引号)
# Linux/abc/ 目录下)
./CloudflareST -f /abc/4.txt -o /abc/result.csv -dd
./cfst -f /abc/4.txt -o /abc/result.csv -dd
# Windows注意是反斜杠
CloudflareST.exe -f C:\abc\4.txt -o C:\abc\result.csv -dd
cfst.exe -f C:\abc\4.txt -o C:\abc\result.csv -dd
# 如果要以【绝对路径】运行 CloudflareST那么 -f / -o 参数中的文件名也必须是【绝对路径】,否则会报错找不到文件!
# 如果要以【绝对路径】运行 CFST那么 -f / -o 参数中的文件名也必须是【绝对路径】,否则会报错找不到文件!
# Linux/abc/ 目录下)
/abc/CloudflareST -f /abc/4.txt -o /abc/result.csv -dd
/abc/cfst -f /abc/4.txt -o /abc/result.csv -dd
# Windows注意是反斜杠
C:\abc\CloudflareST.exe -f C:\abc\4.txt -o C:\abc\result.csv -dd
C:\abc\cfst.exe -f C:\abc\4.txt -o C:\abc\result.csv -dd
```
</details>
@@ -441,7 +531,7 @@ C:\abc\CloudflareST.exe -f C:\abc\4.txt -o C:\abc\result.csv -dd
# 如果你想要测速非默认 443 的其他端口,则需要通过 -tp 参数指定(该参数会影响 延迟测速/下载测速 时使用的端口)
# 如果要延迟测速 80 端口+下载测速(如果 -dd 禁用了下载测速则不需要),那么还需要指定 http:// 协议的下载测速地址才行(且该地址不会强制重定向至 HTTPS因为那样就变成 443 端口了)
CloudflareST.exe -tp 80 -url http://cdn.cloudflare.steamstatic.com/steam/apps/5952/movie_max.webm
cfst.exe -tp 80 -url http://cdn.cloudflare.steamstatic.com/steam/apps/5952/movie_max.webm
# 如果是非 80 443 的其他端口,那么需要确定你使用的下载测速地址是否支持通过该非标端口访问。
```
@@ -461,10 +551,10 @@ CloudflareST.exe -tp 80 -url http://cdn.cloudflare.steamstatic.com/steam/apps/59
# 该参数适用于下载测速 及 HTTP 协议的延迟测速,对于后者该地址可以是任意网页 URL不局限于具体文件地址
# 地址要求:可以直接下载、文件大小超过 200MB、用的是 Cloudflare CDN
CloudflareST.exe -url https://cf.xiu2.xyz/url
cfst.exe -url https://cf.xiu2.xyz/url
# 注意:如果测速地址为 HTTP 协议(该地址不能强制重定向至 HTTPS记得加上 -tp 80这个参数会影响 延迟测速/下载测速 时使用的端口),如果是非 80 443 端口,那么需要确定下载测速地址是否支持通过该端口访问。
CloudflareST.exe -tp 80 -url http://cdn.cloudflare.steamstatic.com/steam/apps/5952/movie_max.webm
cfst.exe -tp 80 -url http://cdn.cloudflare.steamstatic.com/steam/apps/5952/movie_max.webm
```
</details>
@@ -485,7 +575,7 @@ CloudflareST.exe -tp 80 -url http://cdn.cloudflare.steamstatic.com/steam/apps/59
``` bash
# 平均延迟上限200 ms下载速度下限0 MB/s
# 即找到平均延迟低于 200 ms 的 IP然后再按延迟从低到高进行 10 次下载测速
CloudflareST.exe -tl 200
cfst.exe -tl 200
```
> 如果**没有找到一个满足延迟**条件的 IP那么不会输出任何内容。
@@ -497,7 +587,7 @@ CloudflareST.exe -tl 200
``` bash
# 平均延迟上限200 ms下载速度下限0 MB/s数量不知道多少 个
# 即只输出低于 200ms 的 IP且不再下载测速因为不再下载测速所以 -dn 参数就无效了)
CloudflareST.exe -tl 200 -dd
cfst.exe -tl 200 -dd
```
- 仅指定 **[丢包几率上限]** 条件
@@ -505,7 +595,7 @@ CloudflareST.exe -tl 200 -dd
``` bash
# 丢包几率上限0.25
# 即找到丢包率低于等于 0.25 的 IP范围 0.00~1.00,如果 -tlr 0 则代表过滤掉任何丢包的 IP
CloudflareST.exe -tlr 0.25
cfst.exe -tlr 0.25
```
****
@@ -515,13 +605,14 @@ CloudflareST.exe -tlr 0.25
``` bash
# 平均延迟上限9999 ms下载速度下限5 MB/s数量10 个(可选)
# 即需要找到 10 个平均延迟低于 9999 ms 且下载速度高于 5 MB/s 的 IP 才会停止测速
CloudflareST.exe -sl 5 -dn 10
cfst.exe -sl 5 -dn 10
```
> 如果**没有找到一个满足速度**条件的 IP那么会**忽略条件输出所有 IP 测速结果**(方便你下次测速时调整条件)。
> 如果**没有找到一个满足速度**条件的 IP那么不会输出任何内容,你可能需要调低预期的下载测速下限条件,但你需要知道当前的大概测速速度都在什么范围,那么你就可以加上 `-debug` 参数开启调试模式,这样再遇到这种情况时,就会**忽略条件返回所有测速结果**,你就能看到这些 IP 的下载速度都有多少,心里也就有数了,然后**适当调低 `-sl` 再试试**。
> 注意,如果你**没有指定**下载测速下限 `-sl` 条件,那么无论什么情况下 CFST 都会**输出所有测速结果**。
> 没有指定平均延迟上限时,如果一直**凑不够**满足条件的 IP 数量,就会**一直测速**下去。
> 所以建议**同时指定 [下载速度下限] + [平均延迟上限]**,这样测速到指定延迟上限还没凑够数量,就会终止测速。
> 建议**同时指定 [下载速度下限] + [平均延迟上限]**,这样测速到指定延迟上限还没凑够数量,就会终止测速。
****
@@ -531,16 +622,43 @@ CloudflareST.exe -sl 5 -dn 10
# 平均延迟上限、下载速度下限均支持小数(如 -sl 0.5
# 平均延迟上限200 ms下载速度下限5.6 MB/s数量10 个(可选)
# 即需要找到 10 个平均延迟低于 200 ms 且下载速度高于 5 .6MB/s 的 IP 才会停止测速
CloudflareST.exe -tl 200 -sl 5.6 -dn 10
cfst.exe -tl 200 -sl 5.6 -dn 10
```
> 如果**没有找到一个满足延迟**条件的 IP那么不会输出任何内容。
> 如果**没有找到一个满足速度**条件的 IP那么会忽略条件输出所有 IP 测速结果(方便你下次测速时调整条件)。
> 如果**没有找到一个满足速度**条件的 IP那么不会输出任何内容,但可以通过加上 `-debug` 参数开启调试模式,这时会忽略条件输出所有 IP 测速结果(方便你下次测速时调整条件)。
> 所以建议先不指定条件测速一遍,看看平均延迟和下载速度大概在什么范围,避免指定条件**过低/过高**
> 因为 Cloudflare 公开的 IP 段是**回源 IP+任播 IP**,而**回源 IP**是无法使用的,所以下载测速是 0.00。
> 运行时可以加上 `-sl 0.01`(下载速度下限),过滤掉**回源 IP**(下载测速低于 0.01MB/s 的结果)。
****
为了避免大家迷糊,我列出了在各种条件组合下的预期输出结果都是什么样的。
**没有指定任何 延迟/速度条件 (即都是默认值)**
- 无论如何,都直接输出 **所有测速结果**
****
**指定了任何 延迟条件(`-tl` `-tll`,且无论是否开启调试模式 `-debug` 都一样):**
- 如果找到最少 1 个满足条件的 IP则只输出 **这几个满足条件的 IP**(如没有禁用下载测速,则会继续下载测速)
- 如果没找到任何满足条件的 IP则会输出 **空**(如没有禁用下载测速,也会因为数量为 0 而跳过下载测速)
****
**指定了任何 下载速度条件 (`-sl`)**
且当 **关闭 调试模式** 时(即没加上 `-debug` 参数,这种情况下和延迟测速的逻辑完全一致):
- 如果找到最少 1 个满足条件的 IP则只输出 **这几个满足条件的 IP**
- 如果没找到任何满足条件的 IP则输出 **空**
且当 **开启 调试模式** 时(即加上了 `-debug` 参数,延迟测速并没有加上下面第二条里的逻辑,所以依然输出 空):
- 如果找到最少 1 个满足条件的 IP则只输出 **这几个满足条件的 IP**
- 如果没找到任何满足条件的 IP则直接输出 **所有测速结果**
</details>
****
@@ -555,12 +673,12 @@ CloudflareST.exe -tl 200 -sl 5.6 -dn 10
**方式 一**
直接通过参数指定要测速的 IP 段数据。
``` bash
# 先进入 CloudflareST 所在目录,然后运行:
# 先进入 CFST 所在目录,然后运行:
# Windows 系统(在 CMD 中运行)
CloudflareST.exe -ip 1.1.1.1,2.2.2.2/24,2606:4700::/32
cfst.exe -ip 1.1.1.1,2.2.2.2/24,2606:4700::/32
# Linux 系统
./CloudflareST -ip 1.1.1.1,2.2.2.2/24,2606:4700::/32
./cfst -ip 1.1.1.1,2.2.2.2/24,2606:4700::/32
```
****
@@ -579,15 +697,15 @@ CloudflareST.exe -ip 1.1.1.1,2.2.2.2/24,2606:4700::/32
> 子网掩码 `/24` 指的是这个 IP 最后一段,即 `1.0.0.1~1.0.0.255`。
然后运行 CloudflareST 时加上启动参数 `-f 1.txt` 来指定 IP 段数据文件。
然后运行 CFST 时加上启动参数 `-f 1.txt` 来指定 IP 段数据文件。
``` bash
# 先进入 CloudflareST 所在目录,然后运行:
# 先进入 CFST 所在目录,然后运行:
# Windows 系统(在 CMD 中运行)
CloudflareST.exe -f 1.txt
cfst.exe -f 1.txt
# Linux 系统
./CloudflareST -f 1.txt
./cfst -f 1.txt
# 对于 1.0.0.1/24 这样的 IP 段只会随机最后一段1.0.0.1~255如果要测速该 IP 段中的所有 IP请加上 -allip 参数。
```
@@ -596,6 +714,80 @@ CloudflareST.exe -f 1.txt
****
#### \# 下载测速都是 0.00
<details>
<summary><code><strong>「 点击展开 查看内容 」</strong></code></summary>
****
**\#\# 原理简单解释:**
首先要明白CFST 下载测速过程,本质上和你将 `IP 下载测速地址域名` 写入 hosts 文件,然后浏览器去访问下载测速地址是一样的,只不过软件将其自动化了(类似于 `curl -I --resolve 下载测速地址域名:443:IP https://下载测速地址`)。
因此如果下载测速结果全都是 0.00 MB/s那么代表**下载测速过程中出问题报错**,导致直接终止测速了(并最终显示为 0.00),就只有这几种可能性:
1. **下载测速地址有问题**
2. **测速的 IP 地址有问题**
3. **你的网络有问题**
****
**\#\# 调试模式排查:**
接下来**请务必**先在你原先使用的 CFST 运行命令后**追加一个 `-debug` 参数来开启调试模式**,重新跑一遍测速,这样下载测速过程中出现任何报错都会显示具体原因方便你排查。
常见的下载测速失败报错原因有(因为是 Go 语言的原生报错信息,因此基本都是英文):
1. `... read: connection reset by peer ... `
**链接被重置**,可能是下载测速地址被阻断了 或测速 IP 被针对性 HTTPS 阻断了,可能是蔷干的,也可能是运营商干的(比如移动或部分地区的白名单),当然也可能是测速 IP 服务器单纯的重置了你这个不合法的链接请求
2. `... HTTP 状态码: 403 ...`
像这种直接提示 **HTTP 状态码**的,比较好判断,如 403 就是下载测速地址禁止你访问404 就是下载测速地址路径对应的文件找不到(具体其他的可以搜索 HTTP 状态码含义)
3. `... context deadline exceeded (Client.Timeout exceeded while awaiting headers) ...`
这种一般是**请求超时**引起的,可能是 IP 或网络问题,也可能是 `-dt` 下载测速时间设置的太短了(当然默认的 10 秒肯定算不上短)
4. `... tls: handshake failure ...` 或 `... tls: failed to verify certificate ...`
这种 **TLS 握手失败/SSL 证书错误** 代表下载测速地址和测速 IP 服务器不匹配,也就是下载测速地址与测速 IP 其中一方有误(例如下载测速地址是托管在 Fastly CDN 的,但测速 IP 是 Cloudflare CDN 的,或者反过来,总之就是你访问下载测速地址时该测速的 IP 服务器告诉你这个网站域名它不认识并把你拒之门外)
5. `... tls: failed to verify certificate: x509: certificate is valid for XXX.XX, not YYY.YY ...`
这种是 **SSL 证书里没有包含你下载测速地址的域名**,要么是下载测速地址证书配置有问题,要么就是该测速服务器 IP 上并没有该下载测速地址域名对应的 SSL 证书,也就意味着这个服务器 IP 是不能用于该下载测速地址域名的(比如你用谷歌的服务器 IP 去下载测速百度的域名就会这样,或像上面 4 的原因一样)
6. `... tls: failed to verify certificate: x509: certificate has expired or is not yet valid: current time ...`
这种是 **SSL 证书过期了或者尚未到有效时间**,除了这个原因外,也可能是和上面 4、5 的原因一样(这 4、5、6 三种报错可能会同时出现在同一个服务器 IP 上)
7. `... tls: failed to verify certificate: x509: certificate signed by unknown authority.`
这种代表**系统证书配置有问题**,导致 TLS 握手时无法验证证书,目前只在 Termux 内遇到过解决方法见https://github.com/XIU2/CloudflareSpeedTest/discussions/61 帖子末尾)
> 如果你遇到了其他报错原因,且翻译后还是不懂,可以发 Issues 或 Discussions 询问,我也会更新到这里。
> 但注意,发 Issues 或 Discussions 询问时,请记得带上**调试模式下 CFST 输出的完整内容(或者完整截图)**。
根据上面的报错原因排查一遍后,如果还是无法解决,那么可以尝试下面这些进一步排查:
****
**一、下载测速地址有问题**
先去 [#490](https://github.com/XIU2/CloudflareSpeedTest/discussions/490) 找几个其他的下载测速地址都试试。
如果其中有能下载测速出结果的,则就代表你之前使用的下载测速地址有问题(注意,目前默认下载测速地址仅为一个带负载均衡轮询的重定向链接,会自动重定向到上面帖子里大家分享的公益下载测速地址,而这些地址在**不同地区的可用性可能有差异**,因此可能出现之前不行现在又正常的情况,如果**想要稳定,建议自建**,上面帖子写了几种自建方法)。
如果找了很多,都是一样 0.00,那么就要考虑其他可能性了。
****
**二、测速的 IP 地址有问题**
你用来测速的 IP 地址,可能一些 TCP 测试是通的,但实际上因为各种原因导致不能建立 HTTP 链接(比如是回源 IP比如是企业用户专用 IP 等等),因此你可以多尝试一些其他的 IP 看是否可行。
****
**三、你的网络有问题**
这个就比较麻烦了,如果你现在是用电脑+宽带来使用 CFST 测速的,那么可以尝试关闭手机 WIFI 并打开流量,然后数据线连接电脑,设置好 USB 网络共享(不同手机系统不太一样,具体自行搜索哈),并拔掉电脑的网线,这样你的电脑现在就是走的手机流量数据网络了(如果手机流量数据和宽带不是一个运营商会更好排查),然后再次运行 CFST 测速看看结果是否改变(也可以同时尝试上面的排查方法来交叉验证)。
如果测速结果正常了,那么显然就是宽带网络的问题,如果还是一样的 0.00,那么就麻烦了。。。
****
</details>
****
#### \# 一劳永逸加速所有使用 Cloudflare CDN 的网站(不需要再一个个添加域名到 Hosts 了)
我以前说过,开发该软件项目的目的就是为了通过**改 Hosts 的方式来加速访问使用 Cloudflare CDN 的网站**。
@@ -617,11 +809,12 @@ CloudflareST.exe -f 1.txt
如果你遇到什么问题,可以先去 [**Issues**](https://github.com/XIU2/CloudflareSpeedTest/issues)、[Discussions](https://github.com/XIU2/CloudflareSpeedTest/discussions) 里看看是否有别人问过了(记得去看下 [**Closed**](https://github.com/XIU2/CloudflareSpeedTest/issues?q=is%3Aissue+is%3Aclosed) 的)。
如果没找到类似问题,请新开个 [**Issues**](https://github.com/XIU2/CloudflareSpeedTest/issues/new) 来告诉我!
> **注意**_与 `反馈问题、功能建议` 无关的,请前往项目内部 论坛 讨论(上面的 `💬 Discussions`_
> [!NOTE]
> **注意**_与 CFST 本身 `反馈问题、功能建议` 无关的,请前往项目内部 论坛 讨论(顶部的 `💬 Discussions`_
****
## 赞赏支持
## 如果帮到你的话就 "打赏" 一下吧~🎉✨
![微信赞赏](https://github.com/XIU2/XIU2/blob/master/img/zs-01.png)![支付宝赞赏](https://github.com/XIU2/XIU2/blob/master/img/zs-02.png)
@@ -630,18 +823,24 @@ CloudflareST.exe -f 1.txt
## 衍生项目
- _https://github.com/xianshenglu/cloudflare-ip-tester-app_
_**CloudflareST 安卓版 APP [#202](https://github.com/XIU2/CloudflareSpeedTest/discussions/320)**_
_**CFST 安卓版 APP [#202](https://github.com/XIU2/CloudflareSpeedTest/discussions/320)**_
- _https://github.com/mingxiaoyu/luci-app-cloudflarespeedtest_
_**CloudflareST OpenWrt 路由器插件版 [#174](https://github.com/XIU2/CloudflareSpeedTest/discussions/319)**_
_**CFST OpenWrt 路由器插件版 [#174](https://github.com/XIU2/CloudflareSpeedTest/discussions/319)**_
- _https://github.com/immortalwrt-collections/openwrt-cdnspeedtest_
_**CloudflareST OpenWrt 原生编译版本 [#64](https://github.com/XIU2/CloudflareSpeedTest/discussions/64)**_
_**CFST OpenWrt 原生编译版本 [#64](https://github.com/XIU2/CloudflareSpeedTest/discussions/64)**_
- _https://github.com/GuangYu-yu/CloudflareST-Rust_
_**CFST Rust 版本**_
- _https://github.com/masgzy/CloudflareST_
_**CFST 的分支衍生版本(依然是 Go**_
- _https://github.com/hoseinnikkhah/CloudflareSpeedTest-English_
_**English language version of CloudflareST (Text language differences only) [#64](https://github.com/XIU2/CloudflareSpeedTest/issues/68)**_
_**English language version of CFST (Text language differences only) [#64](https://github.com/XIU2/CloudflareSpeedTest/issues/68)**_
> _此处仅收集了在本项目中宣传过的部分 CloudflareST 相关衍生项目,如果有遗漏可以告诉我~_
> _此处仅收集了在本项目中宣传过的部分 CFST 相关衍生项目,如果有遗漏可以告诉我~_
****
@@ -649,8 +848,8 @@ _**English language version of CloudflareST (Text language differences only) [#6
- _https://github.com/Spedoske/CloudflareScanner_
> _因为该项目已经很长时间没更新了而我又产生了很多功能需求所以我临时学了下 Go 语言就上手了(菜)..._
> _本软件基于该项目制作,但**已添加大量功能修复 BUG**根据大家的使用反馈积极添加优化功能(闲)..._
> _因为该项目已经很长时间没更新了而我又产生了很多功能需求所以我临时学了下 Go 语言就上手了 (菜)..._
> _本软件基于该项目但**已彻底重构并添加大量功能/修复BUG**,根据大家的使用反馈积极添加/优化功能 (闲)..._
****
@@ -664,8 +863,8 @@ _**English language version of CloudflareST (Text language differences only) [#6
为了方便,我是在编译的时候将版本号写入代码中的 version 变量,因此你手动编译时,需要像下面这样在 `go build` 命令后面加上 `-ldflags` 参数来指定版本号:
```bash
go build -ldflags "-s -w -X main.version=v2.3.3"
# 在 CloudflareSpeedTest 目录中通过命令行(例如 CMD、Bat 脚本运行该命令即可编译一个可在和当前设备同样系统、位数、架构的环境下运行的二进制程序Go 会自动检测你的系统位数、架构)且版本号为 v2.3.3
go build -ldflags "-s -w -X main.version=v1.0.0"
# 在 CloudflareSpeedTest 目录中通过命令行(例如 CMD、Bat 脚本运行该命令即可编译一个可在和当前设备同样系统、位数、架构的环境下运行的二进制程序Go 会自动检测你的系统位数、架构)且版本号为 v1.0.0
```
如果想要在 Windows 64位系统下编译**其他系统、架构、位数**,那么需要指定 **GOOS** 和 **GOARCH** 变量。
@@ -675,7 +874,7 @@ go build -ldflags "-s -w -X main.version=v2.3.3"
```bat
SET GOOS=linux
SET GOARCH=amd64
go build -ldflags "-s -w -X main.version=v2.3.3"
go build -ldflags "-s -w -X main.version=v1.0.0"
```
例如在 Linux 系统下编译一个适用于 **Windows 系统 amd 架构 32 位**的二进制程序:
@@ -683,7 +882,7 @@ go build -ldflags "-s -w -X main.version=v2.3.3"
```bash
GOOS=windows
GOARCH=386
go build -ldflags "-s -w -X main.version=v2.3.3"
go build -ldflags "-s -w -X main.version=v1.0.0"
```
> 可以运行 `go tool dist list` 来查看当前 Go 版本支持编译哪些组合。
@@ -695,18 +894,18 @@ go build -ldflags "-s -w -X main.version=v2.3.3"
```bat
:: Windows 系统下是这样:
SET version=v2.3.3
SET version=v1.0.0
SET GOOS=linux
SET GOARCH=amd64
go build -o Releases\CloudflareST_linux_amd64\CloudflareST -ldflags "-s -w -X main.version=%version%"
go build -o Releases\cfst_linux_amd64\cfst -ldflags "-s -w -X main.version=%version%"
```
```bash
# Linux 系统下是这样:
version=v2.3.3
version=v1.0.0
GOOS=windows
GOARCH=386
go build -o Releases/CloudflareST_windows_386/CloudflareST.exe -ldflags "-s -w -X main.version=${version}"
go build -o Releases/cfst_windows_386/cfst.exe -ldflags "-s -w -X main.version=${version}"
```
</details>
@@ -715,4 +914,4 @@ go build -o Releases/CloudflareST_windows_386/CloudflareST.exe -ldflags "-s -w -
## License
The GPL-3.0 License.
The GPL-3.0 License.

15
go.mod
View File

@@ -1,8 +1,17 @@
module github.com/XIU2/CloudflareSpeedTest
go 1.14
go 1.18
require (
github.com/VividCortex/ewma v1.1.1
github.com/cheggaaa/pb/v3 v3.0.4
github.com/VividCortex/ewma v1.2.0
github.com/cheggaaa/pb/v3 v3.1.7
github.com/fatih/color v1.18.0
)
require (
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
golang.org/x/sys v0.30.0 // indirect
)

35
go.sum
View File

@@ -1,17 +1,18 @@
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/cheggaaa/pb/v3 v3.0.4 h1:QZEPYOj2ix6d5oEg63fbHmpolrnNiwjUsk+h74Yt4bM=
github.com/cheggaaa/pb/v3 v3.0.4/go.mod h1:7rgWxLrAUcFMkvJuv09+DYi7mMUYi8nO9iOWcvGJPfw=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
github.com/cheggaaa/pb/v3 v3.1.7 h1:2FsIW307kt7A/rz/ZI2lvPO+v3wKazzE4K/0LtTWsOI=
github.com/cheggaaa/pb/v3 v3.1.7/go.mod h1:/Ji89zfVPeC/u5j8ukD0MBPHt2bzTYp74lQ7KlgFWTQ=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

28
main.go
View File

@@ -3,7 +3,7 @@ package main
import (
"flag"
"fmt"
"io/ioutil"
"io"
"net/http"
"os"
"runtime"
@@ -21,7 +21,7 @@ func init() {
var printVersion bool
var help = `
CloudflareSpeedTest ` + version + `
测试 Cloudflare CDN 所有 IP 的延迟和速度,获取最快 IP (IPv4+IPv6)
测试各个 CDN 或网站所有 IP 的延迟和速度,获取最快 IP (IPv4+IPv6)
https://github.com/XIU2/CloudflareSpeedTest
参数:
@@ -43,7 +43,7 @@ https://github.com/XIU2/CloudflareSpeedTest
-httping-code 200
有效状态代码HTTPing 延迟测速时网页返回的有效 HTTP 状态码,仅限一个;(默认 200 301 302)
-cfcolo HKG,KHH,NRT,LAX,SEA,SJC,FRA,MAD
匹配指定地区;地区名为当地机场三字码,英文逗号分隔,仅 HTTPing 模式可用;(默认 所有地区)
匹配指定地区;IATA 机场地区码或国家/城市码,英文逗号分隔,仅 HTTPing 模式可用;(默认 所有地区)
-tl 200
平均延迟上限;只输出低于指定平均延迟的 IP各上下限条件可搭配使用(默认 9999 ms)
@@ -68,6 +68,9 @@ https://github.com/XIU2/CloudflareSpeedTest
-allip
测速全部的IP对 IP 段中的每个 IP (仅支持 IPv4) 进行测速;(默认 每个 /24 段随机测速一个 IP)
-debug
调试输出模式;会在一些非预期情况下输出更多日志以便判断原因;(默认 关闭)
-v
打印程序版本 + 检查版本更新
-h
@@ -99,12 +102,14 @@ https://github.com/XIU2/CloudflareSpeedTest
flag.BoolVar(&task.Disable, "dd", false, "禁用下载测速")
flag.BoolVar(&task.TestAll, "allip", false, "测速全部 IP")
flag.BoolVar(&utils.Debug, "debug", false, "调试输出模式")
flag.BoolVar(&printVersion, "v", false, "打印程序版本")
flag.Usage = func() { fmt.Print(help) }
flag.Parse()
if task.MinSpeed > 0 && time.Duration(maxDelay)*time.Millisecond == utils.InputMaxDelay {
fmt.Println("[提示] 在使用 [-sl] 参数时,建议搭配 [-tl] 参数,以避免因凑不够 [-dn] 数量而一直测速...")
utils.Yellow.Println("[提示] 在使用 [-sl] 参数时,建议搭配 [-tl] 参数,以避免因凑不够 [-dn] 数量而一直测速...")
}
utils.InputMaxDelay = time.Duration(maxDelay) * time.Millisecond
utils.InputMinDelay = time.Duration(minDelay) * time.Millisecond
@@ -117,9 +122,9 @@ https://github.com/XIU2/CloudflareSpeedTest
fmt.Println("检查版本更新中...")
checkUpdate()
if versionNew != "" {
fmt.Printf("*** 发现新版本 [%s]!请前往 [https://github.com/XIU2/CloudflareSpeedTest] 更新! ***", versionNew)
utils.Yellow.Printf("*** 发现新版本 [%s]!请前往 [https://github.com/XIU2/CloudflareSpeedTest] 更新! ***", versionNew)
} else {
fmt.Println("当前为最新版本 [" + version + "]")
utils.Green.Println("当前为最新版本 [" + version + "]")
}
os.Exit(0)
}
@@ -136,15 +141,12 @@ func main() {
speedData := task.TestDownloadSpeed(pingData)
utils.ExportCsv(speedData) // 输出文件
speedData.Print() // 打印结果
if versionNew != "" {
fmt.Printf("\n*** 发现新版本 [%s]!请前往 [https://github.com/XIU2/CloudflareSpeedTest] 更新! ***\n", versionNew)
}
endPrint()
endPrint() // 根据情况选择退出方式(针对 Windows
}
// 根据情况选择退出方式(针对 Windows
func endPrint() {
if utils.NoPrintResult() {
if utils.NoPrintResult() { // 如果不需要打印测速结果,则直接退出
return
}
if runtime.GOOS == "windows" { // 如果是 Windows 系统,则需要按下 回车键 或 Ctrl+C 退出(避免通过双击运行时,测速完毕后直接关闭)
@@ -162,7 +164,7 @@ func checkUpdate() {
return
}
// 读取资源数据 body: []byte
body, err := ioutil.ReadAll(res.Body)
body, err := io.ReadAll(res.Body)
if err != nil {
return
}

View File

@@ -1,23 +1,38 @@
# XIU2/CloudflareSpeedTest - Script
# XIU2/CloudflareSpeedTest - Script(脚本)
这里都是一些基于 **XIU2/CloudflareSpeedTest** 并**扩展更多功能**的脚本。
有什么现有脚本功能上的建议可以告诉我,如果你有一些自用好用的脚本也可以通过 [**Issues**](https://github.com/XIU2/CloudflareSpeedTest/issues) 或 Pull requests 发给我添加到这里让更多人用到(会标注作者的~
> 小提示:点击↖左上角的三横杠图标按钮即可查看目录~
这里都是一些通过调用 **CFST** 并**扩展实现更多个性化功能**的脚本。
****
## 📑 cfst_hosts.sh / cfst_hosts.bat (已内置)
> [!TIP]
> 我之所以将 CFST 制作为一个**命令行程序**,就是考虑到**通用性**,因为毕竟不可能把所有需求都塞到软件内(特别是一些**个性化、小众**的需求),这样增加维护难度和精力不说,还会导致软件异常臃肿(`“变成我讨厌的样子”`),而命令行程序的优势之一就在于**可以很方便的和其他软件、脚本搭配使用**。
运行 CloudflareST 获得最快 IP 后,脚本会替换 Hosts 文件中的旧 CDN IP。
比如像下面这些我写的几个脚本,就是把一些需求以外置脚本方式实现。
> **使用说明https://github.com/XIU2/CloudflareSpeedTest/issues/42**
> 即脚本调用 CFST 测速并获取结果,然后***按照自己的需求自由决定***如何处理得到的测速结果(比如修改 Hosts 等)。
总的来说,我写的这几个脚本都比较简单,功能也很单一,除了满足部分用户的需求外,***更像是一个 CFST 与脚本搭配使用的示例参考***,对于一些会写脚本、软件的用户来说,完全可以**自给自足**来实现一些个性化需求。
当然,如果你有一些自用好用的脚本也可以通过 [**Issues**](https://github.com/XIU2/CloudflareSpeedTest/issues)、[**Discussions**](https://github.com/XIU2/CloudflareSpeedTest/discussions) 或 **Pull requests** 发给我添加到这里让更多人用到!
> 小提示:点击↗右上角的三横杠图标按钮即可查看目录~
****
## 📑 cfst_hosts.sh / cfst_hosts.bat (已内置压缩包)
脚本会运行 CFST 获得最快 IP并替换掉 Hosts 文件中的旧 CDN IP。
> **作者:**[@XIU2](https://github.com/xiu2)
> **使用说明/问题反馈https://github.com/XIU2/CloudflareSpeedTest/discussions/312**
<details>
<summary><code><strong>「 更新日志」</strong></code></summary>
****
#### 2021年12月17日,版本 v1.0.6
#### 2025年12月15日,版本 v1.0.5 (cfst_hosts.bat)
- **1. 修复** CFST新版本下获取不到第一行 IP 的问题
#### 2021年12月17日版本 v1.0.4
- **1. 优化** [找不到满足条件的 IP 就一直循环测速] 功能,在指定下载测速下限时没有重新测速的问题(默认注释)
#### 2021年12月17日版本 v1.0.3
@@ -37,18 +52,22 @@
****
## 📑 cfst_3proxy.bat (已内置)
## 📑 cfst_3proxy.bat (已内置压缩包)
脚本的作用为 CloudflareST 测速后获取最快 IP 并替换 3Proxy 配置文件中的 Cloudflare CDN IP。
脚本会运行 CFST 测速后获取最快 IP 并替换 3Proxy 配置文件中的 Cloudflare CDN IP。
可以把所有 Cloudflare CDN IP 都重定向至最快 IP实现一劳永逸的加速所有使用 Cloudflare CDN 的网站(不需要一个个添加域名到 Hosts 了)。
> **使用说明:https://github.com/XIU2/CloudflareSpeedTest/discussions/71**
> **作者:**[@XIU2](https://github.com/xiu2)
> **使用说明/问题反馈https://github.com/XIU2/CloudflareSpeedTest/discussions/71**
<details>
<summary><code><strong>「 更新日志」</strong></code></summary>
****
#### 2025年12月15日版本 v1.0.6
- **1. 修复** CFST新版本下获取不到第一行 IP 的问题
#### 2021年12月17日版本 v1.0.5
- **1. 优化** [找不到满足条件的 IP 就一直循环测速] 功能,在指定下载测速下限时没有重新测速的问题(默认注释)
@@ -72,17 +91,45 @@
****
## 📑 cfst_ddns.sh / cfst_ddns.bat
## 📑 cfst_dnspod.sh
如果你的域名托管在 Cloudflare则可以通过 Cloudflare 官方提供的 API 来自动更新域名解析记录!
如果你的域名托管在 **dnspod**,则可以通过 dnspod 官方提供的 API 来自动更新域名解析记录!
脚本会运行 CFST 测速获得最快 IP并通过 Cloudflare API 来更新域名解析记录为这个最快 IP。
> **使用说明:https://github.com/XIU2/CloudflareSpeedTest/issues/40**
> **作者:**[@imashen](https://github.com/imashen)
> **使用说明/问题反馈https://github.com/XIU2/CloudflareSpeedTest/pull/533**
<details>
<summary><code><strong>「 更新日志」</strong></code></summary>
****
#### 2024年08月06日版本 v1.0.0
- **1. 发布** 第一个版本
</details>
****
## 📑 cfst_ddns.sh / cfst_ddns.bat
如果你的域名托管在 **Cloudflare**,则可以通过 Cloudflare 官方提供的 API 来自动更新域名解析记录!
脚本会运行 CFST 测速获得最快 IP并通过 Cloudflare API 来更新域名解析记录为这个最快 IP。
> **作者:**[@XIU2](https://github.com/xiu2)
> **使用说明/问题反馈https://github.com/XIU2/CloudflareSpeedTest/discussions/481**
<details>
<summary><code><strong>「 更新日志」</strong></code></summary>
****
#### 2025年12月15日版本 v1.0.6 (cfst_ddns.bat)
- **1. 修复** CFST新版本下获取不到第一行 IP 的问题
#### 2024年10月06日版本 v1.0.5
- **1. 新增** 支持 API 令牌方式(相比 API 密钥这种全局权限的API 令牌可以自由控制权限)
#### 2021年12月17日版本 v1.0.4
- **1. 新增** 找不到满足条件的 IP 就一直循环测速功能(默认注释)
- **2. 优化** 代码
@@ -103,7 +150,29 @@
****
## 📑 cfst_dnsmasq.sh
脚本会运行 CFST 测速后获取最快 IP 并替换 dnsmasq 配置文件中的旧 Cloudflare CDN IP。
> **作者:**[@Sving1024](https://github.com/Sving1024)
> **使用说明/问题反馈https://github.com/XIU2/CloudflareSpeedTest/discussions/566**
<details>
<summary><code><strong>「 更新日志」</strong></code></summary>
****
#### 2025年01月22日版本 v1.0.1
- **1. 修复** IPv6 的问题
#### 2024年12月28日版本 v1.0.0
- **1. 发布** 第一个版本
</details>
****
## 功能建议/问题反馈
如果你遇到什么问题,可以先去 [**Issues**](https://github.com/XIU2/CloudflareSpeedTest/issues) 里看看是否有别人问过了(记得去看下 [**Closed**](https://github.com/XIU2/CloudflareSpeedTest/issues?q=is%3Aissue+is%3Aclosed) 的)
如果没找到类似问题,请新开个 [**Issues**](https://github.com/XIU2/CloudflareSpeedTest/issues/new) 来告诉我!
如果这些脚本使用过程中你遇到什么问题,可以先去脚本对应的 **`使用说明`** 帖子里看看是否有别人问过了
如果没找到类似问题,那么就在脚本对应的 **`使用说明`** 帖子里直接评论问作者吧。

View File

@@ -1,6 +1,6 @@
:: --------------------------------------------------------------
:: <09><>Ŀ: CloudflareSpeedTest <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD> 3Proxy
:: <09>汾: 1.0.5
:: <09>汾: 1.0.6
:: <09><><EFBFBD><EFBFBD>: XIU2
:: <09><>Ŀ: https://github.com/XIU2/CloudflareSpeedTest
:: --------------------------------------------------------------
@@ -36,7 +36,7 @@ if '%errorlevel%' NEQ '0' (
::<3A><><EFBFBD><EFBFBD> nowip_3proxy.txt <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>˵<EFBFBD><CBB5><EFBFBD>ǵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>иýű<C3BD>
if not exist "nowip_3proxy.txt" (
echo <20>ýű<C3BD><C5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ CloudflareST <20><><EFBFBD>ٺ<EFBFBD><D9BA><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> IP <20><><EFBFBD>滻 3Proxy <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>е<EFBFBD> Cloudflare CDN IP<49><50>
echo <20>ýű<C3BD><C5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ CFST <20><><EFBFBD>ٺ<EFBFBD><D9BA><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> IP <20><><EFBFBD>滻 3Proxy <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>е<EFBFBD> Cloudflare CDN IP<49><50>
echo <20><><EFBFBD>԰<EFBFBD><D4B0><EFBFBD><EFBFBD><EFBFBD> Cloudflare CDN IP <20><><EFBFBD>ض<EFBFBD><D8B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP<49><50>ʵ<EFBFBD><CAB5>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ݵļ<DDB5><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> Cloudflare CDN <20><><EFBFBD><EFBFBD>վ<EFBFBD><D5BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫһ<D2AA><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Hosts <20>ˣ<EFBFBD><CBA3><EFBFBD>
echo ʹ<><CAB9>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD>https://github.com/XIU2/CloudflareSpeedTest/discussions/71
echo.
@@ -55,48 +55,46 @@ echo
:RESET
:: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>ӡ<EFBFBD><D3A1>޸<EFBFBD> CloudflareST <20><><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD>echo.| <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6>س<EFBFBD><D8B3>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>򣨲<EFBFBD><F2A3A8B2><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD> -p 0 <20><><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>
echo.|CloudflareST.exe -o "result_3proxy.txt"
:: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>ӡ<EFBFBD><D3A1>޸<EFBFBD> CFST <20><><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD>echo.| <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6>س<EFBFBD><D8B3>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>򣨲<EFBFBD><F2A3A8B2><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD> -p 0 <20><><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>
echo.|cfst.exe -o "result_3proxy.txt"
:: <20>жϽ<D0B6><CFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 0
if not exist result_3proxy.txt (
echo.
echo CloudflareST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
echo CFST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
goto :STOP
)
:: <20><>ȡ<EFBFBD><C8A1>һ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD> IP
for /f "tokens=1 delims=," %%i in (result_3proxy.txt) do (
set /a n+=1
If !n!==2 (
set bestip=%%i
goto :END
)
for /f "skip=1 tokens=1 delims=," %%i in ('more result_3proxy.txt') do (
SET bestip=%%i
goto :END
)
:END
:: <20>жϸոջ<D5B8>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20>Ƿ<EFBFBD>Ϊ<EFBFBD>գ<EFBFBD><D5A3>Լ<EFBFBD><D4BC>Ƿ<EFBFBD><C7B7>;<EFBFBD> IP һ<><D2BB>
if "%bestip%"=="" (
echo.
echo CloudflareST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
echo CFST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
goto :STOP
)
if "%bestip%"=="%nowip%" (
echo.
echo CloudflareST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
echo CFST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
goto :STOP
)
:: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD> "<22>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><>һֱѭ<D6B1><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ" <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>
:: <20><><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD>ޣ<EFBFBD><DEA3><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><>û<EFBFBD>ҵ<EFBFBD>ʱ<EFBFBD><CAB1>CloudflareST <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><><EFBFBD><EFBFBD>
:: <20><><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD>ޣ<EFBFBD><DEA3><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><>û<EFBFBD>ҵ<EFBFBD>ʱ<EFBFBD><CAB1>CFST <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><><EFBFBD><EFBFBD>
:: <20><><EFBFBD>˵<EFBFBD><CBB5><EFBFBD>ָ<EFBFBD><D6B8> -sl <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4>뿪ͷ<EBBFAA><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD> :: ð<><C3B0>ע<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϣ<D0B6><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>10 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 11<31><31>
::set /a v=0
::for /f %%a in ('type result_3proxy.txt') do set /a v+=1
::if %v% GTR 11 (
:: echo.
:: echo CloudflareST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ҵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP<49><50><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><C2B2><EFBFBD>...
:: echo CFST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ҵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP<49><50><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><C2B2><EFBFBD>...
:: goto :RESET
::)

View File

@@ -1,38 +1,42 @@
:: --------------------------------------------------------------
:: 项目: CloudflareSpeedTest 自动更新域名解析记录
:: 版本: 1.0.4
:: 版本: 1.0.6
:: 作者: XIU2
:: 项目: https://github.com/XIU2/CloudflareSpeedTest
:: --------------------------------------------------------------
@echo off
Setlocal Enabledelayedexpansion
:: 这里可以自己添加、修改 CloudflareST 的运行参数echo.| 的作用是自动回车退出程序(不再需要加上 -p 0 参数了)
echo.|CloudflareST.exe -o "result_ddns.txt"
:: 这里可以自己添加、修改 CFST 的运行参数echo.| 的作用是自动回车退出程序(不再需要加上 -p 0 参数了)
echo.|cfst.exe -o "result_ddns.txt"
:: 判断结果文件是否存在,如果不存在说明结果为 0
if not exist result_ddns.txt (
echo.
echo CloudflareST 测速结果 IP 数量为 0跳过下面步骤...
echo CFST 测速结果 IP 数量为 0跳过下面步骤...
goto :END
)
for /f "tokens=1 delims=," %%i in (result_ddns.txt) do (
Set /a n+=1
If !n!==2 (
Echo %%i
if "%%i"=="" (
echo.
echo CloudflareST 测速结果 IP 数量为 0跳过下面步骤...
goto :END
)
curl -X PUT "https://api.cloudflare.com/client/v4/zones/域名ID/dns_records/域名解析记录ID" ^
-H "X-Auth-Email: 账号邮箱" ^
-H "X-Auth-Key: 前面获取的 API 令牌" ^
-H "Content-Type: application/json" ^
--data "{\"type\":\"A\",\"name\":\"完整域名\",\"content\":\"%%i\",\"ttl\":1,\"proxied\":true}"
for /f "skip=1 tokens=1 delims=," %%i in (result_ddns.txt) do (
Echo %%i
if "%%i"=="" (
echo.
echo CFST 测速结果 IP 数量为 0跳过下面步骤...
goto :END
)
:: API 密钥方式(全局权限)
curl -X PUT "https://api.cloudflare.com/client/v4/zones/域名ID/dns_records/域名解析记录ID" ^
-H "X-Auth-Email: 账号邮箱" ^
-H "X-Auth-Key: 前面获取的 API 密钥" ^
-H "Content-Type: application/json" ^
--data "{\"type\":\"A\",\"name\":\"完整域名\",\"content\":\"%%i\",\"ttl\":1,\"proxied\":true}"
:: API 令牌方式(自定义权限),如果要使用这种方式,可以把上面的删除或注释,然后把下面的行首 "::" 注释符删除即可。
:: curl -X PUT "https://api.cloudflare.com/client/v4/zones/域名ID/dns_records/域名解析记录ID" ^
:: -H "Authorization: Bearer 前面获取的 API 令牌" ^
:: -H "Content-Type: application/json" ^
:: --data "{\"type\":\"A\",\"name\":\"完整域名\",\"content\":\"%%i\",\"ttl\":1,\"proxied\":true}"
goto :END
)
:END
pause

View File

@@ -3,7 +3,7 @@ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# --------------------------------------------------------------
# 项目: CloudflareSpeedTest 自动更新域名解析记录
# 版本: 1.0.4
# 版本: 1.0.5
# 作者: XIU2
# 项目: https://github.com/XIU2/CloudflareSpeedTest
# --------------------------------------------------------------
@@ -17,10 +17,10 @@ _READ() {
[[ -z "${ZONE_ID}" ]] && echo -e "[错误] 缺少配置项 [ZONE_ID] !" && exit 1
DNS_RECORDS_ID=$(echo "${CONFIG}"|grep 'DNS_RECORDS_ID='|awk -F '=' '{print $NF}')
[[ -z "${DNS_RECORDS_ID}" ]] && echo -e "[错误] 缺少配置项 [DNS_RECORDS_ID] !" && exit 1
EMAIL=$(echo "${CONFIG}"|grep 'EMAIL='|awk -F '=' '{print $NF}')
[[ -z "${EMAIL}" ]] && echo -e "[错误] 缺少配置项 [EMAIL] !" && exit 1
KEY=$(echo "${CONFIG}"|grep 'KEY='|awk -F '=' '{print $NF}')
[[ -z "${KEY}" ]] && echo -e "[错误] 缺少配置项 [KEY] !" && exit 1
EMAIL=$(echo "${CONFIG}"|grep 'EMAIL='|awk -F '=' '{print $NF}')
[[ -z "${EMAIL}" ]] && echo -e "[信息] 缺少配置项 [EMAIL],由 [API 密钥] 方式转为 [API 令牌] 方式!"
TYPE=$(echo "${CONFIG}"|grep 'TYPE='|awk -F '=' '{print $NF}')
[[ -z "${TYPE}" ]] && echo -e "[错误] 缺少配置项 [TYPE] !" && exit 1
NAME=$(echo "${CONFIG}"|grep 'NAME='|awk -F '=' '{print $NF}')
@@ -32,22 +32,32 @@ _READ() {
}
_UPDATE() {
# 这里可以自己添加、修改 CloudflareST 的运行参数
./CloudflareST -o "result_ddns.txt"
# 这里可以自己添加、修改 CFST 的运行参数
./cfst -o "result_ddns.txt"
# 判断结果文件是否存在,如果不存在说明结果为 0
[[ ! -e "result_ddns.txt" ]] && echo "CloudflareST 测速结果 IP 数量为 0跳过下面步骤..." && exit 0
[[ ! -e "result_ddns.txt" ]] && echo "CFST 测速结果 IP 数量为 0跳过下面步骤..." && exit 0
CONTENT=$(sed -n "2,1p" result_ddns.txt | awk -F, '{print $1}')
if [[ -z "${CONTENT}" ]]; then
echo "CloudflareST 测速结果 IP 数量为 0跳过下面步骤..."
echo "CFST 测速结果 IP 数量为 0跳过下面步骤..."
exit 0
fi
curl -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${DNS_RECORDS_ID}" \
-H "X-Auth-Email: ${EMAIL}" \
-H "X-Auth-Key: ${KEY}" \
-H "Content-Type: application/json" \
--data "{\"type\":\"${TYPE}\",\"name\":\"${NAME}\",\"content\":\"${CONTENT}\",\"ttl\":${TTL},\"proxied\":${PROXIED}}"
# 如果 EMAIL 变量是空的,那么就代表要使用 API 令牌方式
if [[ -n "${EMAIL}" ]]; then
# API 密钥方式(全局权限)
curl -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${DNS_RECORDS_ID}" \
-H "X-Auth-Email: ${EMAIL}" \
-H "X-Auth-Key: ${KEY}" \
-H "Content-Type: application/json" \
--data "{\"type\":\"${TYPE}\",\"name\":\"${NAME}\",\"content\":\"${CONTENT}\",\"ttl\":${TTL},\"proxied\":${PROXIED}}"
else
# API 令牌方式(自定义权限)
curl -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${DNS_RECORDS_ID}" \
-H "Authorization: Bearer ${KEY}" \
-H "Content-Type: application/json" \
--data "{\"type\":\"${TYPE}\",\"name\":\"${NAME}\",\"content\":\"${CONTENT}\",\"ttl\":${TTL},\"proxied\":${PROXIED}}"
fi
}
_READ

56
script/cfst_dnsmasq.sh Executable file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# --------------------------------------------------------------
# 项目: CloudflareSpeedTest 自动更新 dnsmasq 配置文件
# 版本: 1.0.1
# 作者: XIU2,Sving1024
# 项目: https://github.com/XIU2/CloudflareSpeedTest
# --------------------------------------------------------------
_UPDATE() {
echo -e "开始测速..."
BESTIP=""
BESTIP_IPV6="::"
# 这里可以自己添加、修改 CFST 的运行参数
./cfst -o "result_hosts.txt"
# 需要测速 IPv6 请取消注释
#./cfst -o "result_hosts_ipv6.txt" -f ipv6.txt
# 如果需要 "找不到满足条件的 IP 就一直循环测速下去",那么可以将下面的两个 exit 0 改为 _UPDATE 即可
[[ ! -e "result_hosts.txt" ]] && echo "CFST 测速结果 IP 数量为 0跳过下面步骤..." && exit 0
# 下面这行代码是 "找不到满足条件的 IP 就一直循环测速下去" 才需要的代码
# 考虑到当指定了下载速度下限,但一个满足全部条件的 IP 都没找到时CFST 就会输出所有 IP 结果
# 因此当你指定 -sl 参数时,需要移除下面这段代码开头的 # 井号注释符来做文件行数判断比如下载测速数量10 个,那么下面的值就设在为 11
#[[ $(cat result_hosts.txt|wc -l) > 11 ]] && echo "CFST 测速结果没有找到一个完全满足条件的 IP重新测速..." && _UPDATE
BESTIP=$(sed -n "2,1p" result_hosts.txt | awk -F, '{print $1}')
# 需要测速 IPv6 请取消注释
#BESTIP_IPV6=$(sed -n "2,1p" result_hosts_ipv6.txt | awk -F, '{print $1}')
if [[ -z "${BESTIP}" ]]; then
echo "CFST 测速结果 IP 数量为 0跳过下面步骤..."
exit 0
fi
echo ${BESTIP} > nowip_hosts.txt
echo -e "最优 IPv4 IP 为 ${BESTIP}\n"
# 需要测速 IPv6 请取消注释
#echo -e "最优 IPv6 IP 为 ${BESTIP_IPV6}\n"
[[ -f cloudflare.conf ]] && rm cloudflare.conf
cat site.conf | while read domain
do
if [[ ${domain:0:1} != "#" && ${domain} != "" ]]; then
echo "address=/${domain}/${BESTIP}" >> "cloudflare.conf"
echo "address=/${domain}/${BESTIP_IPV6}" >> "cloudflare.conf"
fi
done
[[ -f /etc/dnsmasq.d/cloudflare.conf ]] && rm /etc/dnsmasq.d/cloudflare.conf
cp cloudflare.conf /etc/dnsmasq.d/cloudflare.conf
systemctl restart dnsmasq.service
}
_UPDATE

106
script/cfst_dnspod.sh Normal file
View File

@@ -0,0 +1,106 @@
#!/bin/bash
# --------------------------------------------------------------
# 项目: CloudflareSpeedTest 自动更新Dnspod优选解析
# 版本: 1.0.0
# 作者: imashen
# --------------------------------------------------------------
# 清理历史残留
rm -f result4.csv result6.csv
# DNSPod API 凭据
dnspod_token="${API_TOKEN}"
dnspod_domain="${DOMAIN}"
dnspod_record="${SUB_DOMAIN}"
# DNSPod API URL
dnspod_api_url="https://dnsapi.cn"
# 获取记录 ID
get_record_id() {
local record_type=$1
local response
response=$(curl -s -X POST -d "login_token=$dnspod_token&format=json&domain=$dnspod_domain&record_type=$record_type" "$dnspod_api_url/Record.List")
local record_id
record_id=$(echo "$response" | jq -r --arg type "$record_type" '.records[] | select(.type == $type) | .id')
echo "$record_id"
}
# 创建 DNS 记录
create_dns_record() {
local record_type=$1
local ip_address=$2
local response
response=$(curl -s -X POST -d "login_token=$dnspod_token&format=json&domain=$dnspod_domain&sub_domain=$dnspod_record&record_type=$record_type&record_line=默认&value=$ip_address" "$dnspod_api_url/Record.Create")
local record_id
record_id=$(echo "$response" | jq -r '.record.id')
echo "$record_id"
}
# 更新 DNS 记录
update_dns_record() {
local record_id=$1
local record_type=$2
local ip_address=$3
curl -s -X POST -d "login_token=$dnspod_token&format=json&domain=$dnspod_domain&record_id=$record_id&sub_domain=$dnspod_record&record_type=$record_type&record_line=默认&value=$ip_address" "$dnspod_api_url/Record.Modify"
}
# 运行 CFST v4
./cfst -f ip.txt -n 500 -o result4.csv
# 读取 CSV 文件并提取优选 IPv4 地址
preferred_ipv4=$(awk -F, 'NR==2 {print $1}' result4.csv)
# 检查是否获取到了 IPv4 地址
if [ -z "$preferred_ipv4" ]; then
echo "Failed to get the preferred IPv4 address."
else
echo "BETTER IPv4: $preferred_ipv4"
# 获取 IPv4 记录 ID
ipv4_record_id=$(get_record_id "A")
if [ -n "$ipv4_record_id" ]; then
# 更新 IPv4 记录
update_dns_record "$ipv4_record_id" "A" "$preferred_ipv4"
echo "Updated DNSPod record with IPv4: $preferred_ipv4"
else
# 创建 IPv4 记录
new_ipv4_record_id=$(create_dns_record "A" "$preferred_ipv4")
if [ -n "$new_ipv4_record_id" ]; then
echo "Created DNSPod record with IPv4: $preferred_ipv4"
else
echo "Failed to create DNSPod record with IPv4."
fi
fi
fi
# 运行 CFST v6
./cfst -f ipv6.txt -n 500 -o result6.csv
# 读取 CSV 文件并提取优选 IPv6 地址
preferred_ipv6=$(awk -F, 'NR==2 {print $1}' result6.csv)
# 检查是否获取到了 IPv6 地址
if [ -z "$preferred_ipv6" ]; then
echo "Failed to get the preferred IPv6 address."
else
echo "BETTER IPv6: $preferred_ipv6"
# 获取 IPv6 记录 ID
ipv6_record_id=$(get_record_id "AAAA")
if [ -n "$ipv6_record_id" ]; then
# 更新 IPv6 记录
update_dns_record "$ipv6_record_id" "AAAA" "$preferred_ipv6"
echo "Updated DNSPod record with IPv6: $preferred_ipv6"
else
# 创建 IPv6 记录
new_ipv6_record_id=$(create_dns_record "AAAA" "$preferred_ipv6")
if [ -n "$new_ipv6_record_id" ]; then
echo "Created DNSPod record with IPv6: $preferred_ipv6"
else
echo "Failed to create DNSPod record with IPv6."
fi
fi
fi

View File

@@ -1,6 +1,6 @@
:: --------------------------------------------------------------
:: <09><>Ŀ: CloudflareSpeedTest <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD> Hosts
:: <09>汾: 1.0.4
:: <09>汾: 1.0.5
:: <09><><EFBFBD><EFBFBD>: XIU2
:: <09><>Ŀ: https://github.com/XIU2/CloudflareSpeedTest
:: --------------------------------------------------------------
@@ -36,7 +36,7 @@ if '%errorlevel%' NEQ '0' (
::<3A><><EFBFBD><EFBFBD> nowip_hosts.txt <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>˵<EFBFBD><CBB5><EFBFBD>ǵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>иýű<C3BD>
if not exist "nowip_hosts.txt" (
echo <20>ýű<C3BD><C5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ CloudflareST <20><><EFBFBD>ٺ<EFBFBD><D9BA><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> IP <20><><EFBFBD>滻 Hosts <20>е<EFBFBD> Cloudflare CDN IP<49><50>
echo <20>ýű<C3BD><C5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ CFST <20><><EFBFBD>ٺ<EFBFBD><D9BA><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> IP <20><><EFBFBD>滻 Hosts <20>е<EFBFBD> Cloudflare CDN IP<49><50>
echo ʹ<><CAB9>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD>https://github.com/XIU2/CloudflareSpeedTest/issues/42#issuecomment-768273768
echo.
echo <20><>һ<EFBFBD><D2BB>ʹ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>Ƚ<EFBFBD> Hosts <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Cloudflare CDN IP ͳһ<CDB3><D2BB>Ϊһ<CEAA><D2BB> IP<49><50>
@@ -55,48 +55,46 @@ echo
:RESET
:: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>ӡ<EFBFBD><D3A1>޸<EFBFBD> CloudflareST <20><><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD>echo.| <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6>س<EFBFBD><D8B3>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>򣨲<EFBFBD><F2A3A8B2><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD> -p 0 <20><><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>
echo.|CloudflareST.exe -o "result_hosts.txt"
:: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>ӡ<EFBFBD><D3A1>޸<EFBFBD> CFST <20><><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD>echo.| <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6>س<EFBFBD><D8B3>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>򣨲<EFBFBD><F2A3A8B2><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD> -p 0 <20><><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>
echo.|cfst.exe -o "result_hosts.txt"
:: <20>жϽ<D0B6><CFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 0
if not exist result_hosts.txt (
echo.
echo CloudflareST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
echo CFST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
goto :STOP
)
:: <20><>ȡ<EFBFBD><C8A1>һ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD> IP
for /f "tokens=1 delims=," %%i in (result_hosts.txt) do (
SET /a n+=1
If !n!==2 (
SET bestip=%%i
goto :END
)
for /f "skip=1 tokens=1 delims=," %%i in ('more result_hosts.txt') do (
SET bestip=%%i
goto :END
)
:END
:: <20>жϸոջ<D5B8>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20>Ƿ<EFBFBD>Ϊ<EFBFBD>գ<EFBFBD><D5A3>Լ<EFBFBD><D4BC>Ƿ<EFBFBD><C7B7>;<EFBFBD> IP һ<><D2BB>
if "%bestip%"=="" (
echo.
echo CloudflareST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
echo CFST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
goto :STOP
)
if "%bestip%"=="%nowip%" (
echo.
echo CloudflareST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
echo CFST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD> IP <20><><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B2BD>...
goto :STOP
)
:: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD> "<22>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><>һֱѭ<D6B1><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ" <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>
:: <20><><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD>ޣ<EFBFBD><DEA3><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><>û<EFBFBD>ҵ<EFBFBD>ʱ<EFBFBD><CAB1>CloudflareST <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><><EFBFBD><EFBFBD>
:: <20><><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD>ޣ<EFBFBD><DEA3><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><>û<EFBFBD>ҵ<EFBFBD>ʱ<EFBFBD><CAB1>CFST <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><><EFBFBD><EFBFBD>
:: <20><><EFBFBD>˵<EFBFBD><CBB5><EFBFBD>ָ<EFBFBD><D6B8> -sl <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4>뿪ͷ<EBBFAA><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD> :: ð<><C3B0>ע<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϣ<D0B6><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>10 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 11<31><31>
::set /a v=0
::for /f %%a in ('type result_hosts.txt') do set /a v+=1
::if %v% GTR 11 (
:: echo.
:: echo CloudflareST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ҵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP<49><50><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><C2B2><EFBFBD>...
:: echo CFST <20><><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ҵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP<49><50><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><C2B2><EFBFBD>...
:: goto :RESET
::)

View File

@@ -12,7 +12,7 @@ _CHECK() {
while true
do
if [[ ! -e "nowip_hosts.txt" ]]; then
echo -e "该脚本的作用为 CloudflareST 测速后获取最快 IP 并替换 Hosts 中的 Cloudflare CDN IP。\n使用前请先阅读https://github.com/XIU2/CloudflareSpeedTest/issues/42#issuecomment-768273848"
echo -e "该脚本的作用为 CFST 测速后获取最快 IP 并替换 Hosts 中的 Cloudflare CDN IP。\n使用前请先阅读https://github.com/XIU2/CloudflareSpeedTest/issues/42#issuecomment-768273848"
echo -e "第一次使用,请先将 Hosts 中所有 Cloudflare CDN IP 统一改为一个 IP。"
read -e -p "输入该 Cloudflare CDN IP 并回车(后续不再需要该步骤):" NOWIP
if [[ ! -z "${NOWIP}" ]]; then
@@ -31,21 +31,21 @@ _UPDATE() {
echo -e "开始测速..."
NOWIP=$(head -1 nowip_hosts.txt)
# 这里可以自己添加、修改 CloudflareST 的运行参数
./CloudflareST -o "result_hosts.txt"
# 这里可以自己添加、修改 CFST 的运行参数
./cfst -o "result_hosts.txt"
# 如果需要 "找不到满足条件的 IP 就一直循环测速下去",那么可以将下面的两个 exit 0 改为 _UPDATE 即可
[[ ! -e "result_hosts.txt" ]] && echo "CloudflareST 测速结果 IP 数量为 0跳过下面步骤..." && exit 0
[[ ! -e "result_hosts.txt" ]] && echo "CFST 测速结果 IP 数量为 0跳过下面步骤..." && exit 0
# 下面这行代码是 "找不到满足条件的 IP 就一直循环测速下去" 才需要的代码
# 考虑到当指定了下载速度下限,但一个满足全部条件的 IP 都没找到时CloudflareST 就会输出所有 IP 结果
# 考虑到当指定了下载速度下限,但一个满足全部条件的 IP 都没找到时CFST 就会输出所有 IP 结果
# 因此当你指定 -sl 参数时,需要移除下面这段代码开头的 # 井号注释符来做文件行数判断比如下载测速数量10 个,那么下面的值就设在为 11
#[[ $(cat result_hosts.txt|wc -l) > 11 ]] && echo "CloudflareST 测速结果没有找到一个完全满足条件的 IP重新测速..." && _UPDATE
#[[ $(cat result_hosts.txt|wc -l) > 11 ]] && echo "CFST 测速结果没有找到一个完全满足条件的 IP重新测速..." && _UPDATE
BESTIP=$(sed -n "2,1p" result_hosts.txt | awk -F, '{print $1}')
if [[ -z "${BESTIP}" ]]; then
echo "CloudflareST 测速结果 IP 数量为 0跳过下面步骤..."
echo "CFST 测速结果 IP 数量为 0跳过下面步骤..."
exit 0
fi
echo ${BESTIP} > nowip_hosts.txt

View File

@@ -12,7 +12,7 @@ _CHECK() {
while true
do
if [[ ! -e "nowip_hosts.txt" ]]; then
echo -e "该脚本的作用为 CloudflareST 测速后获取最快 IP 并替换 Hosts 中的 Cloudflare CDN IP。\n使用前请先阅读https://github.com/XIU2/CloudflareSpeedTest/issues/42#issuecomment-768273848"
echo -e "该脚本的作用为 CFST 测速后获取最快 IP 并替换 Hosts 中的 Cloudflare CDN IP。\n使用前请先阅读https://github.com/XIU2/CloudflareSpeedTest/issues/42#issuecomment-768273848"
echo -e "第一次使用,请先将 Hosts 中所有 Cloudflare CDN IP 统一改为一个 IP。"
read -e -p "输入该 Cloudflare CDN IP 并回车(后续不再需要该步骤):" NOWIP
if [[ ! -z "${NOWIP}" ]]; then
@@ -31,21 +31,21 @@ _UPDATE() {
echo -e "开始测速..."
NOWIP=$(head -1 nowip_hosts.txt)
# 这里可以自己添加、修改 CloudflareST 的运行参数
./CloudflareST -o "result_hosts.txt"
# 这里可以自己添加、修改 CFST 的运行参数
./cfst -o "result_hosts.txt"
# 如果需要 "找不到满足条件的 IP 就一直循环测速下去",那么可以将下面的两个 exit 0 改为 _UPDATE 即可
[[ ! -e "result_hosts.txt" ]] && echo "CloudflareST 测速结果 IP 数量为 0跳过下面步骤..." && exit 0
[[ ! -e "result_hosts.txt" ]] && echo "CFST 测速结果 IP 数量为 0跳过下面步骤..." && exit 0
# 下面这行代码是 "找不到满足条件的 IP 就一直循环测速下去" 才需要的代码
# 考虑到当指定了下载速度下限,但一个满足全部条件的 IP 都没找到时CloudflareST 就会输出所有 IP 结果
# 考虑到当指定了下载速度下限,但一个满足全部条件的 IP 都没找到时CFST 就会输出所有 IP 结果
# 因此当你指定 -sl 参数时,需要移除下面这段代码开头的 # 井号注释符来做文件行数判断比如下载测速数量10 个,那么下面的值就设在为 11
#[[ $(cat result_hosts.txt|wc -l) > 11 ]] && echo "CloudflareST 测速结果没有找到一个完全满足条件的 IP重新测速..." && _UPDATE
#[[ $(cat result_hosts.txt|wc -l) > 11 ]] && echo "CFST 测速结果没有找到一个完全满足条件的 IP重新测速..." && _UPDATE
BESTIP=$(sed -n "2,1p" result_hosts.txt | awk -F, '{print $1}')
if [[ -z "${BESTIP}" ]]; then
echo "CloudflareST 测速结果 IP 数量为 0跳过下面步骤..."
echo "CFST 测速结果 IP 数量为 0跳过下面步骤..."
exit 0
fi
echo ${BESTIP} > nowip_hosts.txt

View File

@@ -53,19 +53,19 @@ func TestDownloadSpeed(ipSet utils.PingDelaySet) (speedSet utils.DownloadSpeedSe
if Disable {
return utils.DownloadSpeedSet(ipSet)
}
if len(ipSet) <= 0 { // IP数组长度(IP数量) 大于 0 时才会继续下载测速
fmt.Println("\n[信息] 延迟测速结果 IP 数量为 0跳过下载测速。")
if len(ipSet) <= 0 { // IP 数组长度(IP数量) 大于 0 时才会继续下载测速
utils.Yellow.Println("[信息] 延迟测速结果 IP 数量为 0跳过下载测速。")
return
}
testNum := TestCount
if len(ipSet) < TestCount || MinSpeed > 0 { // 如果IP数组长度(IP数量) 小于下载测速数量-dn则次数修正为IP
testNum := TestCount // 等待下载测速的队列数量 先默认等于 下载测速数量(-dn
if len(ipSet) < TestCount || MinSpeed > 0 { // 如果延迟测速并过滤后的 IP 数组长度(IP数量) 小于 下载测速数量(-dn即 -dn 预期数量是不够的),或者指定了 下载测速下限 (-sl) 条件(这就可能要全部下载测速一遍,直到找齐预期数量或测完为止),则 等待下载测速的队列数量 修正为 IP 数量
testNum = len(ipSet)
}
if testNum < TestCount {
if testNum < TestCount { // 如果 等待下载测速的队列数量 小于 下载测速数量(-dn显然 -dn 预期数量是不够的),所以 下载测速数量(-dn修正为 等待下载测速的队列数量
TestCount = testNum
}
fmt.Printf("开始下载测速(下限:%.2f MB/s, 数量:%d, 队列:%d\n", MinSpeed, TestCount, testNum)
utils.Cyan.Printf("开始下载测速(下限:%.2f MB/s, 数量:%d, 队列:%d\n", MinSpeed, TestCount, testNum)
// 控制 下载测速进度条 与 延迟测速进度条 长度一致(强迫症)
bar_a := len(strconv.Itoa(len(ipSet)))
bar_b := " "
@@ -74,8 +74,11 @@ func TestDownloadSpeed(ipSet utils.PingDelaySet) (speedSet utils.DownloadSpeedSe
}
bar := utils.NewBar(TestCount, bar_b, "")
for i := 0; i < testNum; i++ {
speed := downloadHandler(ipSet[i].IP)
speed, colo := downloadHandler(ipSet[i].IP)
ipSet[i].DownloadSpeed = speed
if ipSet[i].Colo == "" { // 只有当 Colo 是空的时候,才写入,否则代表之前是 httping 测速并获取过了
ipSet[i].Colo = colo
}
// 在每个 IP 下载测速后,以 [下载速度下限] 条件过滤结果
if speed >= MinSpeed*1024*1024 {
bar.Grow(1, "")
@@ -86,7 +89,10 @@ func TestDownloadSpeed(ipSet utils.PingDelaySet) (speedSet utils.DownloadSpeedSe
}
}
bar.Done()
if len(speedSet) == 0 { // 没有符合速度限制的数据,返回所有测数据
if MinSpeed == 0.00 { // 如果没有指定下载速度下限,则直接返回所有测数据
speedSet = utils.DownloadSpeedSet(ipSet)
} else if utils.Debug && len(speedSet) == 0 { // 如果指定了下载速度下限,且是调试模式下,且没有找到任何一个满足条件的 IP 时,返回所有测速数据,供用户查看当前的测速结果,以便适当调低预期测速条件
utils.Yellow.Println("[调试] 没有满足 下载速度下限 条件的 IP忽略条件返回所有测速数据方便下次测速时调整条件。")
speedSet = utils.DownloadSpeedSet(ipSet)
}
// 按速度排序
@@ -106,13 +112,41 @@ func getDialContext(ip *net.IPAddr) func(ctx context.Context, network, address s
}
}
// 统一的请求报错调试输出
func printDownloadDebugInfo(ip *net.IPAddr, err error, statusCode int, url, lastRedirectURL string, response *http.Response) {
finalURL := url // 默认的最终 URL这样当 response 为空时也能输出
if lastRedirectURL != "" {
finalURL = lastRedirectURL // 如果 lastRedirectURL 不是空,说明重定向过,优先输出最后一次要重定向至的目标
} else if response != nil && response.Request != nil && response.Request.URL != nil {
finalURL = response.Request.URL.String() // 如果 response 不为 nil且 Request 和 URL 都不为 nil则获取最后一次成功的响应地址
}
if url != finalURL { // 如果 URL 和最终地址不一致,说明有重定向,是该重定向后的地址引起的错误
if statusCode > 0 { // 如果状态码大于 0说明是后续 HTTP 状态码引起的错误
utils.Red.Printf("[调试] IP: %s, 下载测速终止HTTP 状态码: %d, 下载测速地址: %s, 出错的重定向后地址: %s\n", ip.String(), statusCode, url, finalURL)
} else {
utils.Red.Printf("[调试] IP: %s, 下载测速失败,错误信息: %v, 下载测速地址: %s, 出错的重定向后地址: %s\n", ip.String(), err, url, finalURL)
}
} else { // 如果 URL 和最终地址一致,说明没有重定向
if statusCode > 0 { // 如果状态码大于 0说明是后续 HTTP 状态码引起的错误
utils.Red.Printf("[调试] IP: %s, 下载测速终止HTTP 状态码: %d, 下载测速地址: %s\n", ip.String(), statusCode, url)
} else {
utils.Red.Printf("[调试] IP: %s, 下载测速失败,错误信息: %v, 下载测速地址: %s\n", ip.String(), err, url)
}
}
}
// return download Speed
func downloadHandler(ip *net.IPAddr) float64 {
func downloadHandler(ip *net.IPAddr) (float64, string) {
var lastRedirectURL string // 用于记录最后一次重定向目标,以便在访问错误时输出
client := &http.Client{
Transport: &http.Transport{DialContext: getDialContext(ip)},
Timeout: Timeout,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) > 10 { // 限制最多重定向 10 次
lastRedirectURL = req.URL.String() // 记录每次重定向的目标,以便在访问错误时输出
if len(via) > 10 { // 限制最多重定向 10 次
if utils.Debug { // 调试模式下,输出更多信息
utils.Red.Printf("[调试] IP: %s, 下载测速地址重定向次数过多,终止测速,下载测速地址: %s\n", ip.String(), req.URL.String())
}
return http.ErrUseLastResponse
}
if req.Header.Get("Referer") == defaultURL { // 当使用默认下载测速地址时,重定向不携带 Referer
@@ -123,19 +157,32 @@ func downloadHandler(ip *net.IPAddr) float64 {
}
req, err := http.NewRequest("GET", URL, nil)
if err != nil {
return 0.0
if utils.Debug { // 调试模式下,输出更多信息
utils.Red.Printf("[调试] IP: %s, 下载测速请求创建失败,错误信息: %v, 下载测速地址: %s\n", ip.String(), err, URL)
}
return 0.0, ""
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36")
response, err := client.Do(req)
if err != nil {
return 0.0
if utils.Debug { // 调试模式下,输出更多信息
printDownloadDebugInfo(ip, err, 0, URL, lastRedirectURL, response)
}
return 0.0, ""
}
defer response.Body.Close()
if response.StatusCode != 200 {
return 0.0
if utils.Debug { // 调试模式下,输出更多信息
printDownloadDebugInfo(ip, nil, response.StatusCode, URL, lastRedirectURL, response)
}
return 0.0, ""
}
// 通过头部参数获取地区码
colo := getHeaderColo(response.Header)
timeStart := time.Now() // 开始时间(当前)
timeEnd := timeStart.Add(Timeout) // 加上下载测速时间得到的结束时间
@@ -179,5 +226,5 @@ func downloadHandler(ip *net.IPAddr) float64 {
}
contentRead += int64(bufferRead)
}
return e.Value() / (Timeout.Seconds() / 120)
return e.Value() / (Timeout.Seconds() / 120), colo
}

View File

@@ -2,7 +2,7 @@ package task
import (
//"crypto/tls"
//"fmt"
"io"
"log"
"net"
@@ -11,18 +11,22 @@ import (
"strings"
"sync"
"time"
"github.com/XIU2/CloudflareSpeedTest/utils"
)
var (
Httping bool
HttpingStatusCode int
HttpingCFColo string
HttpingCFColomap *sync.Map
OutRegexp = regexp.MustCompile(`[A-Z]{3}`)
Httping bool
HttpingStatusCode int
HttpingCFColo string
HttpingCFColomap *sync.Map
RegexpColoIATACode = regexp.MustCompile(`[A-Z]{3}`) // 匹配 IATA 机场地区码(俗称 机场三字码)的正则表达式
RegexpColoCountryCode = regexp.MustCompile(`[A-Z]{2}`) // 匹配国家地区码的正则表达式(如 US、CN、UK 等)
RegexpColoGcore = regexp.MustCompile(`^[a-z]{2}`) // 匹配城市地区码的正则表达式(小写,如 us、cn、uk 等)
)
// pingReceived pingTotalTime
func (p *Ping) httping(ip *net.IPAddr) (int, time.Duration) {
func (p *Ping) httping(ip *net.IPAddr) (int, time.Duration, string) {
hc := http.Client{
Timeout: time.Second * 2,
Transport: &http.Transport{
@@ -34,85 +38,95 @@ func (p *Ping) httping(ip *net.IPAddr) (int, time.Duration) {
},
}
// 先访问一次获得 HTTP 状态码 及 Cloudflare Colo
// 先访问一次获得 HTTP 状态码 及 地区码
var colo string
{
requ, err := http.NewRequest(http.MethodHead, URL, nil)
request, err := http.NewRequest(http.MethodHead, URL, nil)
if err != nil {
return 0, 0
if utils.Debug { // 调试模式下,输出更多信息
utils.Red.Printf("[调试] IP: %s, 延迟测速请求创建失败,错误信息: %v, 测速地址: %s\n", ip.String(), err, URL)
}
return 0, 0, ""
}
requ.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36")
resp, err := hc.Do(requ)
request.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36")
response, err := hc.Do(request)
if err != nil {
return 0, 0
if utils.Debug { // 调试模式下,输出更多信息
utils.Red.Printf("[调试] IP: %s, 延迟测速失败,错误信息: %v, 测速地址: %s\n", ip.String(), err, URL)
}
return 0, 0, ""
}
defer resp.Body.Close()
defer response.Body.Close()
//fmt.Println("IP:", ip, "StatusCode:", resp.StatusCode, resp.Request.URL)
//fmt.Println("IP:", ip, "StatusCode:", response.StatusCode, response.Request.URL)
// 如果未指定的 HTTP 状态码,或指定的状态码不合规,则默认只认为 200、301、302 才算 HTTPing 通过
if HttpingStatusCode == 0 || HttpingStatusCode < 100 && HttpingStatusCode > 599 {
if resp.StatusCode != 200 && resp.StatusCode != 301 && resp.StatusCode != 302 {
return 0, 0
if response.StatusCode != 200 && response.StatusCode != 301 && response.StatusCode != 302 {
if utils.Debug { // 调试模式下,输出更多信息
utils.Red.Printf("[调试] IP: %s, 延迟测速终止HTTP 状态码: %d, 测速地址: %s\n", ip.String(), response.StatusCode, URL)
}
return 0, 0, ""
}
} else {
if resp.StatusCode != HttpingStatusCode {
return 0, 0
}
}
io.Copy(io.Discard, resp.Body)
// 只有指定了地区才匹配机场三字码
if HttpingCFColo != "" {
// 通过头部 Server 值判断是 Cloudflare 还是 AWS CloudFront 并设置 cfRay 为各自的机场三字码完整内容
cfRay := func() string {
if resp.Header.Get("Server") == "cloudflare" {
return resp.Header.Get("CF-RAY") // 示例 cf-ray: 7bd32409eda7b020-SJC
if response.StatusCode != HttpingStatusCode {
if utils.Debug { // 调试模式下,输出更多信息
utils.Red.Printf("[调试] IP: %s, 延迟测速终止HTTP 状态码: %d, 指定的 HTTP 状态码 %d, 测速地址: %s\n", ip.String(), response.StatusCode, HttpingStatusCode, URL)
}
return resp.Header.Get("x-amz-cf-pop") // 示例 X-Amz-Cf-Pop: SIN52-P1
}()
colo := p.getColo(cfRay)
if colo == "" { // 没有匹配到三字码或不符合指定地区则直接结束该 IP 测试
return 0, 0
return 0, 0, ""
}
}
io.Copy(io.Discard, response.Body)
// 通过头部参数获取地区码
colo = getHeaderColo(response.Header)
// 只有指定了地区才匹配机场地区码
if HttpingCFColo != "" {
// 判断是否匹配指定的地区码
colo = p.filterColo(colo)
if colo == "" { // 没有匹配到地区码或不符合指定地区则直接结束该 IP 测试
if utils.Debug { // 调试模式下,输出更多信息
utils.Red.Printf("[调试] IP: %s, 地区码不匹配: %s\n", ip.String(), colo)
}
return 0, 0, ""
}
}
}
// 循环测速计算延迟
success := 0
var delay time.Duration
for i := 0; i < PingTimes; i++ {
requ, err := http.NewRequest(http.MethodHead, URL, nil)
request, err := http.NewRequest(http.MethodHead, URL, nil)
if err != nil {
log.Fatal("意外的错误,情报告:", err)
return 0, 0
return 0, 0, ""
}
requ.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36")
request.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36")
if i == PingTimes-1 {
requ.Header.Set("Connection", "close")
request.Header.Set("Connection", "close")
}
startTime := time.Now()
resp, err := hc.Do(requ)
response, err := hc.Do(request)
if err != nil {
continue
}
success++
io.Copy(io.Discard, resp.Body)
_ = resp.Body.Close()
io.Copy(io.Discard, response.Body)
_ = response.Body.Close()
duration := time.Since(startTime)
delay += duration
}
return success, delay
return success, delay, colo
}
func MapColoMap() *sync.Map {
if HttpingCFColo == "" {
return nil
}
// 将参数指定的地区三字码转为大写并格式化
// 将 -cfcolo 参数指定的地区地区码转为大写并格式化
colos := strings.Split(strings.ToUpper(HttpingCFColo), ",")
colomap := &sync.Map{}
for _, colo := range colos {
@@ -121,21 +135,74 @@ func MapColoMap() *sync.Map {
return colomap
}
func (p *Ping) getColo(b string) string {
if b == "" {
return ""
// 从响应头中获取 地区码 值
func getHeaderColo(header http.Header) (colo string) {
if header.Get("server") != "" {
// 如果是 Cloudflare CDN
// server: cloudflare
// cf-ray: 7bd32409eda7b020-SJC
if header.Get("server") == "cloudflare" {
if colo = header.Get("cf-ray"); colo != "" {
return RegexpColoIATACode.FindString(colo)
}
}
// 如果是 CDN77 CDN测试地址 https://www.cdn77.com
// server: CDN77-Turbo
// x-77-pop: losangelesUSCA // 美国的会显示为 USCA 不知道什么情况,暂时没做兼容,只提取 US
// x-77-pop: frankfurtDE
// x-77-pop: amsterdamNL
// x-77-pop: singaporeSG
if header.Get("server") == "CDN77-Turbo" {
if colo = header.Get("x-77-pop"); colo != "" {
return RegexpColoCountryCode.FindString(colo)
}
}
// 如果是 Bunny CDN测试地址 https://bunny.net
// server: BunnyCDN-TW1-1121
if colo = header.Get("server"); strings.Contains(colo, "BunnyCDN-") {
return RegexpColoCountryCode.FindString(strings.TrimPrefix(colo, "BunnyCDN-")) // 去掉 BunnyCDN- 前缀再去匹配
}
}
// 正则匹配并返回 机场三字码
out := OutRegexp.FindString(b)
if HttpingCFColomap == nil {
return out
// 如果是 AWS CloudFront CDN测试地址 https://d7uri8nf7uskq.cloudfront.net/tools/list-cloudfront-ips
// x-amz-cf-pop: SIN52-P1
if colo = header.Get("x-amz-cf-pop"); colo != "" {
return RegexpColoIATACode.FindString(colo)
}
// 匹配 机场三字码 是否为指定的地区
_, ok := HttpingCFColomap.Load(out)
if ok {
return out
// 如果是 Fastly CDN测试地址 https://fastly.jsdelivr.net/gh/XIU2/CloudflareSpeedTest@master/go.mod
// x-served-by: cache-qpg1275-QPG
// x-served-by: cache-fra-etou8220141-FRA, cache-hhr-khhr2060043-HHR最后一个为实际位置
if colo = header.Get("x-served-by"); colo != "" {
if matches := RegexpColoIATACode.FindAllString(colo, -1); len(matches) > 0 {
return matches[len(matches)-1] // 因为 Fastly 的 x-served-by 可能包含多个地区码,所以只取最后一个
}
}
// Gcore CDN 的头部信息(注意均为城市代码而非国家代码),测试地址 https://assets.gcore.pro/assets/icons/shield-lock.svg
// x-id-fe: fr5-hw-edge-gc17
// x-shard: fr5-shard0-default
// x-id: fr5-hw-edge-gc28
if colo = header.Get("x-id-fe"); colo != "" {
if colo = RegexpColoGcore.FindString(colo); colo != "" {
return strings.ToUpper(colo) // 将小写的地区码转换为大写
}
}
// 如果没有获取到头部信息,说明不是支持的 CDN则直接返回空字符串
return ""
}
// 处理地区码
func (p *Ping) filterColo(colo string) string {
if colo == "" {
return ""
}
// 如果没有指定 -cfcolo 参数,则直接返回
if HttpingCFColomap == nil {
return colo
}
// 匹配 机场地区码 是否为指定的地区
_, ok := HttpingCFColomap.Load(colo)
if ok {
return colo
}
return ""
}

View File

@@ -64,9 +64,9 @@ func (p *Ping) Run() utils.PingDelaySet {
return p.csv
}
if Httping {
fmt.Printf("开始延迟测速模式HTTP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
utils.Cyan.Printf("开始延迟测速模式HTTP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
} else {
fmt.Printf("开始延迟测速模式TCP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
utils.Cyan.Printf("开始延迟测速模式TCP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
}
for _, ip := range p.ips {
p.wg.Add(1)
@@ -104,11 +104,12 @@ func (p *Ping) tcping(ip *net.IPAddr) (bool, time.Duration) {
}
// pingReceived pingTotalTime
func (p *Ping) checkConnection(ip *net.IPAddr) (recv int, totalDelay time.Duration) {
func (p *Ping) checkConnection(ip *net.IPAddr) (recv int, totalDelay time.Duration, colo string) {
if Httping {
recv, totalDelay = p.httping(ip)
recv, totalDelay, colo = p.httping(ip)
return
}
colo = "" // TCPing 不获取 colo
for i := 0; i < PingTimes; i++ {
if ok, delay := p.tcping(ip); ok {
recv++
@@ -128,7 +129,7 @@ func (p *Ping) appendIPData(data *utils.PingData) {
// handle tcping
func (p *Ping) tcpingHandler(ip *net.IPAddr) {
recv, totalDlay := p.checkConnection(ip)
recv, totalDlay, colo := p.checkConnection(ip)
nowAble := len(p.csv)
if recv != 0 {
nowAble++
@@ -142,6 +143,7 @@ func (p *Ping) tcpingHandler(ip *net.IPAddr) {
Sended: PingTimes,
Received: recv,
Delay: totalDlay / time.Duration(recv),
Colo: colo,
}
p.appendIPData(data)
}

16
utils/color.go Normal file
View File

@@ -0,0 +1,16 @@
package utils
import (
"github.com/fatih/color"
)
// 由专业的库来处理多平台的颜色输出效果
var (
Red = color.New(color.FgRed) // 红色 31
Green = color.New(color.FgGreen) // 绿色 32
Yellow = color.New(color.FgYellow) // 黄色 33
Blue = color.New(color.FgBlue, color.Bold) // 蓝色 34
Magenta = color.New(color.FgMagenta) // 紫红色 35
Cyan = color.New(color.FgHiCyan, color.Bold) // 青色 36
White = color.New(color.FgWhite) // 白色 37
)

View File

@@ -23,6 +23,7 @@ var (
InputMaxLossRate = maxLossRate
Output = defaultOutput
PrintNum = 10
Debug = false // 是否开启调试模式
)
// 是否打印测试结果
@@ -40,6 +41,7 @@ type PingData struct {
Sended int
Received int
Delay time.Duration
Colo string
}
type CloudflareIPData struct {
@@ -58,13 +60,19 @@ func (cf *CloudflareIPData) getLossRate() float32 {
}
func (cf *CloudflareIPData) toString() []string {
result := make([]string, 6)
result := make([]string, 7)
result[0] = cf.IP.String()
result[1] = strconv.Itoa(cf.Sended)
result[2] = strconv.Itoa(cf.Received)
result[3] = strconv.FormatFloat(float64(cf.getLossRate()), 'f', 2, 32)
result[4] = strconv.FormatFloat(cf.Delay.Seconds()*1000, 'f', 2, 32)
result[5] = strconv.FormatFloat(cf.DownloadSpeed/1024/1024, 'f', 2, 32)
// 如果 Colo 为空,则使用 "N/A" 表示
if cf.Colo == "" {
result[6] = "N/A"
} else {
result[6] = cf.Colo
}
return result
}
@@ -79,7 +87,7 @@ func ExportCsv(data []CloudflareIPData) {
}
defer fp.Close()
w := csv.NewWriter(fp) //创建一个新的写入文件流
_ = w.Write([]string{"IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)"})
_ = w.Write([]string{"IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度(MB/s)", "地区码"})
_ = w.WriteAll(convertToString(data))
w.Flush()
}
@@ -168,18 +176,18 @@ func (s DownloadSpeedSet) Print() {
if len(dateString) < PrintNum { // 如果IP数组长度(IP数量) 小于 打印次数则次数改为IP数量
PrintNum = len(dateString)
}
headFormat := "%-16s%-5s%-5s%-5s%-6s%-11s\n"
dataFormat := "%-18s%-8s%-8s%-8s%-10s%-15s\n"
headFormat := "%-16s%-5s%-5s%-5s%-6s%-12s%-5s\n"
dataFormat := "%-18s%-8s%-8s%-8s%-10s%-16s%-8s\n"
for i := 0; i < PrintNum; i++ { // 如果要输出的 IP 中包含 IPv6那么就需要调整一下间隔
if len(dateString[i][0]) > 15 {
headFormat = "%-40s%-5s%-5s%-5s%-6s%-11s\n"
dataFormat = "%-42s%-8s%-8s%-8s%-10s%-15s\n"
headFormat = "%-40s%-5s%-5s%-5s%-6s%-12s%-5s\n"
dataFormat = "%-42s%-8s%-8s%-8s%-10s%-16s%-8s\n"
break
}
}
fmt.Printf(headFormat, "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)")
Cyan.Printf(headFormat, "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度(MB/s)", "地区码")
for i := 0; i < PrintNum; i++ {
fmt.Printf(dataFormat, dateString[i][0], dateString[i][1], dateString[i][2], dateString[i][3], dateString[i][4], dateString[i][5])
fmt.Printf(dataFormat, dateString[i][0], dateString[i][1], dateString[i][2], dateString[i][3], dateString[i][4], dateString[i][5], dateString[i][6])
}
if !noOutput() {
fmt.Printf("\n完整测速结果已写入 %v 文件,可使用记事本/表格软件查看。\n", Output)