ghprobe 0.1.2 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +152 -0
- package/README.en.md +636 -626
- package/README.md +629 -614
- package/bin/ghprobe.js +74 -6
- package/config.default.yaml +215 -166
- package/package.json +1 -1
- package/src/algorithm.js +173 -0
- package/src/daemon.js +147 -0
- package/src/doctor.js +174 -0
- package/src/health.js +28 -6
- package/src/pool.js +8 -5
- package/src/probe.js +16 -3
- package/src/prober.js +175 -9
- package/src/ranker.js +26 -0
- package/src/status.js +88 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,158 @@
|
|
|
5
5
|
格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
|
|
6
6
|
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
7
7
|
|
|
8
|
+
## [0.6.0] - 2026-10-31
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **用户行为感知的切换时机算法(`src/algorithm.js`)**:换 IP 不是零成本 —— flushdns +
|
|
13
|
+
连接池重建,正在浏览的页面会卡一下。daemon 现在按「打扰成本 vs 紧急度」决定何时落盘:
|
|
14
|
+
- **成本权重**(可配 `algorithm.weights`):前台是浏览器 100 > 浏览器在后台跑 30 >
|
|
15
|
+
前台是其他软件 10 > 空闲 0;
|
|
16
|
+
- **P0 不吃权重**:当前主备全死、用户此刻真的断着的域名 → **立即切**。「正在用」
|
|
17
|
+
和「不能用」二选一,当然选别断网;首次写入(无从打扰)同此;
|
|
18
|
+
- **非紧急优化类**(提上备选 / 重排优化 / 补缺失 / 兜底写入)在前台是浏览器时**推迟**,
|
|
19
|
+
攒成待写块由 daemon 每轮检查,用户空闲后落地;推迟上限 `deferMaxMs`(默认 10 分钟)防饿死。
|
|
20
|
+
- 检测免管理员:`tasklist` 扫浏览器进程(名单可配)+ PowerShell `GetForegroundWindow`
|
|
21
|
+
查前台窗口;结果短缓存(beforeApply 同轮复用,空闲落地走新鲜检测)。
|
|
22
|
+
- 只作用于 daemon 自动写入;手动 `health --apply` / `probe --apply` 是显式意图,不设门。
|
|
23
|
+
- 顺带修正:`fullUpdate` 写入时把 `hostsPath` 传给 `applyHosts`(此前健康检查的写路径
|
|
24
|
+
测试注入会被忽略,默认恰好等于真实 hosts 才未暴露)。
|
|
25
|
+
- 单元测试 192 → **201**(tasklist 解析 / 成本权重 / 决策矩阵 / 门控与空闲落地,全注入)。
|
|
26
|
+
|
|
27
|
+
## [0.5.0] - 2026-10-31
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- **常驻 daemon(无缝切换的核心)**:`ghprobe daemon` 以 15~45s **自适应循环**持续自愈——
|
|
32
|
+
全部健康 45s、有异常/stuck/出错 15s、断网 120s。取代「每分钟起一个新进程」的固定节拍:
|
|
33
|
+
故障发现不再等下一分钟,修复全程无进程启动开销。实测架构目标:抖动窗口结束后的
|
|
34
|
+
恢复延迟从 ~6 分钟量级压进 ~1 分钟以内。
|
|
35
|
+
- 每轮写心跳文件(`daemon.heartbeat`);单实例:发现更年轻的活实例自动让位;
|
|
36
|
+
- 每轮重载配置:编辑 `config.yaml` 即时生效;
|
|
37
|
+
- 循环体异常不退出(按 15s 快档重试)。
|
|
38
|
+
- **监督者架构(零迁移成本)**:现有的每分钟计划任务**原地降级**为监督者——
|
|
39
|
+
心跳新鲜 → 秒退(本轮交给 daemon);心跳陈旧/没有 → **自动拉起新 daemon** + 本轮照常兜底。
|
|
40
|
+
daemon 崩溃 → 下一分钟自动复活。旧版本用户升级 npm 包后自动获得,**无需重装、无需新 UAC**。
|
|
41
|
+
手动诊断用 `ghprobe health --force` 绕过监督逻辑。
|
|
42
|
+
- **status 显示常驻守护状态**:`常驻守护:运行中(pid …,心跳 Ns 前)` 一眼可见。
|
|
43
|
+
- 单元测试 185 → **192**(心跳/单实例/自适应间隔/主循环全注入,不打网络不真睡)。
|
|
44
|
+
|
|
45
|
+
## [0.4.0] - 2026-10-31
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- **🔴 修正 `raw.githubusercontent.com` 探测判据路径(潜伏 bug)**:
|
|
50
|
+
`DOMAIN_SIG` 里的 `/torvalds/linux/README.md` 在真 GitHub 上是 **404** ——
|
|
51
|
+
raw 的第 2 段是分支名,无分支的路径会被当作「README.md 分支」。就算网络全通,
|
|
52
|
+
该判据也会把活 IP 判死(假阴性)。修正为 `/torvalds/linux/master/README`
|
|
53
|
+
(实测 200 且含 "Linux kernel";linux 仓库根文件本来就叫 `README`,无 `.md`)。
|
|
54
|
+
- **默认兜底链按实测数据重写**(jsDelivr 官方多 CDN,同一份内容、官方运营、无中间人):
|
|
55
|
+
|
|
56
|
+
| 替身 | 2026-10-31 实测 |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| `fastly.jsdelivr.net`(新,首选) | Fastly anycast 151.101.x.229,node+双 curl 全栈全 IP **100%**,TTFB ~125ms |
|
|
59
|
+
| `testingcf.jsdelivr.net`(新) | Cloudflare 段,100%,与 Fastly 真正异构 |
|
|
60
|
+
| `gcore.jsdelivr.net`(新) | 100%,但当前与 testingcf 解析到同一对 CF IP,纯语义冗余 |
|
|
61
|
+
| ~~`cdn.jsdelivr.net`~~(移除) | **0/45**:TCP 全通、ClientHello 后即 RST(SNI 硬封),换 IP/换 TLS 栈均无效 |
|
|
62
|
+
|
|
63
|
+
三个替身都以**完整写法**入配置(自带 `/gh/torvalds/linux@master/README` + mustContain 判据,
|
|
64
|
+
它们不在代码 DOMAIN_SIG 里,简写会退回探根路径的弱判据)。
|
|
65
|
+
老用户没改过 `fallbacks` 的自动跟随新默认;改过的用 `ghprobe config-diff` 查看。
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
|
|
69
|
+
- **`ghprobe status` 秒级速查**:不打任何网络请求,汇总「hosts 块现状(每域名主 IP + 备选 +
|
|
70
|
+
缺失/阻断标记)+ 计划任务状态 + 自愈日志尾部」。与 doctor 的分工:日常「现在什么情况」用
|
|
71
|
+
status(<1s),坏了要诊断再用 doctor(~1 分钟)。
|
|
72
|
+
- **候选池拉取自救**:`updatePool` 支持**健康 hosts 条目当备用种子**(排在静态 seed 之前)——
|
|
73
|
+
它们刚通过三关 + HTTP 终审,是「当下确实能直连 GitHub」的 IP;seed 池被 SNI 整段封锁时
|
|
74
|
+
这批 IP 往往是唯一还拉得到 `api.github.com/meta` 的入口,池子不再永久冻结。
|
|
75
|
+
`health` 与 `update-pool` 两条路径都已接入。
|
|
76
|
+
- 单元测试 178 → **185**。
|
|
77
|
+
|
|
78
|
+
### Investigated(按用户要求实测,结论如实记录)
|
|
79
|
+
|
|
80
|
+
- **Cloudflare 1.1.1.1:当前网络全封死,不可用** —— UDP 53 超时、TCP 53 超时、
|
|
81
|
+
DoH 直连 IP 超时、`cloudflare-dns.com` 秒 RST。另勘测确认本机 System32 curl 与 Git
|
|
82
|
+
mingw64 curl 均为 Schannel 构建(与「mingw=OpenSSL」的既有假设不符,栈对比结论不受影响);
|
|
83
|
+
系统 DNS(UDP 53 出站)全部不可用,DoH 是唯一解析通道 —— 印证了本工具「DoH 端点 IP 直连」的设计。
|
|
84
|
+
|
|
85
|
+
## [0.3.0] - 2026-10-31
|
|
86
|
+
|
|
87
|
+
### Added
|
|
88
|
+
|
|
89
|
+
- **`github.githubassets.com` 加入默认域名族**:github.com 网页的全部 JS/CSS/字体都从这里
|
|
90
|
+
加载 —— 不写它「页面能打开但样式全裂」,是直连浏览最常见的体验杀手。
|
|
91
|
+
🔴 它的 Fastly 段是 `185.199.108-111.215`,与 githubusercontent 系的 `.133` **不同段**
|
|
92
|
+
(实测 `.133` 对该 SNI 直接连接失败),所以单独建 `ghassets` 池。
|
|
93
|
+
判据用 `GET /favicons/favicon.svg`(实测 4 个 .215 IP 全部 200 且以 `<svg` 开头)。
|
|
94
|
+
- **`ssh.github.com` 加入默认域名族(SSH-over-443)**:`git clone git@ssh.github.com:...`
|
|
95
|
+
的入口,SNI 封锁下最稳的 SSH 通道。探测类型新增 `type:"ssh"`:服务端先发 banner,
|
|
96
|
+
读到合法 `SSH-2.0-*` 即活,不走 TLS/HTTP 三关(`sshProbe`)。
|
|
97
|
+
- **schannel 二次重探**:Node 的 TLS ClientHello 被中间设备识别并 reset 时(README §3 实测:
|
|
98
|
+
同一 IP 同一时刻 openssl 20/20、Node 5/20、浏览器正常),改用 **Windows 自带的 curl.exe
|
|
99
|
+
(Schannel 构建,与 Edge 同一 TLS 栈)** 重探一次。为此 probeIp 的端口改为可注入。
|
|
100
|
+
重探结果的语义随之升级:
|
|
101
|
+
- schannel 通 → 写入 hosts(0.3.0 前这种情况只能写 `# blocked` 放弃,而浏览器明明能用);
|
|
102
|
+
- schannel 后 HTTP 层仍 4xx → 假活,与指纹无关,不标 blocked;
|
|
103
|
+
- schannel 后连接层仍被 reset → **连浏览器同款栈都过不去**,`# blocked` 从此是
|
|
104
|
+
「浏览器栈验证过确实被拦」的强结论,不再可能是客户端指纹的假阴性。
|
|
105
|
+
🔴 必须显式定位 System32 的 curl.exe:PATH 前面的可能是 Git 自带的 OpenSSL 构建
|
|
106
|
+
(实测 mingw64 curl 走 OpenSSL,指纹又变回去)。
|
|
107
|
+
- **排名双采样抗抖动**:对每域名前 3 名再采一枪,`mergeSamples` 按均值 + 失败罚分
|
|
108
|
+
(500ms/次)重排名。单采样时同一 IP 相邻两轮分差可达数倍、排名近乎随机,
|
|
109
|
+
而无谓的换 IP 要刷 DNS 缓存、断连接池 —— 排名稳比单次「最优」更重要。
|
|
110
|
+
`probe.stableSamples: 2`(默认开),设 1 退回旧行为。
|
|
111
|
+
- 单元测试 166 → **178**(SSH banner 解析/探测、schannel 注入路径、双采样合并、
|
|
112
|
+
githubassets 判据;全部本地 socket 与注入替身,不打真网络)。
|
|
113
|
+
|
|
114
|
+
### Live validation (2026-10-31, 真实网络)
|
|
115
|
+
|
|
116
|
+
- 首轮 probe:`ssh.github.com` 经 banner 判活(20.205.243.160,54ms);
|
|
117
|
+
`github.githubassets.com` 4 个 .215 全活(最优 score 36);`api.github.com` /
|
|
118
|
+
`github.com`(双采样后 4 个可用)正常。
|
|
119
|
+
- `raw/gist/avatars.githubusercontent.com`(.133 段)本轮全灭 —— schannel 重探同样被
|
|
120
|
+
connection reset,证实是网络层对该批 SNI 的真实封锁,**不是工具的指纹假阴性**;
|
|
121
|
+
工具如实标 blocked/absent 并走冷却,这正是设计行为。
|
|
122
|
+
|
|
123
|
+
## [0.2.0] - 2026-10-30
|
|
124
|
+
|
|
125
|
+
### Added
|
|
126
|
+
|
|
127
|
+
- **`ghprobe doctor` 一键自检**:把「本地网络 / DoH 解析 / 逐域名探测 / hosts 写入状态 /
|
|
128
|
+
计划任务」五层各查一遍,逐项给人话结论 + 下一步建议(如「跑 `ghprobe update-pool`」
|
|
129
|
+
「重跑 `ghprobe install`」)。定位:GitHub 连不上时,普通人不该被要求去读日志——
|
|
130
|
+
一条命令看懂哪层坏了、该做什么。有 fail 项时退出码非零,方便脚本消费;
|
|
131
|
+
`# blocked` 类域名只标 warn 不算失败(浏览器可能仍可用,不该吓退用户)。
|
|
132
|
+
评估逻辑拆成纯函数、编排依赖可注入,单测不打真网络。
|
|
133
|
+
- **`api.github.com` 加入默认域名族**:gh CLI(`gh api`)与 REST API 直连提速。
|
|
134
|
+
DNS 同样被污染,此前 hosts 不管它。判据用 `GET /rate_limit`(未认证也返回 200,
|
|
135
|
+
响应体必含 `rate` 字段,不依赖网页特征);候选走 seed/auto 池(GitHub 自租段)。
|
|
136
|
+
老用户升级后经三方合并自动获得该域名(没动过 `domains` 键的话)。
|
|
137
|
+
- **DoH 端点增加 DNSPod 第二入口 `120.53.53.53`**(与 `1.12.12.12` 同证书 `doh.pub`):
|
|
138
|
+
单端点抖动时解析不再整体失明。真实网络实测 4/4 端点可用。
|
|
139
|
+
- 单元测试 153 → **166**。
|
|
140
|
+
|
|
141
|
+
### Notes
|
|
142
|
+
|
|
143
|
+
- `ghprobe serve` 的 HTTP API 保持不变(`POST /api/probe`、`GET /api/status`、
|
|
144
|
+
`GET /api/hosts`、`GET /api/config`),供脚本消费。
|
|
145
|
+
|
|
146
|
+
## [0.1.3] - 2026-10-12
|
|
147
|
+
|
|
148
|
+
### Changed
|
|
149
|
+
|
|
150
|
+
- **默认配置不再预置任何第三方代理域名**(`ghproxy.net` / `gh-proxy.com` 已从 `fallbacks` 移除):
|
|
151
|
+
本工具定位「无代理」,默认预置第三方代理既与该定位矛盾,也有法律风险。
|
|
152
|
+
默认兜底只保留公共 CDN `cdn.jsdelivr.net`;多候选与自带判据机制保留,用户可自行添加替身。
|
|
153
|
+
- README(中英)第 6 节、§3 边界、免责声明同步收紧:明确「不预置任何第三方代理 / 镜像域名」。
|
|
154
|
+
|
|
155
|
+
### Upgrade
|
|
156
|
+
|
|
157
|
+
- 三方合并会把新默认带给**没动过** `fallbacks` 的用户;动过的保留原值。
|
|
158
|
+
老用户配置里若残留 `ghproxy.net` / `gh-proxy.com`,`ghprobe config-diff` 可见,自行删除即可。
|
|
159
|
+
|
|
8
160
|
## [0.1.2] - 2026-10-11
|
|
9
161
|
|
|
10
162
|
### Added
|