基于 Node.js 的 Cloudflare IP 优选 + DNS 自动故障转移工具链
一套脚本,打通「测速优选」➡️「自动切换」➡️「稳定保活」🔁
这个项目包含两个核心脚本,配合使用可以实现:
- 📡 自动拉取候选 IP(支持 URL、本地文件、直写 IP)
- ⚡ 使用 CloudflareSpeedTest 进行测速和筛选
- 🧠 自动保留低延迟/高可用的优选 IP
- ☁️ 自动同步 Cloudflare DNS 解析记录(A 记录)
- 🛟 故障时自动补位,避免全量失联
主要职责:
- 📥 自动下载并解压
CloudflareSpeedTest二进制(跨平台识别:Linux / macOS / Windows) - 🗂️ 读取配置(环境变量、本地
config.txt、青龙配置) - 🌐 从
IP_SOURCE_URL/IP_RANDOM_SOURCE_URL获取候选 IP - 🎲 可对采样池随机抽样,降低测试成本
- ⚙️ 调用 CloudflareSpeedTest 执行延迟 + 下载速度测试
- 📄 解析
data/cfst_select/result.csv结果并落盘本地文件:data/cfst_select/speed_results.txt(IP + 速度)data/cfst_select/valid_ips.txt(全部达标 IP)data/cfst_select/preferred_ips.txt(优选前 N 个 IP)
- 🔔 支持
sendNotify.js通知(若存在) - 📤 可选:配置
IP_UPLOAD_API后,测速完成可调用外部上传模块(需自行提供实现)
一句话:负责“找出更快的 Cloudflare IP,并把结果保存到本地池” ⚡
主要职责:
- 📚 从 IP 池读取候选(支持 URL、本地文件、直接 IP)
- 🛡️
stable模式(默认):每次加载CF_IP_POOL;在岗 IP 优先读内置data/ip_sync/serving_ips.txt,为空则读 CF DNS;淘汰不在池内的 IP 后探活补位;与 DNS 一致时跳过更新;成功后写回缓存 - ⚖️
latency模式:对候选池全部 IP 做轻量延迟/可用性探测,选最低的 N 个 - 🚀
speed模式:先做轻量探活,再仅对延迟最低的少量候选复用本地 CloudflareST 二进制测速 - ☁️ 可选同步 Cloudflare DNS 解析记录(A 记录)
- 📝 可选同步最终 IP 列表到 Gist
- 📦 可选上传最终 IP 列表到 S3/R2 兼容对象存储
- 🚨 IP 不足时触发告警通知
一句话:负责“从候选池选出最终 IP,并同步到已配置的输出目标” 🧭
若同时配置 DNS、Gist、S3/R2,ip_sync.js 会并行执行三种输出,并分别汇总结果。
- 先跑
cfst_select.js生成优选池data/cfst_select/preferred_ips.txt - 再由
ip_sync.js按高频周期维护最终 IP(默认stable模式,适合每 5 分钟定时)
可理解为:
cfst_select.js= 选手选拔赛 🏃(低频,刷新候选池)ip_sync.js= 在岗保活 + 故障补位 🧑🔧(高频,stable时 DNS 无变化会跳过 API 调用)
stable / latency / speed 怎么选:
| 模式 | 适用场景 | 特点 |
|---|---|---|
stable(默认) |
已配置 DNS,希望尽量少改解析 | 保留在岗 IP,只淘汰失效或不在池内的,补位到 MAX_IPS |
latency |
每次从池里重新挑最快的 N 个 | 全量轻量探活,可能频繁换 IP |
speed |
需要按下载速度二次筛选 | 成本最高,会调用 CloudflareST |
项目支持以下配置来源(按脚本逻辑合并):
- 环境变量(推荐)
- 同目录
config.txt(建议由config.example.txt复制得到,仅本地使用) - 青龙配置(
config.json/config.sh)
IP_SOURCE_URL:固定候选 IP 来源(URL/文件/单个 IP,支持逗号分隔)IP_RANDOM_SOURCE_URL:随机候选池来源IP_RANDOM_SAMPLE_COUNT:随机采样数量(默认 300)CFST_SELECT_LATENCY_THRESHOLD:延迟阈值 ms(默认 500)CFST_SELECT_DOWNLOAD_SPEED_THRESHOLD_MBPS:下载速度阈值(默认 10)CFST_SELECT_SPEED_TEST_DURATION_S:测速时长秒(默认 10)CFST_SELECT_TEST_COUNT:参与下载测速的候选数量(默认 30)CFST_SELECT_LATENCY_TEST_CONCURRENCY:CloudflareST 并发数(默认 200)PREFERRED_IP_COUNT:最终优选保存数量(默认 10)CFST_SELECT_SPEED_TEST_URL:CloudflareST 自定义测速地址(可选)LOCAL_DATA_DIR:本地数据目录(默认./data)github_proxy:下载 CloudflareST 的代理前缀(可选)IP_UPLOAD_API:可选;测速结果外部上传接口(需配合自定义上传模块)
CF_IP_POOL:候选 IP 池(URL/文件/IP,逗号分隔);为空时默认读./data/cfst_select/preferred_ips.txt;stable模式下远程 URL 最多重试 3 次IP_UPDATE_MODE:stable、latency或speed,默认stable(建议配置 DNS 三项以便读取当前解析)MAX_IPS:最终产出的 IP 数量(代码默认 2;你也可以在config.txt里按需改大)NOTIFY_THRESHOLD:告警阈值(默认 2)LOCAL_DATA_DIR:本地数据目录(默认./data)data/ip_sync/serving_ips.txt:程序内置在岗 IP 缓存(非配置项);stable模式优先读取,成功后写回CF_API_TOKEN/CF_ZONE_ID/CF_DOMAIN:可选;三者都存在时才同步 DNSGITHUB_TOKEN/GIST_NAME:可选;两者都存在时才同步 GistGIST_SECRET:是否创建 secret gist(可选;仅true视为 secret,其它值都按 public 处理)S3_ENDPOINT/S3_REGION/S3_BUCKET/S3_KEY/S3_ACCESS_KEY_ID/S3_SECRET_ACCESS_KEY:可选;六者都存在时才同步 S3/R2S3_ALLOW_HTTP:可选;默认false,仅本地调试 MinIO 等明文 HTTP 场景才设为trueIP_SYNC_LATENCY_THRESHOLD:优先使用;未设置时回退到CFST_SELECT_LATENCY_THRESHOLDIP_SYNC_TEST_COUNT:优先使用;未设置时回退到CFST_SELECT_TEST_COUNTIP_SYNC_LATENCY_TEST_CONCURRENCY:优先使用;未设置时回退到CFST_SELECT_LATENCY_TEST_CONCURRENCYIP_SYNC_DOWNLOAD_SPEED_THRESHOLD_MBPS:优先使用;未设置时回退到CFST_SELECT_DOWNLOAD_SPEED_THRESHOLD_MBPSIP_SYNC_SPEED_TEST_URL:优先使用;未设置时回退到CFST_SELECT_SPEED_TEST_URLIP_SYNC_SPEED_TEST_DURATION_S:若设置则直接传给 CloudflareST;未设置时才基于CFST_SELECT_SPEED_TEST_DURATION_S计算max(3, floor(x/2))IP_SYNC_SPEED_CANDIDATE_COUNT:若设置则直接作为speed模式二阶段候选数量;未设置时才按MAX_IPS * 3计算
本项目仅使用 Node.js 内置模块,无额外 npm 依赖。
确保你已安装:
- Node.js 16+
curl、tar(macOS/Linux 通常自带)- Windows 建议准备 unzip 能力(或使用已解压好的 CloudflareST)
先在项目根目录复制模板:
cp config.example.txt config.txtconfig.txt 仅本地使用,已被 .gitignore 忽略;请勿提交,尤其不要提交任何密钥。
然后按需编辑 config.txt,例如:
IP_SOURCE_URL=https://example.com/cf_ips.txt
CFST_SELECT_LATENCY_THRESHOLD=500
CFST_SELECT_DOWNLOAD_SPEED_THRESHOLD_MBPS=10
CFST_SELECT_SPEED_TEST_DURATION_S=10
CFST_SELECT_TEST_COUNT=30
CFST_SELECT_LATENCY_TEST_CONCURRENCY=200
PREFERRED_IP_COUNT=10
IP_SYNC_LATENCY_THRESHOLD=
IP_SYNC_TEST_COUNT=
IP_SYNC_LATENCY_TEST_CONCURRENCY=
IP_SYNC_DOWNLOAD_SPEED_THRESHOLD_MBPS=
IP_SYNC_SPEED_TEST_DURATION_S=
IP_SYNC_SPEED_TEST_URL=
IP_SYNC_SPEED_CANDIDATE_COUNT=
IP_UPDATE_MODE=stable
CF_IP_POOL=
CF_API_TOKEN=your_token
CF_ZONE_ID=your_zone_id
CF_DOMAIN=example.com
MAX_IPS=2
GITHUB_TOKEN=your_github_token
GIST_NAME=cf_ips.txt
GIST_SECRET=false
S3_ENDPOINT=https://<account_id>.r2.cloudflarestorage.com
S3_REGION=auto
S3_BUCKET=cloudflare-ips
S3_KEY=best-ip.txt
S3_ACCESS_KEY_ID=your_access_key_id
S3_SECRET_ACCESS_KEY=your_secret_access_keynode cfst_select.js
node ip_sync.jscfst_select.js:低频(例如每天/每周)🗓️ip_sync.js:高频(例如每 5 分钟)⏱️
这样既能持续刷新优选池,又能及时故障转移。
在青龙面板中进入「订阅管理」添加订阅,推荐配置:
- 名称:
cf_auto_bestip - 类型:
公开仓库 - 链接:
https://github.com/lee1080/cf_auto_bestip.git - 分支:
main
你可以直接在青龙容器内执行(成功率最高):
ql repo https://github.com/lee1080/cf_auto_bestip.git "cfst_select|ip_sync" "README|LICENSE" "utils|config" "" "js|txt"参数含义(不同青龙版本参数个数可能不同;下面以此命令为准):
- 仓库:
https://github.com/lee1080/cf_auto_bestip.git - 白名单:
cfst_select|ip_sync(只拉两个入口脚本,避免utils/shared.js出现在任务列表里) - 黑名单:
README|LICENSE(不拉文档/协议文件) - 依赖文件:
utils|config(把utils/shared.js、config.example.txt等依赖拷贝到仓库目录) - 分支:留空(默认分支)
- 文件后缀:
js|txt(允许拉取.js和.txt)
如果你的青龙版本支持「创建订阅 -> 名称」自动解析,可尝试:
cf_auto_bestip#https://github.com/lee1080/cf_auto_bestip.git#main#cfst_select|ip_sync#README|LICENSE#utils|config##js|txt
说明(名称粘贴模式字段顺序):
- 名称#链接#分支#白名单#黑名单#(其余参数…)
- 本示例与上面的
ql repo命令保持一致:白名单cfst_select|ip_sync,黑名单README|LICENSE,依赖文件utils|config,后缀js|txt - 这样入口脚本仍然只有
cfst_select.js和ip_sync.js,而utils/shared.js、config.example.txt会作为依赖文件同步,不会单独出现在任务列表中。
若该模式仍不生效,请优先使用上面的 ql repo 命令方式。✅
拉库完成后,在「定时任务」中新建两个任务:
- 优选测速任务(低频):
- 命令:
task cf_auto_bestip/cfst_select.js
- 命令:
- DNS 同步任务(高频):
- 命令:
task cf_auto_bestip/ip_sync.js
- 命令:
cfst_select.js:0 23 * * 4(每周四 23:00,可按需调整)🗓️ip_sync.js:*/5 * * * *(每 5 分钟)⏱️
在青龙「环境变量」或 config.sh 中建议至少配置以下项:
IP_SOURCE_URL(或IP_RANDOM_SOURCE_URL)IP_UPDATE_MODE=stable(默认即为stable,可不填;需全量重选时用latency/speed)MAX_IPS(DNS 最终保留条数,按域名需求调整)CF_IP_POOL(可选;留空则读data/cfst_select/preferred_ips.txt)- 若需要 DNS 输出:
CF_API_TOKEN、CF_ZONE_ID、CF_DOMAIN - 若需要 Gist 输出:
GITHUB_TOKEN、GIST_NAME
stable 模式下日志会区分 候选池 (CF_IP_POOL) 与 在岗 IP 缓存 (serving_ips.txt),后者为程序内置文件,不是配置里的输入路径。
如需使用文件配置,请在本地复制 config.example.txt 为 config.txt;config.txt 不应提交。✅
- 先手动执行一次
cfst_select.js,确认生成data/cfst_select/preferred_ips.txt - 再执行
ip_sync.js,确认 DNS 可正常更新(stable模式下若 IP 未变化,日志会提示跳过 DNS 同步) - 首次
stable运行时若serving_ips.txt为空,会从 Cloudflare DNS 读在岗 IP 并在成功后写回缓存 - 最后开启定时任务自动运行 🔁
默认在 data/ 目录下按脚本拆分:
speed_results.txt- 测速结果(含速率)valid_ips.txt- 达标 IP 列表preferred_ips.txt- 优选 IP 池(供ip_sync.js默认读取)ips.txt- 本次测试输入 IP 临时文件result.csv- CloudflareST 原始结果
serving_ips.txt- 当前在用 IP(与 DNS 同步的本地缓存,stable模式优先读取)ips.txt-speed模式二阶段测速输入 IP 临时文件result.csv-speed模式二阶段 CloudflareST 原始结果gist_id.txt- Gist ID 本地状态文件(删除后下次会新建新的 Gist)
其中:data/cfst_select/preferred_ips.txt 是测速优选池(CF_IP_POOL 候选来源),data/ip_sync/serving_ips.txt 是当前在用 IP 缓存(程序内置,stable 模式读写);若本次没有可用 IP,serving_ips.txt 会保留原内容,首次运行且无结果时则创建空文件。
- ❗不要把真实
CF_API_TOKEN提交到 GitHub - ✅ 建议提交
config.example.txt,把敏感值替换为占位符 - ✅ 建议使用
.gitignore忽略data/等运行产物,config.txt仅本地使用且不应提交
- XIU2/CloudflareSpeedTest 提供核心测速能力
- Cloudflare 提供稳定强大的 DNS API ☁️
本仓库已附带 MIT License,可直接用于开源发布 ✅