proxygauge 1.5.6

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ValenLan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,357 @@
1
+ # ProxyGauge
2
+
3
+ <p align="center">
4
+ <strong>简体中文</strong> · <a href="README.en.md">English</a>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <img src="Resources/ProxyGauge.png" width="144" alt="ProxyGauge icon">
9
+ </p>
10
+
11
+ ProxyGauge 是一个面向最新稳定版 macOS 与 Windows 11 的开源原生代理状态、链路验证与
12
+ 防泄漏面板。它可以识别 Mihomo / Clash Verge Rev 的核心、mixed 入口、系统代理与 TUN
13
+ 状态,交叉验证实际代理出口,并通过可选的 macOS PF 或 Windows WFP Kill Switch 防止代理
14
+ 失效后回退直连。项目不包含代理订阅或节点,也不收集遥测。
15
+
16
+ ## 功能
17
+
18
+ - macOS 使用 SwiftUI,Windows 使用原生 WPF
19
+ - macOS 与 Windows 均跟随系统浅色/深色外观;Windows 还会优先遵循 High Contrast
20
+ - 应用图标由同一 1024 px `ProxyGauge-source.png` 母版生成 macOS `icns`、Windows 多尺寸 `ico` 与 WPF 高清 `png`
21
+ - 检测 Mihomo 核心、mixed 端口、系统代理与 TUN 路由
22
+ - macOS 与 Windows 首次启动均自动识别 Clash Verge Rev / Mihomo 的本地入口与流量模式;检测失败才要求手动填写端口
23
+ - 流量入口卡片按实际状态切换:仅系统代理或仅 TUN 显示绿色,两者同时开启显示橙色提示,两者均未开启显示灰色
24
+ - 用三个独立查询源交叉验证代理出口,识别出口漂移、分流或透明代理干扰
25
+ - TUN 生效时验证 DNS 是否返回 `198.18.x.x` Fake-IP,直接发现域名分流配置缺失
26
+ - 常规链路检测只回答核心、入口、DNS、出口与分流是否真实生效,不再把第三方 IP 风险分混入链路分
27
+ - macOS 与 Windows 均提供独立“IP 纯净度”入口;确认后先经当前本地代理读取出口 IP,再打开 4 个自动识别页和 2 个带 IP 的结果页
28
+ - 多站结果保留各自定义,不合并成伪精确总分;人工复核与账户判断不计入通过、提示或失败
29
+ - 链路检测运行时显示线性进度,完成后给出可解释的 0–100 链路分
30
+ - 两端默认使用不假定代理拓扑的通用方案;额外出口、策略组和域名规则由用户按需启用
31
+ - 现有 Google/Gemini/Claude 链式出口结构保留为预填模板,可修改名称、策略组、本地入口和目标域名
32
+ - 两端深度复核均使用系统默认浏览器和当前真实浏览器网络路径;ProxyGauge 不强制浏览器使用特定节点,也不修改系统代理
33
+ - 内置可独立分享的 Clash Verge Rev / Mihomo 规则包,不包含订阅或节点
34
+ - macOS 可选用独立 PF anchor 实现防泄漏 Kill Switch
35
+ - Windows 版由独立 LocalSystem 服务维护按用户限定的持久 WFP 防泄漏规则
36
+ - macOS 链路检测、Kill Switch 脚本和管理员助手均内置于 App Bundle
37
+
38
+ ## 平台支持
39
+
40
+ | 平台 | 状态面板 | 链路检测 | Kill Switch | 构建产物 |
41
+ |---|---:|---:|---:|---|
42
+ | macOS 26(Apple Silicon) | ✓ | ✓ | PF anchor(可选) | `ProxyGauge.app` |
43
+ | Windows 11 x64 | ✓ | ✓ | 持久 WFP 规则 | self-contained MSI |
44
+ | Windows 11 ARM64 | ✓ | ✓ | 持久 WFP 规则 | self-contained MSI |
45
+
46
+ 支持所有正式发布的 Windows 11;Windows 10 会被明确拒绝启动,也不为其增加兼容分支。
47
+
48
+ ## 一行安装正式版
49
+
50
+ 开发者可通过 npm 全局安装。需要预先安装 Node.js 18 或更高版本;npm 包会自动识别平台与
51
+ 架构,安装和 npm 包版本一致的 GitHub 正式版,并根据同一 Release 中的
52
+ `SHA256SUMS.txt` 校验安装包:
53
+
54
+ ```bash
55
+ npm install -g proxygauge
56
+ ```
57
+
58
+ 如果 npm 被配置为不运行生命周期脚本,完成全局安装后可显式运行 `proxygauge install`。
59
+ 不使用 npm 时,也可以直接运行下面的平台安装入口。它们会安装 GitHub 的 **Latest Release**,
60
+ 不会下载源码构建,也不会安装代理客户端、订阅或节点。
61
+
62
+ Apple Silicon Mac:
63
+
64
+ ```bash
65
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/ValenLan/ProxyGauge/main/Scripts/install-release-macos.sh)"
66
+ ```
67
+
68
+ Windows 11(在 PowerShell 中运行,自动选择 x64 或 ARM64,安装 MSI 时会请求管理员权限):
69
+
70
+ ```powershell
71
+ irm https://raw.githubusercontent.com/ValenLan/ProxyGauge/main/Scripts/install-release-windows.ps1 | iex
72
+ ```
73
+
74
+ 这些入口会执行 npm 包或本仓库中的安装脚本。谨慎的做法是先阅读 npm 包内容或在浏览器打开
75
+ 命令里的 URL 阅读脚本,确认仓库所有者是 `ValenLan`,再运行。当前正式版尚未购买平台代码签名证书:macOS 使用
76
+ ad-hoc 签名且尚未公证,Windows MSI 也未签名,因此系统可能显示安全提醒;安装器会保留
77
+ Gatekeeper、SmartScreen 和管理员授权检查,不会替用户关闭或绕过这些保护。
78
+
79
+ ## 规则包与订阅
80
+
81
+ ProxyGauge 把两者有意分开:
82
+
83
+ - **订阅**由使用者自己的代理客户端管理,ProxyGauge 不读取、不保存也不分发订阅地址、
84
+ 节点或凭据。
85
+ - **规则包**位于 [`Rules/ProxyGauge-Merge.yaml`](Rules/ProxyGauge-Merge.yaml),随 macOS
86
+ App 与 Windows MSI 一起打包,可从主界面底部“规则管理”入口预览、复制或导出。
87
+
88
+ 规则包使用 Clash Verge Rev 的 `prepend-rules`,确保 AI 与开发站点规则排在订阅自带的
89
+ `GEOIP` / `MATCH` 规则之前,同时包含 TUN 所需的 Fake-IP DNS 配置。默认策略组名是
90
+ `PROXY`;如果朋友的订阅使用其他组名,导入前替换规则最后一列即可。导出后在 Clash
91
+ Verge Rev 中新建并启用 `Merge` 配置,再刷新当前订阅。这样规则可以共享,订阅仍由每个
92
+ 人独立选择。
93
+
94
+ ## macOS
95
+
96
+ ### 系统要求
97
+
98
+ - 最新版 macOS 26,Apple Silicon Mac
99
+ - 使用 Mihomo 核心的代理客户端(默认进程名 `verge-mihomo`)
100
+ - 默认 mixed 端口:`127.0.0.1:7890`
101
+
102
+ ### 构建
103
+
104
+ 构建需要 Xcode Command Line Tools;仅运行预编译版本不需要。
105
+
106
+ ```bash
107
+ chmod +x Scripts/*.sh
108
+ Scripts/build.sh
109
+ Scripts/package-macos.sh
110
+ open "build/ProxyGauge.app"
111
+ ```
112
+
113
+ 仅在修改图标母版后运行 `Scripts/generate-icons.mjs`(需要 Node.js);它会重建两端全部尺寸的图标资源。
114
+
115
+ 构建结果位于 `build/ProxyGauge.app`,分享包位于
116
+ `dist/ProxyGauge-<版本>-macOS-arm64.zip`。应用采用 ad-hoc 签名,尚未使用 Developer ID
117
+ 签名或 Apple 公证。
118
+
119
+ ### 分享预编译版本
120
+
121
+ 推荐从 GitHub Releases 分享一个 macOS ZIP 和两个 Windows MSI,而不是分享源码、App 目录或
122
+ `Scripts/` 目录:
123
+
124
+ - `ProxyGauge-<版本>-macOS-arm64.zip`
125
+ - `ProxyGauge-<版本>-win-x64.msi`
126
+ - `ProxyGauge-<版本>-win-arm64.msi`
127
+
128
+ 用户可从 GitHub Releases 下载对应安装包与 `SHA256SUMS.txt`,并在运行前核对校验值。
129
+
130
+ Mac 用户解压后把 `ProxyGauge.app` 移到“应用程序”即可;正常图形功能所需的检查脚本、规则
131
+ 和管理员助手已包含在 App 内,不需要运行 `install.sh`。由于当前版本没有 Apple 公证,首次
132
+ 打开可能被 Gatekeeper 拦截;只应在确认下载来源与 `SHA256SUMS.txt` 校验值后,到“系统
133
+ 设置 → 隐私与安全性”选择“仍要打开”。面向更广泛用户公开分发前,应补齐 Developer ID
134
+ 签名与公证。
135
+
136
+ macOS 首次启动会优先从 Mihomo 本地控制 socket、macOS 系统代理和 Clash Verge Rev 根设置
137
+ 文件中识别当前 mixed 端口,并展示“代理客户端 → 本地入口 → 流量模式”供用户一次确认。
138
+ 自动检测只提取端口与运行模式,不读取或保存订阅 URL、节点、UUID、密码或密钥;检测失败
139
+ 时才显示只允许本机回环地址的手动端口输入。确认结果保存在 ProxyGauge 自己的 macOS 偏好
140
+ 中,标题栏的连接设置按钮可以随时重新检测。
141
+
142
+ 分享包不包含代理客户端、订阅、节点、服务器地址或个人配置。朋友仍需自行安装并配置
143
+ Mihomo/Clash Verge;PF Kill Switch 的脚本和默认规则随 App 提供,但只有用户主动打开开关并
144
+ 确认管理员授权后才会安装和启用。
145
+
146
+ ### 安装
147
+
148
+ ```bash
149
+ Scripts/install.sh
150
+ ```
151
+
152
+ 默认安装到 `~/Applications/ProxyGauge.app`,辅助脚本安装到:
153
+
154
+ - `~/.local/bin/proxygauge-check`
155
+ - `~/.local/bin/proxygauge-ip-risk.jxa`
156
+ - `~/.local/bin/proxygauge-chain-check.jxa`
157
+ - `~/.local/bin/proxygauge-killswitch`
158
+ - `~/.local/share/proxygauge/`
159
+
160
+ 这些外部脚本用于命令行调用和旧版兼容;图形应用正常运行会优先使用 App Bundle
161
+ 内置副本,因此单独移动 `ProxyGauge.app` 不会丢失链路检测或管理员助手。
162
+
163
+ ### 配置
164
+
165
+ 普通 macOS 图形用户不需要创建配置文件;首次引导确认的本地入口会直接传给 App 内置脚本。
166
+ 下面的文件仅用于开发者命令行和高级链式出口;运行安装脚本时会创建:
167
+
168
+ ```text
169
+ ~/.config/proxygauge/config
170
+ ```
171
+
172
+ 主要配置项:
173
+
174
+ ```bash
175
+ PROXYGAUGE_MIXED="127.0.0.1:7890"
176
+ PROXYGAUGE_EXPECT_IP="" # 可选:校验准确的代理出口 IP
177
+ PROXYGAUGE_SECONDARY_ENABLED="0" # 普通单出口保持关闭
178
+ PROXYGAUGE_SECONDARY_LABEL="Google / Gemini / Claude" # 预填模板,可改名
179
+ PROXYGAUGE_SECONDARY_GROUP="Google-Chain"
180
+ PROXYGAUGE_DEFAULT_GROUP="PROXY"
181
+ PROXYGAUGE_SECONDARY_MIXED="127.0.0.1:7891"
182
+ PROXYGAUGE_SECONDARY_DOMAINS="gemini.google.com,generativelanguage.googleapis.com,www.google.com,claude.ai,api.anthropic.com,platform.claude.com,bridge.claudeusercontent.com"
183
+ PROXYGAUGE_EXPECT_SECONDARY_IP="" # 可选:校验额外出口基线
184
+ PROXYGAUGE_ACTIVE_AI_PROBES="0" # 默认关闭:不主动请求任何 AI 平台
185
+ ```
186
+
187
+ 安装与运行只使用 `com.valenlan.proxygauge`、`ProxyGauge`、`proxygauge` 和
188
+ `PROXYGAUGE_*` 标识,不维护旧产品名、旧配置路径或旧环境变量兼容。
189
+
190
+ 仓库不包含任何真实服务器地址或个人配置。
191
+
192
+ 如果启用了独立链式出口,仅检查策略组和规则命中还不够。当前预填模板使用
193
+ [`Rules/ProxyGauge-Google-Chain-Probe.yaml`](Rules/ProxyGauge-Google-Chain-Probe.yaml)
194
+ 中的 `listeners` 合并到 Mihomo 活动配置后,ProxyGauge 会通过只监听
195
+ `127.0.0.1:7891` 的专用 mixed 入口查询实际出口,并在报告中并排显示默认出口与
196
+ 额外出口。该示例入口固定绑定 `Google-Chain`,不会临时切换策略组,也不会暴露到局域网;
197
+ 其他用户可以在“链路检测 → 方案”中替换成自己的策略组、端口和域名。
198
+
199
+ ### 可选:PF Kill Switch
200
+
201
+ 首页 Kill Switch 是持久的“开启 / 关闭”开关,不收集服务器 IP、网卡或其他规则参数。
202
+ 全新 Mac 第一次开启时,ProxyGauge 使用 App 内置模板自动识别物理接口,并确认 Mihomo 核心
203
+ 由系统服务运行;随后在一次管理员授权中校验 anchor 与临时主配置、备份 `/etc/pf.conf`、
204
+ 安装规则并立即开启。任一步失败都会保持关闭并回滚本次安装。
205
+
206
+ 应用启动和普通状态刷新不会请求管理员权限,也不会修改 PF。
207
+
208
+ 用户开启 Kill Switch 后,helper 会把一份 root-owned 恢复程序安装到
209
+ `/Library/PrivilegedHelperTools/com.valenlan.proxygauge.killswitch`,并注册
210
+ `/Library/LaunchDaemons/com.valenlan.proxygauge.killswitch.plist`。开启意图以 root-only 标记
211
+ 保存在 `/var/db/proxygauge/enabled`;LaunchDaemon 在启动时以及运行中每 15 秒校验已有 anchor、
212
+ 物理接口和 PF enable reference。用户主动关闭时会同时清除该标记,因此开启和关闭状态都会
213
+ 跨应用退出与系统重启保持。界面读取 `/var/run/proxygauge-killswitch.state` 的 root-owned 运行
214
+ 状态,并同时核对当前启动周期的 PF reference,不沿用重启前的绿色缓存。
215
+
216
+ PF 会影响整台 Mac 的联网行为,因此自动安装只允许 root 身份运行的代理核心和其他 root
217
+ 系统服务经物理接口联网;普通应用必须走本机代理或 TUN,用户进程也没有独立的 53 端口直连
218
+ 例外。显式开启时还会清理物理接口已有的 PF 连接状态,使旧连接重新经过新规则。命令行用户
219
+ 也可以运行同一套无参数安装流程:
220
+
221
+ ```bash
222
+ Scripts/install-pf.sh
223
+ ```
224
+
225
+ 该脚本会:
226
+
227
+ 1. 生成 `/etc/pf.anchors/proxygauge`
228
+ 2. 在当前 `/etc/pf.conf` 中注册 `anchor "proxygauge"`
229
+ 3. 先检查 anchor 与系统 PF 配置语法,再安装配置
230
+ 4. 首次执行时备份 `/etc/pf.conf.proxygauge.bak`
231
+
232
+ 命令行安装会自动识别接口,只写入内置规则并保持关闭;完成后由 ProxyGauge 开关启用。
233
+
234
+ Kill Switch 仅支持 `proxygauge` anchor。已有其他 anchor 的系统需要先单独完成清理和
235
+ 迁移;ProxyGauge 不会自动叠加第二套 PF 规则。
236
+
237
+ 当前 Kill Switch 的信任边界是代理核心本身:macOS PF 需要允许 root-owned Mihomo 与系统服务
238
+ 出站,Windows WFP 需要允许 mixed 端口对应的 Mihomo 可执行文件。因此它能阻止普通应用在代理
239
+ 停止或入口失效后回退直连,但不能阻止代理核心自身执行 `DIRECT`。ProxyGauge 不读取订阅和节点,
240
+ Mihomo 的本地状态接口也不能稳定给出所有活动传输的最终物理端点;项目不会猜测节点 IP 并建立
241
+ 可能导致永久断网的出口白名单。只有未来能原子获得并验证完整端点集合时,才会加入这种严格模式。
242
+
243
+ ## Windows
244
+
245
+ Windows 版位于 [`Windows/`](Windows/),使用 .NET 10 WPF,不依赖第三方 UI 框架。
246
+
247
+ ### 使用预编译版本
248
+
249
+ 1. 在 GitHub Releases 下载 `ProxyGauge-<版本>-win-x64.msi`;ARM Windows 下载
250
+ `ProxyGauge-<版本>-win-arm64.msi`,并使用 `SHA256SUMS.txt` 核对文件
251
+ 2. 运行 MSI;安装时授权一次管理员权限,用于安装自动启动的 Guard Service
252
+ 3. 从开始菜单运行 ProxyGauge,确认 mixed 地址与端口,再明确开启“系统保护”
253
+
254
+ MSI 内的界面和系统服务都是 self-contained,朋友的电脑无需预装 .NET。Windows 首次运行
255
+ 未经代码签名的个人应用时,SmartScreen 可能显示提醒。
256
+
257
+ ### 本地构建
258
+
259
+ 需要 .NET 10 SDK、CMake、MSVC 和 Windows 11:
260
+
261
+ ```powershell
262
+ dotnet publish Windows/ProxyGauge.Windows.csproj `
263
+ --configuration Release `
264
+ --runtime win-x64 `
265
+ --self-contained true
266
+ ```
267
+
268
+ Windows 配置保存在:
269
+
270
+ ```text
271
+ %APPDATA%\ProxyGauge\config.json
272
+ ```
273
+
274
+ Windows Guard 使用系统自带 Windows Filtering Platform,不安装内核驱动。保护开启时,
275
+ 服务只给当前启用用户建立规则:允许回环代理、实际监听 mixed 端口的代理核心和已识别的
276
+ TUN 接口,拦截其余 IPv4/IPv6 直连。规则属于 WFP 持久对象,不依赖 WPF 界面进程:关闭
277
+ 窗口、退出界面、用户注销或界面崩溃都不会解除拦截;重启后由自动启动服务校验和修复。
278
+
279
+ 只有主界面的明确“关闭”操作或管理员紧急恢复命令会永久解除保护。若界面不可用,在管理员
280
+ 终端运行:
281
+
282
+ ```powershell
283
+ & "C:\Program Files\ProxyGauge\ProxyGauge.Guard.exe" --emergency-off
284
+ ```
285
+
286
+ 如果该文件也损坏,管理员可执行 `sc.exe config ProxyGaugeGuard start= disabled` 后重启;
287
+ BFE 在启动时不会装载属于已禁用服务的持久 provider 规则。这是最后恢复手段,不是日常开关。
288
+
289
+ 卸载程序会先停止服务并执行同样的清理;若无法完整移除持久规则,卸载会失败而不是遗留
290
+ 一个无法恢复的半卸载状态。
291
+
292
+ ## 发布
293
+
294
+ 每次 push 与 pull request 都会构建并测试 macOS、Windows x64 和 Windows ARM64。只有推送与
295
+ 应用版本完全一致的 `v<版本>` 标签时,工作流才会把一个 macOS ZIP 和两个 Windows MSI 暂存
296
+ 为 Actions artifacts,创建 GitHub Release,并上传这些安装包与 `SHA256SUMS.txt`。临时 artifacts
297
+ 只保留 1 天;正式安装包由 Release 长期保存。例如当前版本对应的发布标签应为 `v1.5.6`。
298
+
299
+ 创建标签会产生正式发布结果,必须在全部本地测试和普通 push CI 通过后由维护者明确执行;
300
+ 构建脚本本身不会自动创建标签。
301
+
302
+ 这里的 GitHub Release 指正式版的发布页和安装包,不是测试版。工作流不会创建草稿或
303
+ Pre-release,并会把新版本标记为 Latest;只有 Latest 正式版才会被上面的一行安装器选中。
304
+
305
+ ## 参与贡献与安全报告
306
+
307
+ - 开发环境、测试要求和 pull request 清单见 [`CONTRIBUTING.md`](CONTRIBUTING.md)。
308
+ - 安全问题请按 [`SECURITY.md`](SECURITY.md) 私下报告,不要在公开 issue 中附带漏洞细节、
309
+ 真实订阅、节点、出口 IP 或个人配置。
310
+ - 构建和发布涉及的第三方组件及随安装包分发的许可文件见
311
+ [`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md)。
312
+
313
+ ## 许可证
314
+
315
+ ProxyGauge 采用 [`MIT License`](LICENSE) 开源。MIT 许可证允许他人使用、复制、修改、合并、
316
+ 发布和分发,但要求在副本或主要部分中保留版权与许可声明;软件按原样提供,不附带任何保证。
317
+ 许可证本身不能替代对代码、图标、文案和第三方依赖授权来源的确认。
318
+
319
+ ## 隐私与安全
320
+
321
+ - 链路检测会通过已配置的本地代理访问公开 IP 查询服务和测试站点。
322
+ - 默认链路检测不会请求 Claude、ChatGPT、Gemini 的网页或 API。启用额外分流模板后,规则
323
+ 命中从本机 Mihomo 运行时读取,链路延迟使用中性 204 地址,实际出口通过专用本地入口
324
+ 访问公开 IP 查询服务确认。只有用户显式把 `PROXYGAUGE_ACTIVE_AI_PROBES` 设为 `1` 时,
325
+ macOS 才会主动请求三个 AI API;即使启用,也不会自动访问账号网页。
326
+ - 出口一致性检查会把默认代理出口分别提交给 `api.ipify.org`、`ifconfig.me` 与 `ip.sb`;
327
+ 启用额外出口探针时,也会经该用户设置的本地入口访问同一组服务。只有至少两个
328
+ 来源给出一致结果才算完成交叉验证。
329
+ - 常规链路检测不再把出口 IP 提交给风险情报服务,也不生成“纯净度”结论;它只通过
330
+ `api.ipify.org`、`ifconfig.me` 与 `ip.sb` 交叉确认实际出口。
331
+ - IPPure、IPCheck.ing、BrowserLeaks、IPQS、Scamalytics 与 AbuseIPDB 只作为用户主动点击并再次确认的
332
+ 复核入口,ProxyGauge 不会在后台自动访问。确认框会明确说明即将弹出系统默认浏览器;部分网站
333
+ 可能要求完成人机验证。它们必须在真实浏览器上下文中运行,才能同时
334
+ 观察当前出口、WebRTC、DNS、IPv6、时区和指纹一致性。各站使用的数据库、风险定义与更新
335
+ 周期不同,结果应交叉阅读,不能视为目标平台的官方判定。
336
+ - 用户确认后,ProxyGauge 会先经已确认的本地 mixed 入口查询当前出口 IP,仅用于生成
337
+ `scamalytics.com/ip/<IP>` 与 `abuseipdb.com/check/<IP>` 两个直达结果链接;查询失败时不打开
338
+ 这两个需要参数的入口,避免落到要求再次输入 IP 的首页。其余 4 个站点由网页识别当前访问 IP。
339
+ - ProxyGauge 不读取 Claude、ChatGPT 等网站的登录 Cookie 或账户资料,也不会把账户判断
340
+ 塞进常规链路报告。账户状态只能由用户在自己的正常登录会话中确认。
341
+ - 链路分只汇总当前检测方案:通用方案按核心、端口、入口与出口四段归一化;启用额外分流后
342
+ 才加入策略、规则与第二出口权重。提示扣对应部分一半权重,失败扣全部权重;关键入口失败时
343
+ 最高为 49 分。它不是网速、纯净度、匿名性或账户安全评分。
344
+ - macOS 的“IP 纯净度复核”先询问用户,确认后读取当前代理出口并通过系统默认浏览器打开 6 个站点。它沿用用户
345
+ 当前浏览器会话与实际网络路径,不创建临时资料目录、不指定进程专属代理,也不改动系统代理。
346
+ 用户需要自行完成人机验证并交叉阅读各站结果;ProxyGauge 不自动抓取、汇总或计分。
347
+ - ProxyGauge 不上传配置,不收集遥测,也不保存浏览记录。
348
+ - macOS 管理员权限仅用于读取或修改 ProxyGauge 自己的 PF anchor,以及安装和维护上述
349
+ root-owned 开机恢复 helper、LaunchDaemon 与启用标记。
350
+ - Windows 日常界面不请求管理员权限;MSI 只在安装/卸载 LocalSystem Guard Service 时请求。
351
+ Guard 直接管理 ProxyGauge 自己的 WFP provider/sublayer,不修改 Windows Firewall 的默认策略。
352
+ - 发布前请不要提交 `~/.config/proxygauge/config`。
353
+
354
+ ## 项目状态
355
+
356
+ 这是一个面向个人最新 macOS 与 Windows 11 环境的小工具。不同代理客户端、端口和 PF
357
+ 网络接口可能需要调整配置。旧版操作系统不在测试和维护范围内。
@@ -0,0 +1,138 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ REPOSITORY="ValenLan/ProxyGauge"
5
+ INSTALL_DIR="$HOME/Applications"
6
+ DESTINATION="$INSTALL_DIR/ProxyGauge.app"
7
+ TEMP_DIR=$(/usr/bin/mktemp -d "${TMPDIR:-/tmp}/proxygauge-release.XXXXXX")
8
+ STAGE_DIR=""
9
+ BACKUP_APP="$TEMP_DIR/ProxyGauge.previous.app"
10
+
11
+ cleanup() {
12
+ status=$?
13
+ trap - EXIT
14
+
15
+ if { [ -e "$BACKUP_APP" ] || [ -L "$BACKUP_APP" ]; } && \
16
+ { [ ! -e "$DESTINATION" ] && [ ! -L "$DESTINATION" ]; }; then
17
+ /bin/mv "$BACKUP_APP" "$DESTINATION" || true
18
+ fi
19
+
20
+ if [ -n "$STAGE_DIR" ] && [ -d "$STAGE_DIR" ]; then
21
+ /bin/rm -rf "$STAGE_DIR"
22
+ fi
23
+ /bin/rm -rf "$TEMP_DIR"
24
+ exit "$status"
25
+ }
26
+ trap cleanup EXIT
27
+
28
+ if [ "$(/usr/bin/uname -s)" != "Darwin" ] || [ "$(/usr/bin/uname -m)" != "arm64" ]; then
29
+ echo "ProxyGauge 正式版仅支持 Apple Silicon Mac。" >&2
30
+ exit 1
31
+ fi
32
+
33
+ REQUESTED_VERSION=${PROXYGAUGE_VERSION:-}
34
+ if [ -n "$REQUESTED_VERSION" ]; then
35
+ if [[ ! "$REQUESTED_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
36
+ echo "无效的 ProxyGauge 指定版本:$REQUESTED_VERSION" >&2
37
+ exit 1
38
+ fi
39
+ VERSION=$REQUESTED_VERSION
40
+ TAG="v$VERSION"
41
+ else
42
+ LATEST_URL=$(/usr/bin/curl \
43
+ --proto '=https' \
44
+ --tlsv1.2 \
45
+ --location \
46
+ --silent \
47
+ --show-error \
48
+ --fail \
49
+ --retry 3 \
50
+ --output /dev/null \
51
+ --write-out '%{url_effective}' \
52
+ "https://github.com/$REPOSITORY/releases/latest")
53
+ TAG=${LATEST_URL##*/}
54
+
55
+ if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
56
+ echo "无法从 GitHub 识别最新正式版标签:$TAG" >&2
57
+ exit 1
58
+ fi
59
+ VERSION=${TAG#v}
60
+ fi
61
+
62
+ ASSET="ProxyGauge-$VERSION-macOS-arm64.zip"
63
+ RELEASE_BASE="https://github.com/$REPOSITORY/releases/download/$TAG"
64
+ ARCHIVE="$TEMP_DIR/$ASSET"
65
+ CHECKSUMS="$TEMP_DIR/SHA256SUMS.txt"
66
+
67
+ download() {
68
+ source_url=$1
69
+ destination_path=$2
70
+ /usr/bin/curl \
71
+ --proto '=https' \
72
+ --tlsv1.2 \
73
+ --location \
74
+ --silent \
75
+ --show-error \
76
+ --fail \
77
+ --retry 3 \
78
+ --output "$destination_path" \
79
+ "$source_url"
80
+ }
81
+
82
+ echo "正在下载 ProxyGauge $TAG 正式版…"
83
+ download "$RELEASE_BASE/$ASSET" "$ARCHIVE"
84
+ download "$RELEASE_BASE/SHA256SUMS.txt" "$CHECKSUMS"
85
+
86
+ EXPECTED_SHA=$(/usr/bin/awk -v asset="$ASSET" '
87
+ length($1) == 64 && $1 ~ /^[0-9A-Fa-f]+$/ {
88
+ name = $2
89
+ sub(/^\*/, "", name)
90
+ if (name == asset) {
91
+ print tolower($1)
92
+ exit
93
+ }
94
+ }
95
+ ' "$CHECKSUMS")
96
+ ACTUAL_SHA=$(/usr/bin/shasum -a 256 "$ARCHIVE" | /usr/bin/awk '{ print tolower($1) }')
97
+
98
+ if [ -z "$EXPECTED_SHA" ] || [ "$ACTUAL_SHA" != "$EXPECTED_SHA" ]; then
99
+ echo "SHA-256 校验失败,安装已停止。" >&2
100
+ exit 1
101
+ fi
102
+
103
+ EXTRACT_DIR="$TEMP_DIR/extracted"
104
+ /bin/mkdir -p "$EXTRACT_DIR"
105
+ /usr/bin/ditto -x -k "$ARCHIVE" "$EXTRACT_DIR"
106
+ EXTRACTED_APP="$EXTRACT_DIR/ProxyGauge.app"
107
+
108
+ if [ ! -x "$EXTRACTED_APP/Contents/MacOS/ProxyGauge" ]; then
109
+ echo "正式版压缩包缺少可执行的 ProxyGauge.app。" >&2
110
+ exit 1
111
+ fi
112
+
113
+ /usr/bin/codesign --verify --deep --strict --verbose=2 "$EXTRACTED_APP"
114
+ BUNDLE_VERSION=$(/usr/libexec/PlistBuddy \
115
+ -c 'Print :CFBundleShortVersionString' \
116
+ "$EXTRACTED_APP/Contents/Info.plist")
117
+ if [ "$BUNDLE_VERSION" != "$VERSION" ]; then
118
+ echo "App 版本 $BUNDLE_VERSION 与正式版标签 $TAG 不一致。" >&2
119
+ exit 1
120
+ fi
121
+
122
+ /bin/mkdir -p "$INSTALL_DIR"
123
+ STAGE_DIR=$(/usr/bin/mktemp -d "$INSTALL_DIR/.proxygauge-install.XXXXXX")
124
+ STAGED_APP="$STAGE_DIR/ProxyGauge.app"
125
+ /usr/bin/ditto "$EXTRACTED_APP" "$STAGED_APP"
126
+
127
+ if [ -e "$DESTINATION" ] || [ -L "$DESTINATION" ]; then
128
+ /bin/mv "$DESTINATION" "$BACKUP_APP"
129
+ fi
130
+
131
+ /bin/mv "$STAGED_APP" "$DESTINATION"
132
+ if [ -e "$BACKUP_APP" ] || [ -L "$BACKUP_APP" ]; then
133
+ /bin/rm -rf "$BACKUP_APP"
134
+ fi
135
+
136
+ echo "已安装 ProxyGauge $TAG:$DESTINATION"
137
+ echo "可在 Finder 的个人目录 → Applications 中打开。"
138
+ echo "当前正式版采用 ad-hoc 签名且尚未公证;脚本不会绕过 macOS 安全检查。"
@@ -0,0 +1,118 @@
1
+ $ErrorActionPreference = "Stop"
2
+ $ProgressPreference = "SilentlyContinue"
3
+ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
4
+
5
+ $Repository = "ValenLan/ProxyGauge"
6
+ $MinimumWindowsBuild = 22000
7
+
8
+ if (-not [Environment]::Is64BitOperatingSystem) {
9
+ throw "ProxyGauge 正式版仅支持 64 位 Windows 11。"
10
+ }
11
+
12
+ $BuildText = (Get-ItemProperty `
13
+ "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" `
14
+ -Name CurrentBuild).CurrentBuild
15
+ $WindowsBuild = 0
16
+ if (-not [int]::TryParse($BuildText, [ref]$WindowsBuild) -or $WindowsBuild -lt $MinimumWindowsBuild) {
17
+ throw "ProxyGauge 正式版仅支持 Windows 11,不支持 Windows 10 或 Windows Server。"
18
+ }
19
+
20
+ $NativeArchitecture = if ($env:PROCESSOR_ARCHITEW6432) {
21
+ $env:PROCESSOR_ARCHITEW6432
22
+ } else {
23
+ $env:PROCESSOR_ARCHITECTURE
24
+ }
25
+
26
+ $Runtime = switch ($NativeArchitecture.ToUpperInvariant()) {
27
+ "AMD64" { "win-x64" }
28
+ "ARM64" { "win-arm64" }
29
+ default { throw "不支持的 Windows 架构:$NativeArchitecture" }
30
+ }
31
+
32
+ $Headers = @{
33
+ Accept = "application/vnd.github+json"
34
+ "User-Agent" = "ProxyGauge-Release-Installer"
35
+ "X-GitHub-Api-Version" = "2022-11-28"
36
+ }
37
+ $RequestedVersion = $env:PROXYGAUGE_VERSION
38
+ $ReleaseUri = "https://api.github.com/repos/$Repository/releases/latest"
39
+ if (-not [string]::IsNullOrWhiteSpace($RequestedVersion)) {
40
+ if ($RequestedVersion -notmatch '^\d+\.\d+\.\d+$') {
41
+ throw "无效的 ProxyGauge 指定版本:$RequestedVersion"
42
+ }
43
+ $ReleaseUri = "https://api.github.com/repos/$Repository/releases/tags/v$RequestedVersion"
44
+ }
45
+ $Release = Invoke-RestMethod `
46
+ -Uri $ReleaseUri `
47
+ -Headers $Headers
48
+
49
+ if ($Release.draft -or $Release.prerelease -or $Release.tag_name -notmatch '^v\d+\.\d+\.\d+$') {
50
+ throw "GitHub 返回的版本不是 ProxyGauge 正式版。"
51
+ }
52
+ if (-not [string]::IsNullOrWhiteSpace($RequestedVersion) -and `
53
+ $Release.tag_name -ne "v$RequestedVersion") {
54
+ throw "GitHub 返回的版本 $($Release.tag_name) 与指定版本 v$RequestedVersion 不一致。"
55
+ }
56
+
57
+ $Version = $Release.tag_name.Substring(1)
58
+ $AssetName = "ProxyGauge-$Version-$Runtime.msi"
59
+ $InstallerAssets = @($Release.assets | Where-Object { $_.name -eq $AssetName })
60
+ $ChecksumAssets = @($Release.assets | Where-Object { $_.name -eq "SHA256SUMS.txt" })
61
+
62
+ if ($InstallerAssets.Count -ne 1 -or $ChecksumAssets.Count -ne 1) {
63
+ throw "正式版缺少 $AssetName 或 SHA256SUMS.txt。"
64
+ }
65
+
66
+ $TempDirectory = Join-Path ([IO.Path]::GetTempPath()) `
67
+ ("proxygauge-release-" + [Guid]::NewGuid().ToString("N"))
68
+ New-Item -ItemType Directory -Path $TempDirectory | Out-Null
69
+
70
+ try {
71
+ $MsiPath = Join-Path $TempDirectory $AssetName
72
+ $ChecksumPath = Join-Path $TempDirectory "SHA256SUMS.txt"
73
+
74
+ Write-Host "正在下载 ProxyGauge $($Release.tag_name) 正式版…"
75
+ Invoke-WebRequest `
76
+ -UseBasicParsing `
77
+ -Uri $InstallerAssets[0].browser_download_url `
78
+ -OutFile $MsiPath
79
+ Invoke-WebRequest `
80
+ -UseBasicParsing `
81
+ -Uri $ChecksumAssets[0].browser_download_url `
82
+ -OutFile $ChecksumPath
83
+
84
+ $ChecksumText = Get-Content -Raw -Path $ChecksumPath
85
+ $ChecksumPattern = "(?im)^([0-9a-f]{64})\s+\*?$([regex]::Escape($AssetName))\s*$"
86
+ $ChecksumMatch = [regex]::Match($ChecksumText, $ChecksumPattern)
87
+ if (-not $ChecksumMatch.Success) {
88
+ throw "SHA256SUMS.txt 中没有 $AssetName 的有效校验值。"
89
+ }
90
+
91
+ $ExpectedSha = $ChecksumMatch.Groups[1].Value.ToLowerInvariant()
92
+ $ActualSha = (Get-FileHash -Algorithm SHA256 -Path $MsiPath).Hash.ToLowerInvariant()
93
+ if ($ActualSha -ne $ExpectedSha) {
94
+ throw "SHA-256 校验失败,安装已停止。"
95
+ }
96
+
97
+ Write-Host "校验通过。Windows 将请求管理员权限以安装正式版和 Guard Service。"
98
+ $Installer = Start-Process `
99
+ -FilePath "msiexec.exe" `
100
+ -Verb RunAs `
101
+ -ArgumentList @("/i", "`"$MsiPath`"", "/passive", "/norestart") `
102
+ -Wait `
103
+ -PassThru
104
+
105
+ if ($Installer.ExitCode -notin @(0, 3010)) {
106
+ throw "MSI 安装失败,退出代码:$($Installer.ExitCode)"
107
+ }
108
+
109
+ Write-Host "已安装 ProxyGauge $($Release.tag_name) 正式版。"
110
+ if ($Installer.ExitCode -eq 3010) {
111
+ Write-Host "Windows 要求重启后完成安装。"
112
+ }
113
+ Write-Host "当前正式版尚未购买代码签名证书;脚本不会绕过 Windows 安全检查。"
114
+ } finally {
115
+ if (Test-Path -LiteralPath $TempDirectory) {
116
+ Remove-Item -LiteralPath $TempDirectory -Recurse -Force
117
+ }
118
+ }
@@ -0,0 +1,86 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { spawnSync } from "node:child_process";
5
+
6
+ export const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
7
+
8
+ export function packageVersion(root = projectRoot) {
9
+ const metadata = JSON.parse(readFileSync(resolve(root, "package.json"), "utf8"));
10
+ if (!/^\d+\.\d+\.\d+$/.test(metadata.version)) {
11
+ throw new Error(`不支持的 npm 包版本:${metadata.version}`);
12
+ }
13
+ return metadata.version;
14
+ }
15
+
16
+ export function installCommand(platform, architecture, root = projectRoot) {
17
+ if (platform === "darwin" && architecture === "arm64") {
18
+ return {
19
+ executable: "/bin/bash",
20
+ arguments: [resolve(root, "Scripts/install-release-macos.sh")],
21
+ label: "macOS arm64"
22
+ };
23
+ }
24
+
25
+ if (platform === "win32" && ["x64", "arm64"].includes(architecture)) {
26
+ return {
27
+ executable: "powershell.exe",
28
+ arguments: [
29
+ "-NoLogo",
30
+ "-NoProfile",
31
+ "-NonInteractive",
32
+ "-File",
33
+ resolve(root, "Scripts/install-release-windows.ps1")
34
+ ],
35
+ label: `Windows ${architecture}`
36
+ };
37
+ }
38
+
39
+ throw new Error(
40
+ `ProxyGauge 不支持当前平台:${platform}/${architecture}。` +
41
+ "支持 Apple Silicon Mac、Windows 11 x64 和 Windows 11 ARM64。"
42
+ );
43
+ }
44
+
45
+ export function shouldRunPostinstall(environment) {
46
+ if (environment.PROXYGAUGE_FORCE_INSTALL === "1") {
47
+ return true;
48
+ }
49
+ return environment.npm_config_global === "true";
50
+ }
51
+
52
+ export function runNativeInstaller({
53
+ platform = process.platform,
54
+ architecture = process.arch,
55
+ environment = process.env,
56
+ root = projectRoot,
57
+ dryRun = environment.PROXYGAUGE_INSTALL_DRY_RUN === "1"
58
+ } = {}) {
59
+ const version = packageVersion(root);
60
+ const command = installCommand(platform, architecture, root);
61
+
62
+ if (dryRun) {
63
+ console.log(
64
+ `ProxyGauge npm 安装器检查通过:将为 ${command.label} 安装 GitHub Release v${version}。`
65
+ );
66
+ return 0;
67
+ }
68
+
69
+ const result = spawnSync(command.executable, command.arguments, {
70
+ cwd: root,
71
+ env: {
72
+ ...environment,
73
+ PROXYGAUGE_VERSION: version
74
+ },
75
+ stdio: "inherit",
76
+ windowsHide: false
77
+ });
78
+
79
+ if (result.error) {
80
+ throw result.error;
81
+ }
82
+ if (result.status !== 0) {
83
+ throw new Error(`ProxyGauge 原生安装器退出,代码:${result.status ?? "unknown"}`);
84
+ }
85
+ return 0;
86
+ }
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ packageVersion,
5
+ runNativeInstaller,
6
+ shouldRunPostinstall
7
+ } from "./proxygauge-npm-lib.mjs";
8
+
9
+ function printHelp() {
10
+ console.log(`ProxyGauge npm installer
11
+
12
+ Usage:
13
+ proxygauge install Reinstall the native app matching this npm package version
14
+ proxygauge --version Print the package version
15
+ proxygauge --help Show this help`);
16
+ }
17
+
18
+ function main() {
19
+ const argumentsList = process.argv.slice(2);
20
+ const postinstall = argumentsList.includes("--postinstall");
21
+ const command = argumentsList.find((argument) => !argument.startsWith("--")) ?? "install";
22
+
23
+ if (postinstall && !shouldRunPostinstall(process.env)) {
24
+ console.log(
25
+ "ProxyGauge 桌面应用只在全局安装时自动安装;请运行 npm install -g proxygauge。"
26
+ );
27
+ return;
28
+ }
29
+
30
+ if (["--version", "-v", "version"].some((argument) => argumentsList.includes(argument))) {
31
+ console.log(packageVersion());
32
+ return;
33
+ }
34
+
35
+ if (["--help", "-h", "help"].some((argument) => argumentsList.includes(argument))) {
36
+ printHelp();
37
+ return;
38
+ }
39
+
40
+ if (command !== "install") {
41
+ throw new Error(`未知命令:${command}`);
42
+ }
43
+
44
+ runNativeInstaller();
45
+ }
46
+
47
+ try {
48
+ main();
49
+ } catch (error) {
50
+ console.error(`ProxyGauge 安装失败:${error.message}`);
51
+ process.exitCode = 1;
52
+ }
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "proxygauge",
3
+ "version": "1.5.6",
4
+ "description": "Open-source native proxy health, route verification, and leak-protection dashboard for macOS and Windows 11.",
5
+ "license": "MIT",
6
+ "author": "ValenLan",
7
+ "type": "module",
8
+ "preferGlobal": true,
9
+ "bin": {
10
+ "proxygauge": "Scripts/proxygauge-npm.mjs"
11
+ },
12
+ "scripts": {
13
+ "test": "node --test Tests/npm-installer.test.mjs",
14
+ "postinstall": "node Scripts/proxygauge-npm.mjs install --postinstall",
15
+ "prepack": "npm test"
16
+ },
17
+ "files": [
18
+ "LICENSE",
19
+ "README.md",
20
+ "README.en.md",
21
+ "Scripts/install-release-macos.sh",
22
+ "Scripts/install-release-windows.ps1",
23
+ "Scripts/proxygauge-npm-lib.mjs",
24
+ "Scripts/proxygauge-npm.mjs"
25
+ ],
26
+ "engines": {
27
+ "node": ">=18"
28
+ },
29
+ "os": [
30
+ "darwin",
31
+ "win32"
32
+ ],
33
+ "cpu": [
34
+ "arm64",
35
+ "x64"
36
+ ],
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/ValenLan/ProxyGauge.git"
40
+ },
41
+ "homepage": "https://github.com/ValenLan/ProxyGauge#readme",
42
+ "bugs": {
43
+ "url": "https://github.com/ValenLan/ProxyGauge/issues"
44
+ },
45
+ "keywords": [
46
+ "proxy",
47
+ "mihomo",
48
+ "clash-verge",
49
+ "macos",
50
+ "windows"
51
+ ]
52
+ }