ghprobe 0.1.0 → 0.1.1
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 +41 -0
- package/README.en.md +582 -525
- package/README.md +575 -518
- package/bin/ghprobe.js +3 -1
- package/package.json +7 -3
- package/src/health.js +138 -32
- package/src/prober.js +46 -12
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,46 @@
|
|
|
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.1] - 2026-10-11
|
|
9
|
+
|
|
10
|
+
线上实测驱动的三个修复。都是「工具看着在干活、实际把用户搞断网」那一类。
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- 🔴 **假活 IP 被写进 hosts,而客户端不会 fallback**:`github.com` 的状态码白名单里有
|
|
15
|
+
`400/401/403/404`,而 `20.205.243.161` 对该域名的**所有路径**都返回 400、响应体还是 GitHub
|
|
16
|
+
自己的错误页(`<title>Bad request · GitHub</title>`)—— 于是 `mustContain:["github"]`
|
|
17
|
+
也命中,三道判据全部放行,它被排到第 1 名写进 hosts。
|
|
18
|
+
更糟的是「同名多条目 fallback」兜不住它:**400 是合法 HTTP 响应、不是连接失败,客户端不会回退到备选**。
|
|
19
|
+
→ 根路径只接受 2xx/3xx;`reject` 加 `"bad request"`。
|
|
20
|
+
(`objects` / `gist` 的 4xx 刻意保留 —— 它们的根路径本来就是 404 / 301,实测响应体里没有 "github",
|
|
21
|
+
无法用 `mustContain` 兜底,已在代码里注明这是已知的判据弱点。)
|
|
22
|
+
- 🔴 **主 IP 挂了、备选是好的,工具却不知道**:`runHealth` 只探**主条目**,备选条目从不探活。
|
|
23
|
+
于是这种最常见的情况被当成「域名挂了」直接重排 —— 撞上 IP 抖动窗口,换了个更差的,用户反而断网。
|
|
24
|
+
→ 主 + 备选一起探活;**主挂备活时把备选提上来(promote),不重排**;
|
|
25
|
+
一个域名只有「所有已写入条目全挂」才算挂。
|
|
26
|
+
- 🔴 **指纹阻断被误判成「域名不可达」**(假阴性):ghprobe 自己是 Node,而实测
|
|
27
|
+
(同一 IP、同一 SNI、同一时刻,各 20 次)`openssl s_client` **20/20** 握手成功、node **5/20**、
|
|
28
|
+
curl **3/20**,浏览器能正常打开同一个 URL —— 说明封锁依据是 **TLS ClientHello 的形态**
|
|
29
|
+
(扩展列表 / 顺序 / 长度),既不是主机名、也不是 IP。
|
|
30
|
+
旧逻辑把「TCP 连上了但 TLS 被 reset」当成「这个 IP 不可用」,于是把 `raw.githubusercontent.com`
|
|
31
|
+
写成 `# absent` 并冷却 1 小时 —— **而浏览器明明能用**,工具却主动放弃它。
|
|
32
|
+
→ 区分「TCP 阶段失败(IP 真不可用)」与「TLS 阶段失败(本机指纹被识别)」。
|
|
33
|
+
- **备选在抖动窗口里被删掉**:`applyDelta` 用「覆盖」而非「合并」处理备选,
|
|
34
|
+
本轮只探到 1 个活 IP 时会把原有备选删掉 —— 恰恰在最需要 fallback 的时候失去它。
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- hosts 块新增 `# blocked <domain> <timestamp>` 注释,与 `# absent` 语义分开:
|
|
39
|
+
`# absent` = 探过、确实没有可用 IP;`# blocked` = **探测不可判**(本机探测客户端的 TLS 指纹被识别),
|
|
40
|
+
用户的浏览器可能仍能访问。两者共用同一档冷却,避免每分钟为不可判的域名白跑一次全量探测。
|
|
41
|
+
- 健康检查日志区分三种动作:`提上备选` / `重排换 IP` / `指纹阻断`。
|
|
42
|
+
- README(中 / 英)新增「和同类项目的区别」与「边界:哪些问题它解决不了」两节,含四层故障表、
|
|
43
|
+
三客户端实测数据、以及 `# blocked` 与 `# absent` 的语义区别;
|
|
44
|
+
并修正原文「很多工具只处理第一层…束手无策」的不准确说法
|
|
45
|
+
(走代理的工具并不束手无策,应收窄为「**只写 hosts 的**工具」)。
|
|
46
|
+
- 单元测试 120 → **137**。
|
|
47
|
+
|
|
8
48
|
## [0.1.0] - 2026-10-11
|
|
9
49
|
|
|
10
50
|
首个公开版本。
|
|
@@ -120,4 +160,5 @@
|
|
|
120
160
|
- 提权脚本以 UTF-8 BOM 落盘,杜绝编码解析歧义
|
|
121
161
|
- 写入前校验块标记存在,失败自动回滚;还原时只移除本工具自己的行
|
|
122
162
|
|
|
163
|
+
[0.1.1]: https://github.com/zmw-zmw/ghprobe/releases/tag/v0.1.1
|
|
123
164
|
[0.1.0]: https://github.com/zmw-zmw/ghprobe/releases/tag/v0.1.0
|