99 Commits

Author SHA1 Message Date
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
xiu2
2cfc1e6b69 README.md 2023-11-25 15:18:27 +08:00
xiu2
a4b39ecc23 调整 测速过程中的输出内容 2023-11-25 15:18:18 +08:00
xiu2
49992a763e README.md 2023-09-24 20:28:43 +08:00
xiu2
ffc0dafbae README.md 2023-09-24 19:58:59 +08:00
xiu2
4621c56370 README.md 2023-07-05 14:21:47 +08:00
xiu2
2d400783c9 README.md 2023-07-03 21:33:01 +08:00
xiu2
133924d169 README.md 2023-06-08 10:58:39 +08:00
xiu2
bef4476b25 README.md 2023-06-06 19:44:36 +08:00
xiu2
6c698a815d README.md 2023-06-06 19:43:07 +08:00
xiu2
5f9d28e4a0 README.md 2023-05-31 17:12:12 +08:00
xiu2
4222b6ce95 README.md 2023-05-31 17:09:09 +08:00
xiu2
7c36abc12f 新增 [丢包几率上限] 参数 2023-05-31 16:46:16 +08:00
xiu2
eae7d2eead 优化 当延迟上下限条件为默认值时不进行过滤 2023-05-31 16:46:08 +08:00
xiu2
b6f3ddcd4c README.md 2023-05-15 12:27:28 +08:00
xiu2
c6d49bc7cb README.md 2023-05-11 18:44:02 +08:00
xiu2
a07af2f58b 修复 测速大量子网掩码 /32 /128 的 IP 时小概率出现重复 IP 的问题 2023-04-29 23:32:29 +08:00
xiu2
9f000aa23a 优化 解析 IP 段数据时会去除首尾的空白字符并跳过空行 2023-04-28 14:52:59 +08:00
xiu2
1800c2e89e README.md 2023-04-25 12:36:49 +08:00
xiu2
39d1687875 README.md 2023-04-25 11:55:35 +08:00
xiu2
24a162ac46 README.md 2023-04-25 11:28:07 +08:00
xiu2
3125b49b63 README.md 2023-04-25 11:23:21 +08:00
xiu2
729631deef 调整 -cfcolo 参数支持小写 2023-04-25 11:18:49 +08:00
Mac_Zhou
fe0721f077 Add support for CloudFront x-amz-cf-pop (#376)
1. 增加了对CloudFront筛选节点
2. 节点地区码使用正则表达式
2023-04-25 11:00:46 +08:00
xiu2
201619ecf7 README.md 2023-04-24 10:36:48 +08:00
xiu2
12effc301f Update issue templates 2023-04-04 11:02:05 +08:00
xiu2
fede8a04e6 Update issue templates 2023-04-04 10:57:27 +08:00
xiu2
b63f368837 将 module 名改为 github.com/XIU2/CloudflareSpeedTest 2023-03-27 11:49:59 +08:00
xiu2
c9a8c2b8cf README.md 2023-03-16 19:20:16 +08:00
xiu2
e80d7fff50 README.md 2023-03-03 20:05:59 +08:00
xiu2
f61a94886b Update issue templates 2023-03-02 21:00:00 +08:00
xiu2
f3f2bafbe7 Update issue templates 2023-03-02 20:22:27 +08:00
xiu2
5cf3b4bb42 Update issue templates 2023-03-02 19:35:02 +08:00
xiu2
6667e82c84 Update issue templates 2023-03-02 16:05:06 +08:00
xiu2
af4e8cf8b2 Update issue templates 2023-03-02 16:03:12 +08:00
XIU2
f2ec0a447c Update issue templates 2023-03-02 15:55:20 +08:00
xiu2
45b604103e README.md 2023-03-01 10:42:41 +08:00
xiu2
05ba005960 README.md 2023-02-23 12:44:29 +08:00
xiu2
a0b194f1d0 README.md 2023-02-23 12:43:28 +08:00
xiu2
7e21b2f46b README.md 2023-02-16 12:05:33 +08:00
xiu2
efafc38db8 README.md 2023-02-13 20:26:00 +08:00
xiu2
b14b3657b7 README.md 2023-02-13 09:51:13 +08:00
xiu2
2634fe43ff README.md 2023-02-13 09:45:12 +08:00
xiu2
b26fa89447 README.md 2023-02-12 19:15:27 +08:00
xiu2
a6b08bb4b8 README.md 2023-02-12 18:47:35 +08:00
xiu2
bd6fbb9f1f 修复 使用文件大小未知的下载测速地址时太快下载完成会导致测速结果异常的问题(如 speed.cloudflare.com 这种实时生成的) 2023-02-12 17:57:53 +08:00
xiu2
465a83462b README.md 2023-02-12 16:53:35 +08:00
20 changed files with 1113 additions and 328 deletions

34
.github/ISSUE_TEMPLATE/01-bugReport.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: 反馈问题 (Bug report)
description: 软件报错等异常情况,或遇到预期之外的问题...
labels: 反馈问题
body:
- type: markdown
attributes:
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)的),请勿重复发起!
> [!NOTE]
> 注意!如果你反馈的问题和 CFST **软件本身功能无关**(如关于 Cloudflare CDN 的网络问题),请**前往讨论区** (💬 [**Discussions**](https://github.com/XIU2/CloudflareSpeedTest/discussions)) 发帖交流!(不合适的 Issues 会被转过去
****
- type: textarea
id: description
attributes:
label: 问题描述
description: 必填,最好写上 复现问题 的步骤,越详细越好,特别是一些复杂的问题
placeholder: 请输入...
validations:
required: true
- type: input
id: version
attributes:
label: 软件版本
description: 必填,可通过运行软件来获取版本信息(例如 v2.2.2
placeholder: 请输入...
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: 附加截图
description: 可选,也可以是一些错误代码
placeholder: 可在此粘贴图片,或点击下方 [Attach files by dragging & dropping, selecting or pasting them.] 文字来选择图片...

View File

@@ -0,0 +1,31 @@
name: 功能建议 (Feature request)
description: 有什么建议,或希望添加、完善某个功能...
labels: 功能建议
body:
- type: markdown
attributes:
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)的),请勿重复发起!
> [!NOTE]
> 注意!如果你提的功能建议和 CFST **软件本身功能无关**,请**前往讨论区** (💬 [**Discussions**](https://github.com/XIU2/CloudflareSpeedTest/discussions)) 发帖交流!
> [!TIP]
> 另外,不接受**个性化**的小众功能请求(即 **很少人** 或 **只有你自己** 才会用到的功能)
****
- type: textarea
id: description
attributes:
label: 功能需求
description: 必填,你要什么样的功能?
placeholder: 请输入...
validations:
required: true
- type: textarea
id: anticipation
attributes:
label: 预期目标
description: 必填,你希望该功能具体是什么样子的?如果能提供 示例/截图/代码 就更好了
placeholder: 请输入...
validations:
required: true

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

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

545
README.md
View File

@@ -7,24 +7,41 @@
[![GitHub Fork](https://img.shields.io/github/forks/XIU2/CloudflareSpeedTest.svg?style=flat-square&label=Fork&color=00ADD8&logo=github)](https://github.com/XIU2/CloudflareSpeedTest/)
国外很多网站都在使用 Cloudflare CDN但分配给中国内地访客的 IP 并不友好(延迟高、丢包多、速度慢)。
虽然 Cloudflare 公开了所有 [IP 段](https://www.cloudflare.com/ips/) ,但想要在这么多 IP 中找到适合自己的,怕是要累死,于是就有了这个软件。
虽然 Cloudflare 公开了所有 [IP 段](https://www.cloudflare.com/zh-cn/ips/) ,但想要在这么多 IP 中找到适合自己的,怕是要累死,于是就有了这个软件。
**「自选优选 IP」测试 Cloudflare CDN 延迟和速度,获取最快 IP (IPv4+IPv6)**!好用的话**点个`⭐`鼓励一下叭~**
> _分享我其他开源项目[**TrackersList.com** - 全网热门 BT Tracker 列表!有效提高 BT 下载速度~](https://github.com/XIU2/TrackersListCollection) <img src="https://img.shields.io/github/stars/XIU2/TrackersListCollection.svg?style=flat-square&label=Star&color=4285dd&logo=github" height="16px" />_
> _[**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" />_
> _[**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/issues/180)、[Gcore](https://github.com/XIU2/CloudflareSpeedTest/issues/267) CDN但下载测速需自行寻找地址
> 本项目也支持对**其他 CDN / 网站 IP** 延迟测速(如:[CloudFront](https://github.com/XIU2/CloudflareSpeedTest/discussions/304)、[Gcore](https://github.com/XIU2/CloudflareSpeedTest/discussions/303) CDN但下载测速需自行寻找地址
> 对于**代理套 Cloudflare CDN** 的用户,须知这应为**备用方案**,而不应该是**唯一方案**,请勿过度依赖 [#217](https://github.com/XIU2/CloudflareSpeedTest/issues/217) [#188](https://github.com/XIU2/CloudflareSpeedTest/issues/188)
> [!IMPORTANT]
> Cloudflare CDN 已**明文禁止代理**方式使用,对于**代理套 CDN** 的自行承担风险,请勿过度依赖 [#382](https://github.com/XIU2/CloudflareSpeedTest/discussions/382) [#383](https://github.com/XIU2/CloudflareSpeedTest/discussions/383)
****
## \# 快速使用
### 下载运行
1. 下载编译好的可执行文件 [蓝奏云](https://pan.lanzouv.com/b0742hkxe) / [Github](https://github.com/XIU2/CloudflareSpeedTest/releases) 并解压。
2. 双击运行 `CloudflareST.exe` 文件Windows 系统),等待测速完成...
1. 下载编译好的可执行文件 [Github Releases](https://github.com/XIU2/CloudflareSpeedTest/releases) / [蓝奏云](https://pan.lanpw.com/b0742hkxe) 并解压。
2. 双击运行 `cfst.exe` 文件Windows 系统),等待测速完成...
<details>
<summary><code><strong>「 点击查看 Windows 系统下其他安装方式」</strong></code></summary>
****
通过scoop安装:
```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>
@@ -35,59 +52,65 @@
``` yaml
# 如果是第一次使用,则建议创建新文件夹(后续更新时,跳过该步骤)
mkdir CloudflareST
mkdir cfst
# 进入文件夹(后续更新,只需要从这里重复下面的下载、解压命令即可)
cd CloudflareST
cd cfst
# 下载 CloudflareST 压缩包(自行根据需求替换 URL 中 [版本号] 和 [文件名]
wget -N https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.2.1/CloudflareST_linux_amd64.tar.gz
# 如果你是在国内服务器上下载,那么请使用下面这几个镜像加速:
# wget -N https://download.fastgit.org/XIU2/CloudflareSpeedTest/releases/download/v2.2.1/CloudflareST_linux_amd64.tar.gz
# wget -N https://ghproxy.com/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.2.1/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.2/cfst_linux_amd64.tar.gz
# 如果你是在国内网络环境中下载,那么请使用下面这几个镜像加速之一
# wget -N https://ghfast.top/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.2/cfst_linux_arm64.tar.gz
# wget -N https://wget.la/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.2/cfst_linux_arm64.tar.gz
# wget -N https://ghproxy.net/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.2/cfst_linux_arm64.tar.gz
# wget -N https://gh-proxy.com/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.2/cfst_linux_arm64.tar.gz
# wget -N https://hk.gh-proxy.com/https://github.com/XIU2/CloudflareSpeedTest/releases/download/v2.3.2/cfst_linux_arm64.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 -dd -tll 90
```
> 如果平**均延迟非常低**(如 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/issues/151)**_
> _在**手机**上独立运行 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)**_
> [!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所以每次的测速结果都不可能相同这是正常的
@@ -97,19 +120,21 @@ IP 地址 已发送 已接收 丢包率 平均延迟 下载速度
# 软件在 默认参数 下的整个流程大概步骤:
# 1. 延迟测速(默认 TCPing 模式HTTPing 模式需要手动加上参数)
# 2. 延迟排序(延迟从低到高排序,不同丢包率会分开独立排序,因此可能会有一些延迟低但丢包的 IP 排到后面)
# 2. 延迟排序(延迟 从低到高 排序并按条件过滤,不同丢包率会分开排序,因此可能会有一些延迟低但丢包的 IP 排到后面)
# 3. 下载测速(从延迟最低的 IP 开始依次下载测速,默认测够 10 个就会停止)
# 4. 速度排序(速度从高到低排序)
# 5. 输出结果(可依靠参数控制是否输出到命令行(-p 0)/文件(-o "")
# 5. 输出结果(通过参数控制是否输出到命令行(-p 0)或输出到文件(-o "")
# 注意:输出的结果文件 result.csv 通过微软 Excel 表格打开会中文乱码,这是正常的,其他表格软件/记事本都显示正常
```
测速结果第一行就是**既下载速度最快、又平均延迟最低的最快 IP**至于拿来干嘛?取决于你~
测速结果第一行就是**既下载速度最快、又平均延迟最低的最快 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
```
> _大家可以按自己需求对完整结果**进一步筛选处理**,或者去看一看进阶使用**指定过滤条件**_
@@ -119,18 +144,18 @@ IP 地址, 已发送, 已接收, 丢包率, 平均延迟, 下载速度 (MB/s)
直接运行使用的是默认参数,如果想要测速结果更全面、更符合自己的要求,可以自定义参数。
``` cmd
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
参数:
-n 200
延迟测速线程;越多延迟测速越快,性能弱的设备 (如路由器) 请勿太高;(默认 200 最多 1000)
-t 4
延迟测速次数;单个 IP 延迟测速次数,为 1 时将过滤丢包的IP(默认 4 次)
延迟测速次数;单个 IP 延迟测速次数;(默认 4 次)
-dn 10
下载测速数量;延迟测速并排序后,从最低延迟起下载测速的数量;(默认 10 个)
-dt 10
@@ -139,18 +164,29 @@ 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
匹配指定地区;地区名为当地机场三字码,英文逗号分隔,仅 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)
平均延迟上限;只输出低于指定平均延迟的 IP各上下限条件可搭配使用(默认 9999 ms)
-tll 40
平均延迟下限;只输出高于指定平均延迟的 IP,可与其他上限/下限搭配(默认 0 ms)
平均延迟下限;只输出高于指定平均延迟的 IP(默认 0 ms)
-tlr 0.2
丢包几率上限;只输出低于/等于指定丢包率的 IP范围 0.00~1.000 过滤掉任何丢包的 IP(默认 1.00)
-sl 5
下载速度下限;只输出高于指定下载速度的 IP凑够指定数量 [-dn] 才会停止测速;(默认 0.00 MB/s)
@@ -168,22 +204,104 @@ https://github.com/XIU2/CloudflareSpeedTest
-allip
测速全部的IP对 IP 段中的每个 IP (仅支持 IPv4) 进行测速;(默认 每个 /24 段随机测速一个 IP)
-debug
调试输出模式;会在一些非预期情况下输出更多日志以便判断原因;(默认 关闭)
目前该功能仅针对 HTTPing 延迟测速过程 及 下载测速过程,当过程中因为各种原因导致当前 IP 测速中断都会输出错误原因
例如HTTPing 延迟测速过程中,因为 HTTP 状态码不符合或测速地址有问题或超时等原因而终止测速
例如下载测速过程中因为下载测速地址有问题被阻断、403状态码、超时等原因而终止测速
-v
打印程序版本 + 检查版本更新
-h
打印帮助说明
```
### 界面解释
为了避免大家对测速过程中的**输出内容产生误解(可用、队列等数字,下载测速一半就"中断"?下载测速"卡住"不动?)**,我特意解释下。
<details>
<summary><code><strong>「 点击展开 查看内容 」</strong></code></summary>
****
> 该示例把常用参数都给加上了,即为:`-tll 40 -tl 150 -sl 1 -dn 5`,最后输出结果如下:
```python
# XIU2/CloudflareSpeedTest vX.X.X
开始延迟测速模式TCP, 端口443, 范围40 ~ 150 ms, 丢包1.00)
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 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 退出。
```
****
> 刚接触 CFST 的人,可能会迷惑**明明延迟测速可用 IP 有 30 个,怎么最后只剩下 3 个了呢?**
> 下载测速里的队列又是什么意思?难道我下载测速还要排队?
CFST 会先延迟测速,在这过程中进度条右侧会实时显示可用 IP 数量(`可用: 30`),但注意该可用数量指的是**测试通过没有超时的 IP 数量**,和延迟上下限、丢包条件无关。当延迟测速完成后,因为还指定了**延迟上下限、丢包**的条件,所以按照条件过滤后只剩下 `10` 个了(也就是等待下载测速的 `队列10`)。
即以上示例中,`321` 个 IP 延迟测速完成后,只有 `30` 个 IP 测试通过没有超时,然后根据延迟上下限范围:`40 ~ 150 ms` 及丢包上限条件过滤后,只剩下 `10` 个满足要求的 IP 了。如果你 `-dd` 禁用了下载测速,那么就会直接输出这 `10` 个 IP 了。当然该示例并未禁用,因此接下来软件会继续对这 `10` 个 IP 进行下载测速(`队列10`)。
> 因为下载测速是单线程一个个 IP 挨着排队测速的,因此等待下载测速的 IP 数量才会叫做 `队列`。
****
> 你可能注意到了,**明明指定了要找到 5 个满足下载速度条件的 IP怎么才 3 个就 “中断” 了呢?**
下载测速进度条中的 `3 / 5`,前者指的是找到了 `3` 个满足下载速度下限条件的 IP即下载速度高于 `1 MB/s` ),后者 `5` 指的是你要求找到 `5` 个满足下载速度下限条件的 IP`-dn 5`)。
> 另外,提醒一下,如果你指定的 `-dn` 大于下载测速队列,比如你延迟测速后只剩下 `4` 个 IP 了,那么下载测速进度条中后面的数字就会和下载测速队列一样都是 `4` 个,而非你 `-dn` 指定的 `5` 个了。
软件在测速完这 `10` 个 IP 后,只找到了 `3` 个下载速度高于 `1 MB/s` 的 IP剩下的 `7` 个 IP 都是 “不及格” 的。
因此,这不是 `“每次测速都不到 5 就中断了”`,而是所有 IP 都下载测速完了,但却只找到了 `3` 个满足条件的。
****
还有一种情况,那就是当可用 IP 很多时(几百几千),你还设置了下载速度条件,那么可能就会遇到:**怎么下载测速进度条老是卡在 `X / 5` 了呢?**
这其实并不是卡住了,而是只有当找到一个满足条件的 IP 时,进度条才会 +1因此如果一直找不到那么 CFST 就会一直下载测速下去,因此在表现为进度条卡住不动,但这也是在提醒你:你设置的下载速度条件对你来说已经高于实际了,你需要适当调低预期。
****
如果不想遇到这种全部测速一遍都没几个满足条件的情况,那么就要**调低下载速度上限参数 `-sl`**,或者移除。
因为只要指定了 `-sl` 参数,那么只要没有凑够 `-dn` 的数量(默认 10 个),就会一直测速下去,直到凑够或全部测速完。移除 `-sl` 并添加 `-dn 20` 参数,这样就是只测速延迟最低的前 20 个 IP测速完就停止节省时间。
****
另外,如果全部队列 IP 都测速完了,但一个满足下载速度条件的 IP 都没有,你可能需要调低预期的下载测速下限条件,但你需要知道当前的大概测速速度都在什么范围,那么你就可以加上 `-debug` 参数开启调试模式,这样再遇到这种情况时,就会**忽略条件返回所有测速数据**,你就能看到这些 IP 的下载速度都有多少,心里也就有数了,然后**适当调低 `-sl` 再试试**。
同样,延迟测速方面,`可用: 30`、`队列10` 这两个数值也可以让你清楚,你设置的延迟条件对你来说是否过于苛刻。如果可用 IP 一大堆,但条件过滤后只剩下 2、3 个,那不用说就知道需要**调低预期的延迟/丢包条件**了。
这两个机制,一个是告诉你**延迟丢包条件**是否合适的,一个是告诉你**下载速度条件**是否合适的。
</details>
****
### 使用示例
Windows 要指定参数需要在 CMD 中运行,或者把参数添加到快捷方式目标中。
> **注意**:各参数均有**默认值**,使用默认值的参数是可以省略的(**按需选择**),参数**不分前后顺序**。
> **提示**Linux 系统只需要把下面命令中的 `CloudflareST.exe` 改为 `./CloudflareST` 即可。
> [!TIP]
> - 各参数均有**默认值**,使用默认值的参数是可以省略的(**按需选择**),参数**不分前后顺序**。
> - Windows **PowerShell** 只需把下面命令中的 `cfst.exe` 改为 `.\cfst.exe` 即可。
> - Linux 系统只需要把下面命令中的 `cfst.exe` 改为 `./cfst` 即可。
****
#### \# CMD 带参数运行 CloudflareST
#### \# CMD 带参数运行
对命令行程序不熟悉的人,可能不知道该如何带参数运行,我就简单说一下。
@@ -192,26 +310,28 @@ 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 -tll 50 -tl 200`即可运行
**方式 二**
1. 打开 CloudflareST 程序所在目录
1. 打开 CFST 程序所在目录
2. 直接在文件夹地址栏中全选并输入 `cmd` 回车来打开 CMD 窗口,此时默认就位于当前目录下
4. 输入带参数的命令,如:`CloudflareST.exe -tll 50 -tl 200`即可运行
4. 输入带参数的命令,如:`cfst.exe -tll 50 -tl 200`即可运行
> 当然你也可以随便打开一个 CMD 窗口,然后输入如 `cd /d "D:\Program Files\CloudflareST"` 来进入程序目录
> 当然你也可以随便打开一个 CMD 窗口,然后输入如 `cd /d "D:\Program Files\cfst"` 来进入程序目录
> **提示**:如果用的是 **PowerShell** 只需把命令中的 `cfst.exe` 改为 `.\cfst.exe` 即可。
</details>
****
#### \# Windows 快捷方式带参数运行 CloudflareST
#### \# Windows 快捷方式带参数运行
如果不经常修改运行参数(比如平时都是直接双击运行)的人,建议使用快捷方式,更方便点。
@@ -220,14 +340,14 @@ Windows 要指定参数需要在 CMD 中运行,或者把参数添加到快捷
****
右键 `CloudflareST.exe` 文件 - **\[创建快捷方式\]**,然后右键该快捷方式 - **\[属性\]**,修改其**目标**
右键 `cfst.exe` 文件 - **\[创建快捷方式\]**,然后右键该快捷方式 - **\[属性\]**,修改其**目标**
``` bash
# 如果要不输出结果文件,那么请加上 -o " ",引号里的是空格(没有空格会导致该参数被省略)。
D:\ABC\CloudflareST\CloudflareST.exe -n 500 -t 4 -dn 20 -dt 5 -o " "
D:\ABC\cfst\cfst.exe -n 500 -t 4 -dn 20 -dt 5 -o " "
# 如果文件路径包含引号,则需要把启动参数放在引号外面,记得引号和 - 之间有空格。
"D:\Program Files\CloudflareST\CloudflareST.exe" -n 500 -t 4 -dn 20 -dt 5 -o " "
"D:\Program Files\cfst\cfst.exe" -n 500 -t 4 -dn 20 -dt 5 -o " "
# 注意!快捷方式 - 起始位置 不能是空的,否则就会因为绝对路径而找不到 ip.txt 文件
```
@@ -243,14 +363,15 @@ 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
# 指定自带的 IPv4 数据文件可测速这些 IPv4 地址-f 默认值就是 ip.txt所以该参数可省略
cfst.exe -f ip.txt
# 测速 IPv6 时,需要指定 IPv6 数据文件v2.1.0 版本后支持 IPv4+IPv6 混合测速并移除了 -ipv6 参数)
CloudflareST.exe -f ipv6.txt
# 指定自带的 IPv6 数据文件可测速这些 IPv6 地址
# 另外v2.1.0 版本后支持 IPv4+IPv6 混合测速并移除了 -ipv6 参数,因此一个文件内可以同时包含 IPv4+IPv6 地址
cfst.exe -f ipv6.txt
# 当然你也可以将 IPv4 IPv6 混合在一起测速,也可以直接通过参数指定要测速的 IP
CloudflareST.exe -ip 1.1.1.1,2606:4700::/32
# 也可以直接通过参数指定要测速的 IP
cfst.exe -ip 1.1.1.1,2606:4700::/32
```
> 测速 IPv6 时,可能会注意到每次测速数量都不一样,了解原因: [#120](https://github.com/XIU2/CloudflareSpeedTest/issues/120)
@@ -272,44 +393,75 @@ TCP 协议耗时更短、消耗资源更少,超时时间为 1 秒,该协议
HTTP 协议适用于快速测试某域名指向某 IP 时是否可以访问,超时时间为 2 秒。
同一个 IP各协议去 Ping 得到的延迟一般为:**ICMP < TCP < HTTP**,越靠右对丢包等网络波动越敏感。
> 注意HTTPing 本质上也算一种**网络扫描**行为,因此如果你在服务器上面运行,需要**降低并发**(`-n`),否则可能会被一些严格的商家暂停服务。
> 注意HTTPing 本质上也算一种**网络扫描**行为,因此如果你在服务器上面运行,需要**降低并发**(`-n`),否则可能会被一些严格的商家暂停服务。如果你遇到 HTTPing 首次测速可用 IP 数量正常,后续测速越来越少甚至直接为 0但停一段时间后又恢复了的情况那么也可能是被 运营商、Cloudflare CDN 认为你在网络扫描而**触发临时限制机制**,因此才会过一会儿就恢复了,建议**降低并发**(`-n`)减少这种情况的发生。
> 另外,本软件 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 的)
CloudflareST.exe -httping -tp 80 -url http://xxx/xxx
# 同理,如果要测速 80 端口,那么也需要加上 -url 参数来指定一个 http:// 协议的地址才行(且该地址不会强制重定向至 HTTPS如果是非 80 443 端口,那么需要确定该下载测速地址是否支持通过该端口访问。
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
# 指定地区名后,延迟测速后得到的结果就都是指定地区的 IP 了(也可以继续进行下载测速)
# 节点地区名为当地 机场三字码,指定多个时用英文逗号分隔
# 指定地区名后,延迟测速后得到的结果就都是指定地区的 IP 了(如果没有指定 -dd 的话则会继续进行下载测速)
# 如果延迟测速后结果为 0则说明没有找到任何一个未超时可用的指定地区的 IP。
# 节点地区名为当地 IATA 机场地区码或国家/城市码指定多个时用英文逗号分隔v2.2.3 版本后支持小写
CloudflareST.exe -cfcolo HKG,KHH,NRT,LAX,SEA,SJC,FRA,MAD
cfst.exe -httping -cfcolo HKG,KHH,NRT,LAX,SEA,SJC,FRA,MAD
# 注意,该参数只有在 HTTPing 延迟测速模式下才可用(因为要访问网页来获得
# 注意,该参数只有在 HTTPing 延迟测速模式下才可用(因为软件是通过 HTTP 链接中的响应头来获得该 IP 的实际地区码
# 另外HTTPing 过程中,软件会从 HTTP 响应头中获取该 IP 当前地区码(支持 Cloudflare、AWS CloudFront、Fastly、Gcore、CDN77、Bunny 等 CDN并显示出来而 TCPing 过程中无法这样做(但 下载测速 时也会这样做来获取地区码,毕竟下载测速也是个 HTTP 链接)
```
> Cloudflare 所有节点地区名(机场三字码),请看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>
@@ -324,42 +476,62 @@ 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>
****
#### \# 测速其他端口
<details>
<summary><code><strong>「 点击展开 查看内容 」</strong></code></summary>
****
``` bash
# 如果你想要测速非默认 443 的其他端口,则需要通过 -tp 参数指定(该参数会影响 延迟测速/下载测速 时使用的端口)
# 如果要延迟测速 80 端口+下载测速(如果 -dd 禁用了下载测速则不需要),那么还需要指定 http:// 协议的下载测速地址才行(且该地址不会强制重定向至 HTTPS因为那样就变成 443 端口了)
cfst.exe -tp 80 -url http://cdn.cloudflare.steamstatic.com/steam/apps/5952/movie_max.webm
# 如果是非 80 443 的其他端口,那么需要确定你使用的下载测速地址是否支持通过该非标端口访问。
```
</details>
****
#### \# 自定义测速地址
<details>
@@ -371,37 +543,31 @@ C:\abc\CloudflareST.exe -f C:\abc\4.txt -o C:\abc\result.csv -dd
# 该参数适用于下载测速 及 HTTP 协议的延迟测速,对于后者该地址可以是任意网页 URL不局限于具体文件地址
# 地址要求:可以直接下载、文件大小超过 200MB、用的是 Cloudflare CDN
CloudflareST.exe -url https://cf.xiu2.xyz/url
cfst.exe -url https://cf.xiu2.xyz/url
# 注意:如果测速地址为 HTTP 协议,记得加上 -tp 80这个参数会影响 延迟测速/下载测速 时使用的端口)
CloudflareST.exe -tp 80 -url http://xxx/xxx
# 注意:如果测速地址为 HTTP 协议(该地址不能强制重定向至 HTTPS,记得加上 -tp 80这个参数会影响 延迟测速/下载测速 时使用的端口),如果是非 80 443 端口,那么需要确定下载测速地址是否支持通过该端口访问。
cfst.exe -tp 80 -url http://cdn.cloudflare.steamstatic.com/steam/apps/5952/movie_max.webm
```
</details>
****
#### \# 自定义测速条件(指定 延迟/下载速度 的目标范围)
#### \# 自定义测速条件(指定 延迟/丢包/下载速度 的目标范围)
<details>
<summary><code><strong>「 点击展开 查看内容 」</strong></code></summary>
****
- 指定 **[平均延迟下限]** 条件
``` bash
# 平均延迟下限40 ms (一般除了移动直连香港外,几乎不存在低于 100ms 的,自行测试适合的下限延迟)
# 平均延迟下限和其他的上下限参数一样,都可以单独使用、互相搭配使用!
CloudflareST.exe -tll 40
```
> 注意:延迟测速进度条右边的**可用数量**,仅指延迟测速过程中**未超时的 IP 数量**,和延迟下限条件无关。
- 仅指定 **[平均延迟上限]** 条件
``` bash
# 平均延迟上限200 ms下载速度下限0 MB/s数量10 个(可选)
# 平均延迟上限200 ms下载速度下限0 MB/s
# 即找到平均延迟低于 200 ms 的 IP然后再按延迟从低到高进行 10 次下载测速
CloudflareST.exe -tl 200 -dn 10
cfst.exe -tl 200
```
> 如果**没有找到一个满足延迟**条件的 IP那么不会输出任何内容。
@@ -413,7 +579,15 @@ CloudflareST.exe -tl 200 -dn 10
``` bash
# 平均延迟上限200 ms下载速度下限0 MB/s数量不知道多少 个
# 即只输出低于 200ms 的 IP且不再下载测速因为不再下载测速所以 -dn 参数就无效了)
CloudflareST.exe -tl 200 -dd
cfst.exe -tl 200 -dd
```
- 仅指定 **[丢包几率上限]** 条件
``` bash
# 丢包几率上限0.25
# 即找到丢包率低于等于 0.25 的 IP范围 0.00~1.00,如果 -tlr 0 则代表过滤掉任何丢包的 IP
cfst.exe -tlr 0.25
```
****
@@ -423,10 +597,10 @@ CloudflareST.exe -tl 200 -dd
``` 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` 再试试**
> 没有指定平均延迟上限时,如果一直**凑不够**满足条件的 IP 数量,就会**一直测速**下去。
> 所以建议**同时指定 [下载速度下限] + [平均延迟上限]**,这样测速到指定延迟上限还没凑够数量,就会终止测速。
@@ -439,14 +613,14 @@ 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。
> 因为 Cloudflare 公开的 IP 段是**回源 IP+任播 IP**,而**回源 IP**是无法使用的,所以下载测速是 0.00。
> 运行时可以加上 `-sl 0.01`(下载速度下限),过滤掉**回源 IP**(下载测速低于 0.01MB/s 的结果)。
</details>
@@ -463,12 +637,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
```
****
@@ -487,15 +661,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 参数。
```
@@ -504,11 +678,71 @@ CloudflareST.exe -f 1.txt
****
#### \# 下载测速都是 0.00
<details>
<summary><code><strong>「 点击展开 查看内容 」</strong></code></summary>
****
首先要明白,本软件的下载测速过程,本质上和你将 `IP 下载测速地址的域名` 写入 hosts 文件,然后浏览器去访问下载测速地址是一样的,只不过软件将其自动化了(类似于 `curl -I --resolve 下载测速地址的域名:443:IP https://下载测速地址`)。
因此如果下载测速结果全都是 0.00 MB/s那么以为着下载测速失败就只有这几种可能性。
1. **下载测速地址有问题**
2. **测速的 IP 地址有问题**
3. **你的网络有问题**
但在排查具体是哪个问题前,可以先在你原先的 CFST 运行命令后追加一个 `-debug` 参数来开启调试模式,重新跑一边测速,这样下载过程中报错了就能直接看到下载测速失败的具体原因。
常见的下载测速失败报错原因有(因为是原生报错信息,因此基本都是英文):
1. `... read: connection reset by peer ... `
下载测速地址被阻断了,可能是蔷干的,也可能是运营商干的(比如移动或部分地区的白名单)
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 握手失败/TLS 证书错误 代表下载测速地址和测速 IP 服务器不匹配,也就是 下载测速地址 与 测速 IP 其中一方有误(例如下载测速地址是托管在 Fastly CDN 的,但测速 IP 是 Cloudflare CDN 的,或者反过来,总之就是 IP 服务器告诉你这个网站域名它不认识并把你拒之门外)
> 如果你遇到了其他报错原因,且翻译后还是不懂,可以发 Issues 或 Discussions 询问。
根据上面的报错原因排查一遍后,如果还是无法解决,那么可以尝试下面这些:
**一、下载测速地址有问题**
先去 [#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 的网站**。
但就如 [**#8**](https://github.com/XIU2/CloudflareSpeedTest/issues/8) 所说,一个个添加域名到 Hosts 实在**太麻烦**了,于是我就找到了个**一劳永逸**的办法!可以看这个 [**还在一个个添加 Hosts完美本地加速所有使用 Cloudflare CDN 的网站方法来了!**](https://github.com/XIU2/CloudflareSpeedTest/discussions/71) 和另一个[依靠本地 DNS 服务来修改域名解析 IP 为自选 IP](https://github.com/XIU2/CloudflareSpeedTest/issues/115) 的教程。
但就如 [**#8**](https://github.com/XIU2/CloudflareSpeedTest/issues/8) 所说,一个个添加域名到 Hosts 实在**太麻烦**了,于是我就找到了个**一劳永逸**的办法!可以看这个 [**还在一个个添加 Hosts完美本地加速所有使用 Cloudflare CDN 的网站方法来了!**](https://github.com/XIU2/CloudflareSpeedTest/discussions/71) 和另一个[依靠本地 DNS 服务来修改域名解析 IP 为自选 IP](https://github.com/XIU2/CloudflareSpeedTest/discussions/317) 的教程。
****
@@ -516,37 +750,41 @@ CloudflareST.exe -f 1.txt
考虑到很多人获得最快 Cloudflare CDN IP 后,需要替换 Hosts 文件中的 IP。
可以看这个 [**Issues**](https://github.com/XIU2/CloudflareSpeedTest/issues/42) 获取 **Windows/Linux 自动更新 Hosts 脚本**
可以看这个 [**Issues**](https://github.com/XIU2/CloudflareSpeedTest/discussions/312) 获取 **Windows/Linux 自动更新 Hosts 脚本**
****
## 问题反馈
如果你遇到什么问题,可以先去 [**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)、[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) 来告诉我!
> _有问题请**大胆告诉我**,描述越详细越好(随时可远程协助),如果不说那我怎么去完善功能或~~修复 BUG~~ 呢_
> [!NOTE]
> **注意**_与 CFST 本身 `反馈问题、功能建议` 无关的,请前往项目内部 论坛 讨论(顶部的 `💬 Discussions`_
****
## 赞赏支持
## 如果帮到你的话就 "打赏" 一下吧~🎉✨
![微信赞赏](https://cdn.staticaly.com/gh/XIU2/XIU2/master/img/zs-01.png)![支付宝赞赏](https://cdn.staticaly.com/gh/XIU2/XIU2/master/img/zs-02.png)
![微信赞赏](https://github.com/XIU2/XIU2/blob/master/img/zs-01.png)![支付宝赞赏](https://github.com/XIU2/XIU2/blob/master/img/zs-02.png)
****
## 衍生项目
- _https://github.com/xianshenglu/cloudflare-ip-tester-app_
_**CloudflareST 安卓版 APP [#202](https://github.com/XIU2/CloudflareSpeedTest/issues/202)**_
_**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/issues/174)**_
_**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)**_
> _此处仅收集了在本项目 Issues 中宣传过的部分 CloudflareST 相关衍生项目,如果有遗漏可以告诉我~_
- _https://github.com/hoseinnikkhah/CloudflareSpeedTest-English_
_**English language version of CFST (Text language differences only) [#64](https://github.com/XIU2/CloudflareSpeedTest/issues/68)**_
> _此处仅收集了在本项目中宣传过的部分 CFST 相关衍生项目,如果有遗漏可以告诉我~_
****
@@ -559,6 +797,65 @@ _**CloudflareST OpenWrt 原生编译版本 [#64](https://github.com/XIU2/Cloudfl
****
## 手动编译
<details>
<summary><code><strong>「 点击展开 查看内容 」</strong></code></summary>
****
为了方便,我是在编译的时候将版本号写入代码中的 version 变量,因此你手动编译时,需要像下面这样在 `go build` 命令后面加上 `-ldflags` 参数来指定版本号:
```bash
go build -ldflags "-s -w -X main.version=v1.0.0"
# 在 CloudflareSpeedTest 目录中通过命令行(例如 CMD、Bat 脚本运行该命令即可编译一个可在和当前设备同样系统、位数、架构的环境下运行的二进制程序Go 会自动检测你的系统位数、架构)且版本号为 v1.0.0
```
如果想要在 Windows 64位系统下编译**其他系统、架构、位数**,那么需要指定 **GOOS** 和 **GOARCH** 变量。
例如在 Windows 系统下编译一个适用于 **Linux 系统 amd 架构 64 位**的二进制程序:
```bat
SET GOOS=linux
SET GOARCH=amd64
go build -ldflags "-s -w -X main.version=v1.0.0"
```
例如在 Linux 系统下编译一个适用于 **Windows 系统 amd 架构 32 位**的二进制程序:
```bash
GOOS=windows
GOARCH=386
go build -ldflags "-s -w -X main.version=v1.0.0"
```
> 可以运行 `go tool dist list` 来查看当前 Go 版本支持编译哪些组合。
****
当然,为了方便批量编译,我会专门指定一个变量为版本号,后续编译直接调用该版本号变量即可。
同时,批量编译的话,还需要分开放到不同文件夹才行(或者文件名不同),需要加上 `-o` 参数指定。
```bat
:: Windows 系统下是这样:
SET version=v1.0.0
SET GOOS=linux
SET GOARCH=amd64
go build -o Releases\cfst_linux_amd64\cfst -ldflags "-s -w -X main.version=%version%"
```
```bash
# Linux 系统下是这样:
version=v1.0.0
GOOS=windows
GOARCH=386
go build -o Releases/cfst_windows_386/cfst.exe -ldflags "-s -w -X main.version=${version}"
```
</details>
****
## License
The GPL-3.0 License.
The GPL-3.0 License.

2
go.mod
View File

@@ -1,4 +1,4 @@
module CloudflareSpeedTest
module github.com/XIU2/CloudflareSpeedTest
go 1.14

34
main.go
View File

@@ -3,14 +3,14 @@ package main
import (
"flag"
"fmt"
"io/ioutil"
"io"
"net/http"
"os"
"runtime"
"time"
"CloudflareSpeedTest/task"
"CloudflareSpeedTest/utils"
"github.com/XIU2/CloudflareSpeedTest/task"
"github.com/XIU2/CloudflareSpeedTest/utils"
)
var (
@@ -21,14 +21,14 @@ 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
参数:
-n 200
延迟测速线程;越多延迟测速越快,性能弱的设备 (如路由器) 请勿太高;(默认 200 最多 1000)
-t 4
延迟测速次数;单个 IP 延迟测速次数,为 1 时将过滤丢包的IP(默认 4 次)
延迟测速次数;单个 IP 延迟测速次数;(默认 4 次)
-dn 10
下载测速数量;延迟测速并排序后,从最低延迟起下载测速的数量;(默认 10 个)
-dt 10
@@ -43,12 +43,14 @@ 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)
平均延迟上限;只输出低于指定平均延迟的 IP各上下限条件可搭配使用(默认 9999 ms)
-tll 40
平均延迟下限;只输出高于指定平均延迟的 IP,可与其他上限/下限搭配(默认 0 ms)
平均延迟下限;只输出高于指定平均延迟的 IP(默认 0 ms)
-tlr 0.2
丢包几率上限;只输出低于/等于指定丢包率的 IP范围 0.00~1.000 过滤掉任何丢包的 IP(默认 1.00)
-sl 5
下载速度下限;只输出高于指定下载速度的 IP凑够指定数量 [-dn] 才会停止测速;(默认 0.00 MB/s)
@@ -66,12 +68,16 @@ https://github.com/XIU2/CloudflareSpeedTest
-allip
测速全部的IP对 IP 段中的每个 IP (仅支持 IPv4) 进行测速;(默认 每个 /24 段随机测速一个 IP)
-debug
调试输出模式;会在一些非预期情况下输出更多日志以便判断原因;(默认 关闭)
-v
打印程序版本 + 检查版本更新
-h
打印帮助说明
`
var minDelay, maxDelay, downloadTime int
var maxLossRate float64
flag.IntVar(&task.Routines, "n", 200, "延迟测速线程")
flag.IntVar(&task.PingTimes, "t", 4, "延迟测速次数")
flag.IntVar(&task.TestCount, "dn", 10, "下载测速数量")
@@ -85,6 +91,7 @@ https://github.com/XIU2/CloudflareSpeedTest
flag.IntVar(&maxDelay, "tl", 9999, "平均延迟上限")
flag.IntVar(&minDelay, "tll", 0, "平均延迟下限")
flag.Float64Var(&maxLossRate, "tlr", 1, "丢包几率上限")
flag.Float64Var(&task.MinSpeed, "sl", 0, "下载速度下限")
flag.IntVar(&utils.PrintNum, "p", 10, "显示结果数量")
@@ -95,15 +102,18 @@ 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] 数量而一直测速...")
fmt.Println("\033[33m[提示] 在使用 [-sl] 参数时,建议搭配 [-tl] 参数,以避免因凑不够 [-dn] 数量而一直测速...\033[0m")
}
utils.InputMaxDelay = time.Duration(maxDelay) * time.Millisecond
utils.InputMinDelay = time.Duration(minDelay) * time.Millisecond
utils.InputMaxLossRate = float32(maxLossRate)
task.Timeout = time.Duration(downloadTime) * time.Second
task.HttpingCFColomap = task.MapColoMap()
@@ -125,8 +135,8 @@ func main() {
fmt.Printf("# XIU2/CloudflareSpeedTest %s \n\n", version)
// 开始延迟测速
pingData := task.NewPing().Run().FilterDelay()
// 开始延迟测速 + 过滤延迟/丢包
pingData := task.NewPing().Run().FilterDelay().FilterLossRate()
// 开始下载测速
speedData := task.TestDownloadSpeed(pingData)
utils.ExportCsv(speedData) // 输出文件
@@ -157,7 +167,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,16 +1,28 @@
# 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>
@@ -37,12 +49,13 @@
****
## 📑 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>
@@ -72,17 +85,42 @@
****
## 📑 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>
****
#### 2024年10月06日版本 v1.0.5
- **1. 新增** 支持 API 令牌方式(相比 API 密钥这种全局权限的API 令牌可以自由控制权限)
#### 2021年12月17日版本 v1.0.4
- **1. 新增** 找不到满足条件的 IP 就一直循环测速功能(默认注释)
- **2. 优化** 代码
@@ -103,7 +141,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

@@ -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,14 +55,14 @@ 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
)
@@ -79,24 +79,24 @@ for /f "tokens=1 delims=," %%i in (result_3proxy.txt) do (
:: <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,19 +1,19 @@
:: --------------------------------------------------------------
:: 项目: CloudflareSpeedTest 自动更新域名解析记录
:: 版本: 1.0.4
:: 版本: 1.0.5
:: 作者: 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
)
@@ -23,14 +23,21 @@ for /f "tokens=1 delims=," %%i in (result_ddns.txt) do (
Echo %%i
if "%%i"=="" (
echo.
echo CloudflareST 测速结果 IP 数量为 0跳过下面步骤...
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 "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
)
)

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

@@ -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,14 +55,14 @@ 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
)
@@ -79,24 +79,24 @@ for /f "tokens=1 delims=," %%i in (result_hosts.txt) do (
:: <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

@@ -10,7 +10,7 @@ import (
"strconv"
"time"
"CloudflareSpeedTest/utils"
"github.com/XIU2/CloudflareSpeedTest/utils"
"github.com/VividCortex/ewma"
)
@@ -54,7 +54,7 @@ func TestDownloadSpeed(ipSet utils.PingDelaySet) (speedSet utils.DownloadSpeedSe
return utils.DownloadSpeedSet(ipSet)
}
if len(ipSet) <= 0 { // IP数组长度(IP数量) 大于 0 时才会继续下载测速
fmt.Println("\n[信息] 延迟测速结果 IP 数量为 0跳过下载测速。")
fmt.Println("\n\033[33m[信息] 延迟测速结果 IP 数量为 0跳过下载测速。\033[0m")
return
}
testNum := TestCount
@@ -65,7 +65,7 @@ func TestDownloadSpeed(ipSet utils.PingDelaySet) (speedSet utils.DownloadSpeedSe
TestCount = testNum
}
fmt.Printf("开始下载测速(下载速度下限:%.2f MB/s,下载测速数量:%d下载测速队列%d\n", MinSpeed, TestCount, testNum)
fmt.Printf("\033[34m开始下载测速(下限:%.2f MB/s, 数量:%d, 队列:%d\033[0m\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,8 @@ func TestDownloadSpeed(ipSet utils.PingDelaySet) (speedSet utils.DownloadSpeedSe
}
}
bar.Done()
if len(speedSet) == 0 { // 没有符合速度限制的数据,返回所有测数据
if utils.Debug && len(speedSet) == 0 { // 调试模式下,没有满足速度限制的数据,返回所有测数据供用户查看当前的测速结果,以便适当调低预期测速条件
fmt.Println("\033[33m[调试] 没有满足 下载速度下限 条件的 IP忽略条件返回所有测速数据方便下次测速时调整条件。\033[0m")
speedSet = utils.DownloadSpeedSet(ipSet)
}
// 按速度排序
@@ -106,13 +110,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 状态码引起的错误
fmt.Printf("\033[31m[调试] IP: %s, 下载测速终止HTTP 状态码: %d, 下载测速地址: %s, 出错的重定向后地址: %s\033[0m\n", ip.String(), statusCode, url, finalURL)
} else {
fmt.Printf("\033[31m[调试] IP: %s, 下载测速失败,错误信息: %v, 下载测速地址: %s, 出错的重定向后地址: %s\033[0m\n", ip.String(), err, url, finalURL)
}
} else { // 如果 URL 和最终地址一致,说明没有重定向
if statusCode > 0 { // 如果状态码大于 0说明是后续 HTTP 状态码引起的错误
fmt.Printf("\033[31m[调试] IP: %s, 下载测速终止HTTP 状态码: %d, 下载测速地址: %s\033[0m\n", ip.String(), statusCode, url)
} else {
fmt.Printf("\033[31m[调试] IP: %s, 下载测速失败,错误信息: %v, 下载测速地址: %s\033[0m\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 { // 调试模式下,输出更多信息
fmt.Printf("\033[31m[调试] IP: %s, 下载测速地址重定向次数过多,终止测速,下载测速地址: %s\033[0m\n", ip.String(), req.URL.String())
}
return http.ErrUseLastResponse
}
if req.Header.Get("Referer") == defaultURL { // 当使用默认下载测速地址时,重定向不携带 Referer
@@ -123,19 +155,32 @@ func downloadHandler(ip *net.IPAddr) float64 {
}
req, err := http.NewRequest("GET", URL, nil)
if err != nil {
return 0.0
if utils.Debug { // 调试模式下,输出更多信息
fmt.Printf("\033[31m[调试] IP: %s, 下载测速请求创建失败,错误信息: %v, 下载测速地址: %s\033[0m\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) // 加上下载测速时间得到的结束时间
@@ -169,6 +214,8 @@ func downloadHandler(ip *net.IPAddr) float64 {
if err != nil {
if err != io.EOF { // 如果文件下载过程中遇到报错(如 Timeout且并不是因为文件下载完了则退出循环终止测速
break
} else if contentLength == -1 { // 文件下载完成 且 文件大小未知则退出循环终止测速例如https://speed.cloudflare.com/__down?bytes=200000000 这样的,如果在 10 秒内就下载完成了,会导致测速结果明显偏低甚至显示为 0.00(下载速度太快时)
break
}
// 获取上个时间片
last_time_slice := timeStart.Add(timeSlice * time.Duration(timeCounter-1))
@@ -177,5 +224,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,25 +2,31 @@ package task
import (
//"crypto/tls"
//"fmt"
"fmt"
"io"
"log"
"net"
"net/http"
"regexp"
"strings"
"sync"
"time"
"github.com/XIU2/CloudflareSpeedTest/utils"
)
var (
Httping bool
HttpingStatusCode int
HttpingCFColo string
HttpingCFColomap *sync.Map
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{
@@ -32,78 +38,96 @@ 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 { // 调试模式下,输出更多信息
fmt.Printf("\033[31m[调试] IP: %s, 延迟测速请求创建失败,错误信息: %v, 测速地址: %s\033[0m\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 { // 调试模式下,输出更多信息
fmt.Printf("\033[31m[调试] IP: %s, 延迟测速失败,错误信息: %v, 测速地址: %s\033[0m\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 { // 调试模式下,输出更多信息
fmt.Printf("\033[31m[调试] IP: %s, 延迟测速终止HTTP 状态码: %d, 测速地址: %s\033[0m\n", ip.String(), response.StatusCode, URL)
}
return 0, 0, ""
}
} else {
if resp.StatusCode != HttpingStatusCode {
return 0, 0
if response.StatusCode != HttpingStatusCode {
if utils.Debug { // 调试模式下,输出更多信息
fmt.Printf("\033[31m[调试] IP: %s, 延迟测速终止HTTP 状态码: %d, 指定的 HTTP 状态码 %d, 测速地址: %s\033[0m\n", ip.String(), response.StatusCode, HttpingStatusCode, URL)
}
return 0, 0, ""
}
}
io.Copy(io.Discard, resp.Body)
io.Copy(io.Discard, response.Body)
// 通过头部参数获取地区码
colo = getHeaderColo(response.Header)
// 只有指定了地区才匹配机场地区码
if HttpingCFColo != "" {
cfRay := resp.Header.Get("CF-RAY")
colo := p.getColo(cfRay)
if colo == "" {
return 0, 0
// 判断是否匹配指定的地区码
colo = p.filterColo(colo)
if colo == "" { // 没有匹配到地区码或不符合指定地区则直接结束该 IP 测试
if utils.Debug { // 调试模式下,输出更多信息
fmt.Printf("\033[31m[调试] IP: %s, 地区码不匹配: %s\033[0m\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
}
colos := strings.Split(HttpingCFColo, ",")
// 将 -cfcolo 参数指定的地区地区码转为大写并格式化
colos := strings.Split(strings.ToUpper(HttpingCFColo), ",")
colomap := &sync.Map{}
for _, colo := range colos {
colomap.Store(colo, colo)
@@ -111,22 +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- 前缀再去匹配
}
}
idColo := strings.Split(b, "-")
out := idColo[1]
if HttpingCFColomap == nil {
return out
}
_, ok := HttpingCFColomap.Load(out)
if ok {
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)
}
// 如果是 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

@@ -49,6 +49,7 @@ func newIPRanges() *IPRanges {
}
}
// 如果是单独 IP 则加上子网掩码,反之则获取子网掩码(r.mask)
func (r *IPRanges) fixIP(ip string) string {
// 如果不含有 '/' 则代表不是 IP 段,而是一个单独的 IP因此需要加上 /32 /128 子网掩码
if i := strings.IndexByte(ip, '/'); i < 0 {
@@ -64,6 +65,7 @@ func (r *IPRanges) fixIP(ip string) string {
return ip
}
// 解析 IP 段,获得 IP、IP 范围、子网掩码
func (r *IPRanges) parseCIDR(ip string) {
var err error
if r.firstIP, r.ipNet, err = net.ParseCIDR(r.fixIP(ip)); err != nil {
@@ -98,40 +100,48 @@ func (r *IPRanges) getIPRange() (minIP, hosts byte) {
}
func (r *IPRanges) chooseIPv4() {
minIP, hosts := r.getIPRange()
for r.ipNet.Contains(r.firstIP) {
if TestAll { // 如果是测速全部 IP
for i := 0; i <= int(hosts); i++ { // 遍历 IP 最后一段最小值到最大值
r.appendIPv4(byte(i) + minIP)
if r.mask == "/32" { // 单个 IP 则无需随机,直接加入自身即可
r.appendIP(r.firstIP)
} else {
minIP, hosts := r.getIPRange() // 返回第四段 IP 的最小值及可用数目
for r.ipNet.Contains(r.firstIP) { // 只要该 IP 没有超出 IP 网段范围,就继续循环随机
if TestAll { // 如果是测速全部 IP
for i := 0; i <= int(hosts); i++ { // 遍历 IP 最后一段最小值到最大值
r.appendIPv4(byte(i) + minIP)
}
} else { // 随机 IP 的最后一段 0.0.0.X
r.appendIPv4(minIP + randIPEndWith(hosts))
}
} else { // 随机 IP 的最后一段 0.0.0.X
r.appendIPv4(minIP + randIPEndWith(hosts))
}
r.firstIP[14]++ // 0.0.(X+1).X
if r.firstIP[14] == 0 {
r.firstIP[13]++ // 0.(X+1).X.X
if r.firstIP[13] == 0 {
r.firstIP[12]++ // (X+1).X.X.X
r.firstIP[14]++ // 0.0.(X+1).X
if r.firstIP[14] == 0 {
r.firstIP[13]++ // 0.(X+1).X.X
if r.firstIP[13] == 0 {
r.firstIP[12]++ // (X+1).X.X.X
}
}
}
}
}
func (r *IPRanges) chooseIPv6() {
var tempIP uint8
for r.ipNet.Contains(r.firstIP) {
if r.mask != "/128" {
if r.mask == "/128" { // 单个 IP 则无需随机,直接加入自身即可
r.appendIP(r.firstIP)
} else {
var tempIP uint8 // 临时变量,用于记录前一位的值
for r.ipNet.Contains(r.firstIP) { // 只要该 IP 没有超出 IP 网段范围,就继续循环随机
r.firstIP[15] = randIPEndWith(255) // 随机 IP 的最后一段
r.firstIP[14] = randIPEndWith(255) // 随机 IP 的最后一段
}
targetIP := make([]byte, len(r.firstIP))
copy(targetIP, r.firstIP)
r.appendIP(targetIP)
for i := 13; i >= 0; i-- {
tempIP = r.firstIP[i]
r.firstIP[i] += randIPEndWith(255)
if r.firstIP[i] >= tempIP {
break
targetIP := make([]byte, len(r.firstIP))
copy(targetIP, r.firstIP)
r.appendIP(targetIP) // 加入 IP 地址池
for i := 13; i >= 0; i-- { // 从倒数第三位开始往前随机
tempIP = r.firstIP[i] // 保存前一位的值
r.firstIP[i] += randIPEndWith(255) // 随机 0~255加到当前位上
if r.firstIP[i] >= tempIP { // 如果当前位的值大于等于前一位的值,说明随机成功了,可以退出该循环
break
}
}
}
}
@@ -140,10 +150,14 @@ func (r *IPRanges) chooseIPv6() {
func loadIPRanges() []*net.IPAddr {
ranges := newIPRanges()
if IPText != "" { // 从参数中获取 IP 段数据
IPs := strings.Split(IPText, ",")
IPs := strings.Split(IPText, ",") // 以逗号分隔为数组并循环遍历
for _, IP := range IPs {
ranges.parseCIDR(IP)
if isIPv4(IP) {
IP = strings.TrimSpace(IP) // 去除首尾的空白字符(空格、制表符、换行符等)
if IP == "" { // 跳过空的(即开头、结尾或连续多个 ,, 的情况)
continue
}
ranges.parseCIDR(IP) // 解析 IP 段,获得 IP、IP 范围、子网掩码
if isIPv4(IP) { // 生成要测速的所有 IPv4 / IPv6 地址(单个/随机/全部)
ranges.chooseIPv4()
} else {
ranges.chooseIPv6()
@@ -159,9 +173,13 @@ func loadIPRanges() []*net.IPAddr {
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
ranges.parseCIDR(scanner.Text())
if isIPv4(scanner.Text()) {
for scanner.Scan() { // 循环遍历文件每一行
line := strings.TrimSpace(scanner.Text()) // 去除首尾的空白字符(空格、制表符、换行符等)
if line == "" { // 跳过空行
continue
}
ranges.parseCIDR(line) // 解析 IP 段,获得 IP、IP 范围、子网掩码
if isIPv4(line) { // 生成要测速的所有 IPv4 / IPv6 地址(单个/随机/全部)
ranges.chooseIPv4()
} else {
ranges.chooseIPv6()

View File

@@ -8,7 +8,7 @@ import (
"sync"
"time"
"CloudflareSpeedTest/utils"
"github.com/XIU2/CloudflareSpeedTest/utils"
)
const (
@@ -64,9 +64,9 @@ func (p *Ping) Run() utils.PingDelaySet {
return p.csv
}
if Httping {
fmt.Printf("开始延迟测速模式HTTP端口:%d,平均延迟上限:%v ms平均延迟下限%v ms)\n", TCPPort, utils.InputMaxDelay.Milliseconds(), utils.InputMinDelay.Milliseconds())
fmt.Printf("\033[34m开始延迟测速模式HTTP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\033[0m\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
} else {
fmt.Printf("开始延迟测速模式TCP端口:%d,平均延迟上限:%v ms平均延迟下限%v ms)\n", TCPPort, utils.InputMaxDelay.Milliseconds(), utils.InputMinDelay.Milliseconds())
fmt.Printf("\033[34m开始延迟测速模式TCP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\033[0m\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)
}

View File

@@ -11,16 +11,19 @@ import (
)
const (
defaultOutput = "result.csv"
maxDelay = 9999 * time.Millisecond
minDelay = 0 * time.Millisecond
defaultOutput = "result.csv"
maxDelay = 9999 * time.Millisecond
minDelay = 0 * time.Millisecond
maxLossRate float32 = 1.0
)
var (
InputMaxDelay = maxDelay
InputMinDelay = minDelay
Output = defaultOutput
PrintNum = 10
InputMaxDelay = maxDelay
InputMinDelay = minDelay
InputMaxLossRate = maxLossRate
Output = defaultOutput
PrintNum = 10
Debug = false // 是否开启调试模式
)
// 是否打印测试结果
@@ -38,30 +41,38 @@ type PingData struct {
Sended int
Received int
Delay time.Duration
Colo string
}
type CloudflareIPData struct {
*PingData
recvRate float32
lossRate float32
DownloadSpeed float64
}
func (cf *CloudflareIPData) getRecvRate() float32 {
if cf.recvRate == 0 {
// 计算丢包率
func (cf *CloudflareIPData) getLossRate() float32 {
if cf.lossRate == 0 {
pingLost := cf.Sended - cf.Received
cf.recvRate = float32(pingLost) / float32(cf.Sended)
cf.lossRate = float32(pingLost) / float32(cf.Sended)
}
return cf.recvRate
return cf.lossRate
}
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.getRecvRate()), 'f', 2, 32)
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
}
@@ -76,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()
}
@@ -89,17 +100,22 @@ func convertToString(data []CloudflareIPData) [][]string {
return result
}
// 延迟丢包排序
type PingDelaySet []CloudflareIPData
// 延迟条件过滤
func (s PingDelaySet) FilterDelay() (data PingDelaySet) {
if InputMaxDelay > maxDelay || InputMinDelay < minDelay {
if InputMaxDelay > maxDelay || InputMinDelay < minDelay { // 当输入的延迟条件不在默认范围内时,不进行过滤
return s
}
if InputMaxDelay == maxDelay && InputMinDelay == minDelay { // 当输入的延迟条件为默认值时,不进行过滤
return s
}
for _, v := range s {
if v.Delay > InputMaxDelay { // 平均延迟上限
if v.Delay > InputMaxDelay { // 平均延迟上限,延迟大于条件最大值时,后面的数据都不满足条件,直接跳出循环
break
}
if v.Delay < InputMinDelay { // 平均延迟下限
if v.Delay < InputMinDelay { // 平均延迟下限,延迟小于条件最小值时,不满足条件,跳过
continue
}
data = append(data, v) // 延迟满足条件时,添加到新数组中
@@ -107,18 +123,30 @@ func (s PingDelaySet) FilterDelay() (data PingDelaySet) {
return
}
// 丢包条件过滤
func (s PingDelaySet) FilterLossRate() (data PingDelaySet) {
if InputMaxLossRate >= maxLossRate { // 当输入的丢包条件为默认值时,不进行过滤
return s
}
for _, v := range s {
if v.getLossRate() > InputMaxLossRate { // 丢包几率上限
break
}
data = append(data, v) // 丢包率满足条件时,添加到新数组中
}
return
}
func (s PingDelaySet) Len() int {
return len(s)
}
func (s PingDelaySet) Less(i, j int) bool {
iRate, jRate := s[i].getRecvRate(), s[j].getRecvRate()
iRate, jRate := s[i].getLossRate(), s[j].getLossRate()
if iRate != jRate {
return iRate < jRate
}
return s[i].Delay < s[j].Delay
}
func (s PingDelaySet) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
@@ -129,11 +157,9 @@ type DownloadSpeedSet []CloudflareIPData
func (s DownloadSpeedSet) Len() int {
return len(s)
}
func (s DownloadSpeedSet) Less(i, j int) bool {
return s[i].DownloadSpeed > s[j].DownloadSpeed
}
func (s DownloadSpeedSet) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
@@ -150,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 := "\033[34m%-16s%-5s%-5s%-5s%-6s%-12s%-5s\033[0m\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 = "\033[34m%-40s%-5s%-5s%-5s%-6s%-12s%-5s\033[0m\n"
dataFormat = "%-42s%-8s%-8s%-8s%-10s%-16s%-8s\n"
break
}
}
fmt.Printf(headFormat, "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)")
fmt.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)