Commit Graph

18 Commits

Author SHA1 Message Date
wangjia 002eea7562 build(scripts): build-libbox apple 按平台分发产物,避免覆盖另一端 Frameworks
只编某一平台时(apple macos / apple ios),产出的 xcframework 只含该平台 slice,
不能覆盖到另一平台的 client/*/Frameworks(否则那端 build 缺 slice)。改为:
空(全 Apple)→ macos+ios 都放;macos→只 macos;ios→只 ios。
本次 iOS 打包已验证只部署到 client/ios/Frameworks。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 09:37:09 +08:00
wangjia b23377acde build(scripts): 各端 libbox 构建脚本修正 + 自动部署产物
排查 Android 打包"libbox.aar not found / Unresolved reference nekohasekai"踩坑:
- scripts/build-libbox.sh:
  · 构建后自动部署产物到工程引用位置(android→app/kernel/dist/android/libbox.aar;
    apple→client/{macos,ios}/Frameworks/Libbox.xcframework),不再留 /tmp 让人手动拷
  · android 自动挑 NDK ≥28(未设 ANDROID_NDK_HOME 时):官方 build_libbox 拉 cronet-go,
    其 libcronet.a 在 NDK 27 lld 链接报 unknown relocation(315)失败
  · 头注释补全前置(NDK≥28 / JDK17 / gomobile 入 PATH)与产物路径
- app/kernel/build-android.sh:补 -javapkg io.nekohasekai —— 缺它产出默认包名 `libbox`,
  与 Kotlin 的 io.nekohasekai.libbox 对不上、APK Kotlin 编译失败
- build.gradle:注释指明两条构建途径 + 包名必须 io.nekohasekai.libbox

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 07:53:35 +08:00
wangjia 97c0fdbbad test(macos): local_test.sh 加 killswitch fail-closed 漏测子命令
ks-baseline:VPN 断开下记录真实公网 IP 基线
ks-test:VPN 连接(killswitch 开)下 sudo 杀扩展进程,在 on-demand 重连
  窗口内反复探 IP —— 任何一次拿到真实 IP 即判泄漏(FAIL),全程被阻断/
  仅隧道 IP 即 fail-closed 生效(PASS);随后验 on-demand 自愈
ks-status:看 VPN 状态 + 统一日志里 killSwitch/includeAllNetworks 打点

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 00:01:51 +08:00
wangjia 63bb31066f test(ci): 闸1 接缝脚手架 new-seam.sh(支柱1:让对的写法成默认)
预防式闸:一条命令生成「接口 + Impl + Fake + Riverpod provider + flow-test 桩」,
外部依赖从一开始就藏接口后、可注入、自带 Fake、可测——把支柱1 变成阻力最小路径。
- scripts/new-seam.sh <PascalName> [lib子目录]
- 验证:生成样例 SampleProbe → flutter analyze 无 issue + test 过 → 清理

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 12:17:58 +08:00
wangjia c5223af4a1 test(ci): L3 golden 权威环境脚本(进 CI 前置准备)
golden 真进 CI 卡两个硬约束:Linux/mac 渲染不一致(mac 基线在 CI 全红)+ 基线绑定
stats-overhaul dirty 工作区。本提交备好权威环境,不裹挟 dirty、不破坏:
- scripts/update-goldens.sh:在 CI 同款镜像 cirruslabs/flutter 重生成 Linux 权威基线
  (开发者改 UI 后用它刷新,而非裸 mac --update-goldens,保持与 CI 一致)
- docs/test-architecture.html:L3 现状更新 + 列明启 CI 硬闸的两个前置条件
- 真启闸需:有 docker 的机器生成并提交 Linux 基线 + dirty 工作区合并(本机无 docker)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 12:16:16 +08:00
wangjia fd82d82fe3 test(e2e): 第5刀b L4 gRPC 全链路(enroll→ReportUsage→统计真入库真读出)
在 HTTP 段基础上接 gRPC mTLS 全链路,真验证「统计准不准」:
- 脚本:生成 Node CA + gRPC server 证书(镜像 deploy.sh)、起 server 带 gRPC、
  nodectl 签 bootstrap token,传 E2E_GRPC_ADDR/CA/token/node 给 driver
- driver:复用 agentd.EnsureEnrolled 真 TCP enroll → enroll 到的 client cert
  建 mTLS → ReportUsage 注入 1GiB/100MiB(dp_uuid=用户) → 轮询 /v1/usage
  断言 bytes_up=1GiB·bytes_down=100MiB 真入库真读回
- 本地全链路绿;go build ./... 不受影响(tag e2e)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 07:04:26 +08:00
wangjia b3cbeef7cf test(e2e): 第5刀a L4 进程级冒烟编排 + HTTP 段
真起 server 二进制(sqlite + Redis)跑 HTTP 用户旅程,验证 in-process 测试给不了的
信心(二进制起/迁移/路由/鉴权/DB 端到端):
- scripts/e2e-smoke.sh:起栈编排(Redis 三选一:已有 addr / docker / 内嵌 miniredis
  兜底)+ 随机端口 + trap 清理;调 Go driver
- server/test/e2e/smoke_test.go (tag e2e):造用户(复用 argon2 HashPassword)
  → 登录 → /v1/me(dp_uuid/plan/email) → /v1/usage 鉴权 + 无 token 401
- server/test/e2e/miniredis (tag e2e):无 docker 时 Redis 兜底 launcher
- 本地绿;go build/test ./...(无 tag)仍 25 包绿,tag e2e 文件被静默跳过

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 06:59:39 +08:00
wangjia 306d8e5247 Merge branch 'main' into worktree-monitor-debounce
# Conflicts:
#	scripts/vpn_test.py
2026-06-22 15:08:11 +08:00
wangjia 7a4d0cf7cd fix(diag): host 参数走 base64 避免 GFW 拦明文敏感词诊断请求
控制面跑明文 HTTP 在国外 IP 上,白盒诊断请求 URL 里出现 google/youtube 等 GFW
敏感词时被墙重置(返回空)→ 出海段拿不到、报告显示「—」。改:host 用 base64url
传(host_b64),响应也回 b64、不回明文,明文里无敏感词(不影响真实加密隧道流量)。

- diag.go: EgressTiming 支持 ?host_b64=,解码后查白名单,响应 echo b64
- vpn_whitebox.py: node_egress 用 base64url 编码 host

验证:cara(墙内)google/youtube 出海段从 None → 8-9ms,与 github/cloudflare 一致。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 14:34:05 +08:00
wangjia a19406d041 feat(test): VPN 黑盒/白盒测试工具 + 索引页 + 链路时序图与阶段拆解
- vpn_test.py(黑盒):站点矩阵连通/延迟(TLS 握手口径)/吞吐,落 tests/vpn/runs/
  并重建 index.html 索引(内嵌 meta、file:// 直开);索引含 cara→LA→Google 时序图
  + 步骤表
- vpn_whitebox.py(白盒):双 IP-echo 判国内是否被隧道 + 五段拆解;经控制面
  /v1/diag/egress 取出海段,自动算「接入段=整轮−出海段」,报告出「阶段拆解」表
  (对应时序图 橙=接入 / 绿=出海)
- tests/vpn/: runs 与生成的 index.html 为本地工件(.gitignore),README 说明用法
- docs/: vpn-testing-research.md(调研)+ vpn-test-plan.md(黑盒/白盒方案)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 14:12:46 +08:00
wangjia 98ba2b411e test: VPN 黑盒测试工具改用 Python(零依赖)+ HTML 报告 + 国内外站点矩阵
- scripts/vpn_test.py:替换 vpn_test.sh。纯标准库(socket/ssl/urllib),覆盖国内外
  常见站点矩阵(google/youtube/github/x/fb/ig/wiki/cloudflare/openai/reddit;
  百度/腾讯/淘宝/京东/B站/微博/网易/知乎/阿里云),测连通+延迟+TTFB+DNS+出口IP+吞吐,
  本机连通性(tun/系统扩展),生成自包含 HTML 报告(-o)。
- 延迟标准 = TLS 握手耗时(ssl 握手,纯链路往返),报告里标注 "TTL=按 TLS 计算、非 IP TTL";
  TTFB 作参考。禁用 ping/tcp_connect(经 TUN 本地应答失真)。
- 删除 scripts/vpn_test.sh;文档引用同步更新为 .py。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEHzjEcFzvGwgbxT6Wbt6c
2026-06-22 09:43:46 +08:00
wangjia 8fcc4e8b75 docs+test: VPN 测试方案(黑盒+白盒)+ 修正延迟测量方法
- docs/vpn-test-plan.md:黑盒+白盒两方向测试方案。白盒细化:链路五段拆解、
  协议/出站选择(Clash API)、接入段 vs 出海段分段 RTT、连接/流量、稳定性
  (长跑/Kill switch/GFW 三元组封锁与被动探测/热重载)。含初轮报告:cara 黑盒
  15 PASS;吞吐 国内直连 74Mbps vs 国外经隧道 ~10-17Mbps(瓶颈在出海段)。
- scripts/vpn_test.sh:修正延迟测量——经 TUN 代理时 ping/tcp_connect 被隧道本地
  应答(2-4ms 假象),改用 TLS 握手(time_appconnect)/ TTFB 作为真实 RTT。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEHzjEcFzvGwgbxT6Wbt6c
2026-06-22 09:17:00 +08:00
wangjia 2d2baf887c docs+test: macOS 隧道踩坑复盘/规则 + VPN 测试调研 + 黑盒测试工具
- docs/macos-sysext-realize-troubleshooting.html:补"运行时"章节(libbox 空指针、
  接口时序、队列死锁、DNS 劫持)+ 运行时 checklist。
- docs/vpn-testing-research.md:VPN 测试调研(行业方法论 + GFW 专项 + Pangolin
  分层测试项 + 三层测试工具设计)。
- CLAUDE.md:新增「client/ macOS 原生隧道」铁律章节(构建发版/系统扩展 realize 要求/
  libbox+NE 集成/配置由服务端渲染/已知坑)。
- scripts/vpn_test.sh:客户端侧黑盒测试工具(出口 IP/DNS/可达性/延迟/吞吐/IPv6 泄漏,
  PASS/WARN/FAIL,可远程跑)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEHzjEcFzvGwgbxT6Wbt6c
2026-06-22 09:00:10 +08:00
wangjia 447f3f494e feat(client/macos): P1 原生隧道——PacketTunnel 系统扩展可加载 + libbox 运行
经长链路排查(同机对照可工作的 Tailscale),修复 macOS 系统扩展 realize
失败(OSSystemExtensionErrorDomain code=4)与 libbox 运行时崩溃,使内嵌
sing-box 的系统扩展能在 macOS 15 上激活并启动隧道。

系统扩展 realize(三个叠加根因):
- 扩展自包含:PacketTunnel 加 OTHER_LDFLAGS="" 切断对项目级 CocoaPods 链接
  标志的继承(原会把 flutter_secure_storage 链进扩展);Libbox.xcframework
  改纯 Link(静态),从 Embed Frameworks 移除冗余内嵌
- bundle 名 = 标识符:PRODUCT_NAME 设为 com.pangolin.pangolin.PacketTunnel
- 扩展 Info.plist 补 NSSystemExtensionUsageDescription(网络扩展类别强制要求)
- App Group 改 macOS 原生格式 BYL4KQHMTN.com.pangolin.pangolin;NEMachServiceName
  以其为前缀;扩展补 network.client/server;get-task-allow=false + 签名加 --timestamp
- CFBundleVersion 随构建递增(否则 sysextd 视为同版本不更新)

libbox 运行时:
- startOrReloadService(options:) 传 nil 致空指针 SIGSEGV → 传 LibboxOverrideOptions()
- 默认接口监控阻塞到首个 path 更新再返回,修 "no available network interface"

配套:
- scripts/local_test.sh:build/sign/notarize/copy/run 一条龙(Developer ID + 公证)
- client/macos/sign_libbox.sh:构建期以 Developer ID 重签内嵌 Libbox
- VpnChannel:401 自动刷新 token、详尽 os_log;auth/api 统一走 kApiBaseUrl
- docs/macos-sysext-realize-troubleshooting.html:完整踩坑复盘

WIP / 临时(后续清理):
- 隧道运行时仍在排查:剥离远程 rule-set 后 sing-box 启动卡点未定位
- 含临时诊断代码:main.swift stderr 重定向、box.log 输出、rule-set 剥离、debug 日志
- api_config 仍指向联调节点,发版前还原

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEHzjEcFzvGwgbxT6Wbt6c
2026-06-21 21:18:33 +08:00
wangjia 236e33aef9 feat(scripts): P0 完成 — libbox 嵌入式核心构建脚本(方案B)
scripts/build-libbox.sh:用 sagernet/gomobile fork v0.1.12 + sing-box v1.13.13
+ 官方 build_libbox,一键编出 Libbox.xcframework(Apple)/ Libbox.aar(Android)。
已本地跑通 macOS:双架构(arm64+x86_64)xcframework,Headers 暴露 LibboxNewService /
LibboxCommandClient(状态·速率)等 API。产物不入 git(~204MB),按需重编。
docs/vpn-core-embedding.md 标记 P0 完成。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:07:02 +08:00
wangjia 51a5170b9e feat(scripts): 新增 speedtest.sh 隧道测速/质量验证工具
连上 pangolin 后一键测:出口IP确认 / 客户端→节点真实路径(绑en0绕隧道,
RTT+丢包) / 经隧道TTFB / Cloudflare 下行+上行带宽;--node 可 ssh 节点测
其自身出口带宽做理论上限对照。零依赖(curl+ping)。

实测节点(RackNerd 512MB/1核,LA):下行~22-24 / 上行~25 Mbps,RTT 298ms,
0% 丢包(晚高峰偶发瞬时丢包)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 22:48:44 +08:00
wangjia bdf67cb56e fix(client-config): 加 route.default_domain_resolver(sing-box 1.12+ 必需)
sing-box 1.13 对缺失 default_domain_resolver 直接 FATAL。加 {"server":"local"}
后,节点下发的整份客户端配置经 `sing-box check` 验证通过(无 FATAL/废弃)。
顺带 local_test.sh:免密已生效则跳过(不再反复要密码)+ --no-build 快速重跑。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 21:35:50 +08:00
wangjia 25c7bd75aa feat(client+scripts): release 本地真测 — local_test.sh + 内核查找加 /opt/homebrew
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
- scripts/local_test.sh:一键构建 release macOS 包 + 配 sing-box 免密 sudoers
  (TUN 需 root)+ 前台运行真身(日志直出),让本地测试 = release 线上行为
- kernel_process 二进制查找兜底加 /opt/homebrew/bin/sing-box(Apple Silicon
  brew),release 包从 Finder/直接启动也能找到内核,免设 PANGOLIN_SINGBOX_BIN

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 21:09:08 +08:00