实现 .NET 10 托盘版网关保活

包含分层探测、可补偿的 IPv4 路由/DNS 切换、自动策略、托盘与分组设置界面、只读诊断工具、离线测试和发布脚本。
This commit is contained in:
chuzhongzai
2026-10-23 23:35:20 +08:00
parent 59a2982b2c
commit 2d85527656
57 changed files with 8623 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
# 网络修改与恢复
## 修改范围
仅处理显式选择网卡的 IPv4 `0.0.0.0/0` 默认路由和 IPv4 接口 DNS。不会修改 IPv6、代理注册表、网卡 IP 地址、其他网卡、VPN 或特定前缀路由。
旁路由模式为目标网关准备 metric 1 的默认路由,保留该网卡原路由并把其他受管默认路由 metric 至少提高到 101。直连模式采取相同优先级策略。Windows 有效 metric 还包含接口 metric;最终通过全机有效选路和绑定源 IP 的 TLS 探测验证,若 VPN / 其他路径抢占则不冒报切换成功。
路由位于活动配置,未主动写入持久路由。DHCP 更新或外部程序更改配置时,快照比较会阻止继续覆盖,需核对设置后重新保存以接管。未连接网卡不累计旁路由故障计数。
## 网络身份
未接管诊断使用 Windows 网络配置文件 ID;接管后使用网卡 GUID、IPv4 子网与已配置主路由的 ARP 硬件地址作为网络指纹,防止本程序更换默认网关导致 NLM 配置文件变化而误判换网。无法验证主路由身份时拒绝写入。该识别用于避免误操作,不是抵御恶意局域网的身份认证。
同一网络内接口索引变化也会停止复用旧快照。静态 DNS 与自动 DNS 分开保存;默认直连恢复接管时的真实 DNS,也可明确选择自动/静态直连 DNS。网络配置文件层的 DNS 不覆盖。
## 切换日志
写入前持久化 `switch-journal.json`,保存 Before/Intended 与阶段。新路由先准备,再改变优先级和 DNS,最后读回并验证出口;只有控制状态已落盘才删除切换日志。补偿只接受仍处于该事务前值/目标值组合的现场,发现外部路由或 DNS 不继续覆盖。
程序崩溃后不会有仍在运行的恢复服务。下次启动显示“需恢复”,点击恢复处理未完成切换。记录包含原网卡、路由与 DNS,请在查清故障前保留。
## 手动核对
以管理员 PowerShell 读取当前网卡、默认路由和 DNS:
```powershell
Get-NetAdapter
Get-NetRoute -AddressFamily IPv4 -DestinationPrefix '0.0.0.0/0'
Get-DnsClientServerAddress -AddressFamily IPv4
```
与 `session.json` 中的 Baseline 和 `switch-journal.json` 中的 Before 比较。恢复具体接口时只处理快照中该接口的具体路由行,不删除全机默认路由。DNS 的 `Automatic=true` 表示恢复自动获取,否则恢复 Servers 中原有顺序。优先使用程序的恢复功能,它会验证接口、网络身份、操作归属和读回结果。
如网络已经改变或原主路由无法识别,程序会拒绝自动重放。先由使用者在 Windows 网络设置中修复连通性,再核对配置并重新接管;不要删日志来强行跳过恢复保护。
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

+26
View File
@@ -0,0 +1,26 @@
# 验证记录
日期:2026-10-23。环境:Windows 10/11 x64,开发机网卡 `以太网`(索引 16),IPv4 地址 `192.168.6.119/24`,主路由 `192.168.6.1`。
## 已实际验证
- 解决方案 Debug/Release 构建:0 警告、0 错误(`TreatWarningsAsErrors` 已开启)。
- 核心离线测试:45/45 通过,覆盖状态机计数与冷却、切换故障补偿、外部修改保护、跨网络恢复拒绝、无变化跳过写入、持久的暂停状态、Stop 恢复基线、写入前现场复核、原子 JSON 持久化与原生结构布局。
- 探测离线测试:16/16 通过,覆盖 SOCKS5 分片/截断/慢读取消/多种地址类型、DNS 压缩与 TCP 回退、畸形响应、指定 DNS 与系统 DNS 分离、旁路由候选不依赖当前出口、按实际网关选择出口探测目标。
- 只读诊断:成功读取网卡、IPv4 默认路由、DNS 配置和有效选路;`NativeLayout` 为 104/168/64 字节,路由 metric 偏移 84,接口 metric 偏移 148,与 x64 SDK 结构一致。运行前后系统网关保持 `192.168.6.1`。
- 切换计划预演(`--dry-run --proxy`):生成目标 metric 1 的旁路由默认路由,原主路由降为 metric 101,DNS 指向 `192.168.6.2`,未写系统。
- 真实分层探测:主路由 TLS 出口 2/2 通过;`192.168.6.2` 的 TCP/DNS/SOCKS 探测超时,判为旁路由不可用,符合当前设备实际状态。
- 发布包:依赖运行时单文件约 490 KB,独立单文件约 116 MB;两者托盘 `--preview` 均能启动并输出 10 张界面图,无异常输出;独立版只读诊断通过。
- 界面预览渲染:主面板正常/故障回退/未配置、诊断展开,设置三页及滚动后状态,均在 200% 缩放下检查过无裁切、无浅色系统控件。
## 未验证,需真机确认
以下都需要真实管理员的网络写入,本次刻意未执行,以免改变用户当前网络:
- 实际切换到旁路由并读回路由/DNS/出口;旁路由断开后的自动回退;恢复后回切旁路由。
- 旁路由 DNS 正常但默认转发失效、SOCKS5 正常但转发失效等不对称故障。
- VPN 或其他网卡同时持有默认路由、DHCP 续租、拔插网线、休眠唤醒后的行为。
- 登录后最高权限计划任务的创建、注销/重启后启动,以及程序移动路径后的重新设置。
- 崩溃后重启识别未完成切换日志的实际恢复流程。
首次在目标机启用前,建议先运行发布的 `diagnostics/GatewayKeepalive.Cli.exe --diagnose`,确认网卡 GUID、主/旁路由和 DNS 与计划一致,再用 `--dry-run` 核对计划,最后通过托盘界面保存并手动启用自动保活。