ghprobe 0.1.0 → 0.1.2
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 +80 -0
- package/README.en.md +626 -525
- package/README.md +614 -518
- package/bin/ghprobe.js +28 -3
- package/config.default.yaml +166 -140
- package/package.json +7 -3
- package/src/config.js +118 -7
- package/src/health.js +138 -32
- package/src/prober.js +68 -14
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,84 @@
|
|
|
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.1.2] - 2026-10-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **配置升级机制(三方合并)**:解决「默认值的改进到不了老用户」——
|
|
13
|
+
用户配置是 `install` 时**整份复制**的、且优先于包内默认,所以默认文件里**已有键**的新值
|
|
14
|
+
永远不生效(数组是整体替换,不合并)。现在 `install` 会额外存一份**默认配置快照**
|
|
15
|
+
(`%LOCALAPPDATA%\ghprobe\config.default.snapshot.yaml`),`loadConfig` 做**三方合并**:
|
|
16
|
+
用户值 == 快照值 → 这个键他没动过 → 用**新默认**;否则保留用户值。
|
|
17
|
+
快照**只在缺失时创建、不随升级刷新**(一刷新基准就漂了,没改过的键会被误判成改过)。
|
|
18
|
+
新增 `ghprobe config-diff` 查看用户配置与当前默认的差异;`config-path` 一并打印快照路径。
|
|
19
|
+
⚠️ 0.1.2 之前装的用户没有快照,跑一次 `ghprobe install` 之后才会建立;在那之前用
|
|
20
|
+
`config-diff` 看差异、手动采纳。
|
|
21
|
+
- **兜底链支持多个候选,并挑当下能通的那个**:原来 `fallbacks` 每个主域名只能配一个替身,
|
|
22
|
+
而替身自己也会被封(实测同一时刻 `cdn.jsdelivr.net` 的 TCP 连得上、TLS 被掐)。
|
|
23
|
+
现在默认给三个:`cdn.jsdelivr.net`(jsDelivr 公共 CDN)、`ghproxy.net` / `gh-proxy.com`
|
|
24
|
+
(第三方 GitHub 代理,配置里已注明「请求会经过它们的服务器」,介意可删)。
|
|
25
|
+
- **替身可以自带探测判据**:`fallbacks` 新增完整写法
|
|
26
|
+
`- { domain, path, mustContain }`,判据写在配置里而不是代码里 ——
|
|
27
|
+
因为不同替身的 URL 形态不同(CDN 映射 `/gh/<user>/<repo>@<ref>/<path>` vs 代理 `/<完整原始 URL>`),
|
|
28
|
+
用户新增替身不需要改源码。归一化在 `loadConfig()` 里做,下游(`targetDomains` /
|
|
29
|
+
`neededFallbacks`)拿到的仍是 `{ 主域名: [替身域名...] }`,无需改动。
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- `config.default.yaml` 头部补了升级说明:`install` 会把默认配置**整份**复制成用户配置,
|
|
34
|
+
而用户配置优先 —— 所以**默认值里已有的键,升级后新默认不会自动生效**(新增的键不受影响)。
|
|
35
|
+
- README 第 6 节重写(原「关于为什么还会出现 cdn.jsdelivr.net」):说明兜底链要解决的是
|
|
36
|
+
**换 IP 修不了**的那层封锁、为什么需要多个候选、第三方代理的隐私代价、以及怎么自己加替身。
|
|
37
|
+
并修正了原文「`raw` 被封锁后这类文件没有替代入口」的自相矛盾说法。
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- README **中文版**修正两条过时 FAQ:还在说「每个域名只写一条 IP」「Windows 对同一域名只认第一条」——
|
|
42
|
+
这两个说法在 0.1.0 就被实测推翻了(hosts 里同名多条会被解析器**全部返回**、curl / 浏览器
|
|
43
|
+
**逐个尝试**,所以备选是真兜底)。**英文版当时改了、中文版漏了**,两边现在一致。
|
|
44
|
+
- 单测 137 → **153**。
|
|
45
|
+
|
|
46
|
+
## [0.1.1] - 2026-10-11
|
|
47
|
+
|
|
48
|
+
线上实测驱动的三个修复。都是「工具看着在干活、实际把用户搞断网」那一类。
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- 🔴 **假活 IP 被写进 hosts,而客户端不会 fallback**:`github.com` 的状态码白名单里有
|
|
53
|
+
`400/401/403/404`,而 `20.205.243.161` 对该域名的**所有路径**都返回 400、响应体还是 GitHub
|
|
54
|
+
自己的错误页(`<title>Bad request · GitHub</title>`)—— 于是 `mustContain:["github"]`
|
|
55
|
+
也命中,三道判据全部放行,它被排到第 1 名写进 hosts。
|
|
56
|
+
更糟的是「同名多条目 fallback」兜不住它:**400 是合法 HTTP 响应、不是连接失败,客户端不会回退到备选**。
|
|
57
|
+
→ 根路径只接受 2xx/3xx;`reject` 加 `"bad request"`。
|
|
58
|
+
(`objects` / `gist` 的 4xx 刻意保留 —— 它们的根路径本来就是 404 / 301,实测响应体里没有 "github",
|
|
59
|
+
无法用 `mustContain` 兜底,已在代码里注明这是已知的判据弱点。)
|
|
60
|
+
- 🔴 **主 IP 挂了、备选是好的,工具却不知道**:`runHealth` 只探**主条目**,备选条目从不探活。
|
|
61
|
+
于是这种最常见的情况被当成「域名挂了」直接重排 —— 撞上 IP 抖动窗口,换了个更差的,用户反而断网。
|
|
62
|
+
→ 主 + 备选一起探活;**主挂备活时把备选提上来(promote),不重排**;
|
|
63
|
+
一个域名只有「所有已写入条目全挂」才算挂。
|
|
64
|
+
- 🔴 **指纹阻断被误判成「域名不可达」**(假阴性):ghprobe 自己是 Node,而实测
|
|
65
|
+
(同一 IP、同一 SNI、同一时刻,各 20 次)`openssl s_client` **20/20** 握手成功、node **5/20**、
|
|
66
|
+
curl **3/20**,浏览器能正常打开同一个 URL —— 说明封锁依据是 **TLS ClientHello 的形态**
|
|
67
|
+
(扩展列表 / 顺序 / 长度),既不是主机名、也不是 IP。
|
|
68
|
+
旧逻辑把「TCP 连上了但 TLS 被 reset」当成「这个 IP 不可用」,于是把 `raw.githubusercontent.com`
|
|
69
|
+
写成 `# absent` 并冷却 1 小时 —— **而浏览器明明能用**,工具却主动放弃它。
|
|
70
|
+
→ 区分「TCP 阶段失败(IP 真不可用)」与「TLS 阶段失败(本机指纹被识别)」。
|
|
71
|
+
- **备选在抖动窗口里被删掉**:`applyDelta` 用「覆盖」而非「合并」处理备选,
|
|
72
|
+
本轮只探到 1 个活 IP 时会把原有备选删掉 —— 恰恰在最需要 fallback 的时候失去它。
|
|
73
|
+
|
|
74
|
+
### Added
|
|
75
|
+
|
|
76
|
+
- hosts 块新增 `# blocked <domain> <timestamp>` 注释,与 `# absent` 语义分开:
|
|
77
|
+
`# absent` = 探过、确实没有可用 IP;`# blocked` = **探测不可判**(本机探测客户端的 TLS 指纹被识别),
|
|
78
|
+
用户的浏览器可能仍能访问。两者共用同一档冷却,避免每分钟为不可判的域名白跑一次全量探测。
|
|
79
|
+
- 健康检查日志区分三种动作:`提上备选` / `重排换 IP` / `指纹阻断`。
|
|
80
|
+
- README(中 / 英)新增「和同类项目的区别」与「边界:哪些问题它解决不了」两节,含四层故障表、
|
|
81
|
+
三客户端实测数据、以及 `# blocked` 与 `# absent` 的语义区别;
|
|
82
|
+
并修正原文「很多工具只处理第一层…束手无策」的不准确说法
|
|
83
|
+
(走代理的工具并不束手无策,应收窄为「**只写 hosts 的**工具」)。
|
|
84
|
+
- 单元测试 120 → **137**。
|
|
85
|
+
|
|
8
86
|
## [0.1.0] - 2026-10-11
|
|
9
87
|
|
|
10
88
|
首个公开版本。
|
|
@@ -120,4 +198,6 @@
|
|
|
120
198
|
- 提权脚本以 UTF-8 BOM 落盘,杜绝编码解析歧义
|
|
121
199
|
- 写入前校验块标记存在,失败自动回滚;还原时只移除本工具自己的行
|
|
122
200
|
|
|
201
|
+
[0.1.2]: https://github.com/zmw-zmw/ghprobe/releases/tag/v0.1.2
|
|
202
|
+
[0.1.1]: https://github.com/zmw-zmw/ghprobe/releases/tag/v0.1.1
|
|
123
203
|
[0.1.0]: https://github.com/zmw-zmw/ghprobe/releases/tag/v0.1.0
|