Files
pangolin/docs/p1-macos-system-extension.md
T
wangjia b25c8bbc2c
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
feat(client/macos): P1 方案B 骨架 — System Extension + NETunnelProviderManager 接线
把 PoC 的 sudo sing-box 外部二进制换成自包含、免 root 的 NEPacketTunnelProvider
(System Extension)+ 嵌入 libbox 的生产架构铺好骨架(不破坏现有 PoC 构建)。

- PacketTunnel/:扩展 target 源 — PacketTunnelProvider(LibboxSetup→NewService→start,
  openTun 建 NEPacketTunnelNetworkSettings)、Info.plist(NEProviderClasses)、
  entitlements(packet-tunnel-provider-systemextension + App Group)
- Runner/VpnChannel.swift:主 app 经 NETunnelProviderManager 启停 + 状态/速率回传,
  对齐 Dart 侧 VpnNativeBridge 的 pangolin/vpn channel 契约
- vpn_bridge_provider.dart:kUseNativeVpnMacOS 开关(默认 false,联调通过后置 true)
- docs/p1-macos-system-extension.md:文件清单 + Xcode/签名步骤 + 待办
  (Team BYL4KQHMTN;Network Extensions 已确认自助开通、无需 Apple 审批)

非破坏:新源文件未入 build target、注册行/app-group entitlements 均注释、gate 默认 false。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:07:36 +08:00

99 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P1 · macOS System Extension 接线指南(方案B)
> 状态:**骨架已落**(本仓库)。把 PoC 的 `sudo sing-box run` 外部二进制换成自包含、免 root
> 的 NEPacketTunnelProvider(System Extension)+ 嵌入式 libbox。本文档列清单 + 待人工在
> Xcode/开发者后台完成的步骤。总览见 [vpn-core-embedding.md](./vpn-core-embedding.md)。
## 0. 关键标识(已确定)
| 项 | 值 |
|---|---|
| Team ID | **BYL4KQHMTN** |
| 主 app bundle id | `com.pangolin.pangolin`(App ID 已注册,勾 Network Extensions + App Groups)|
| 隧道扩展 bundle id | `com.pangolin.pangolin.tunnel`(**待注册**,同样勾 Network Extensions + App Groups)|
| App Group | `group.com.pangolin.pangolin`(**待在 Identifiers → App Groups 注册**)|
| 分发方式 | 站外 Developer ID + 公证(非 App Store)→ entitlement 用 `-systemextension` 后缀 |
| 权限审批 | **无需**——Network Extensions 在 Identifiers 自助勾选即得(Packet Tunnel Provider 已 GA)|
## 1. 仓库里已就位的文件(骨架)
```
client/macos/
├─ Runner/
│ ├─ DebugProfile.entitlements / Release.entitlements ← application-groups 已备(注释,待 §3.6 解开)
│ ├─ MainFlutterWindow.swift ← VpnChannel 注册行已备(注释,待 §3.6 解开)
│ └─ VpnChannel.swift ← 主app:NETunnelProviderManager 启停+状态/速率回传(待加入 target)
└─ PacketTunnel/ ← 新 System Extension target 的源
├─ PacketTunnelProvider.swift ← 扩展:LibboxSetup→NewService→start;openTun 建 TUN
├─ PacketTunnel.entitlements ← packet-tunnel-provider-systemextension + app group
└─ Info.plist ← NEProviderClasses → PacketTunnelProvider
client/lib/bridge/
├─ vpn_bridge.dart ← VpnNativeBridge(method/event channel,已存在)
└─ vpn_bridge_provider.dart ← kUseNativeVpnMacOS 开关(默认 false;原生就绪后置 true)
```
**Channel 契约**(`VpnNativeBridge``VpnChannel`):
- MethodChannel `pangolin/vpn`:`start(configJson)` / `stop` / `getStatus` / `selectOutbound(tag)` / `getActiveOutbound` / `setKillSwitch(bool)`
- EventChannel `pangolin/vpn/status`:状态字符串(`on`/`connecting`/`off`/…)
- EventChannel `pangolin/vpn/stats`:每秒一帧 `{up, down, uplinkTotal, downlinkTotal}`
## 2. 开发者后台(你来做,几分钟)
1. **App Group**:Identifiers → App Groups → `group.com.pangolin.pangolin`
2. 回到 App ID `com.pangolin.pangolin`**App Groups** capability → Edit → 勾上该 group。
3. 新建 App ID `com.pangolin.pangolin.tunnel`(扩展)→ 勾 **Network Extensions** + **App Groups**(关联同一 group)。
4. **Developer ID Application** 证书(Certificates → ,若还没有)——签名 + 公证用。
## 3. Xcode:新增 System Extension target + 接 libbox(核心人工步骤)
> Flutter 工程开 `client/macos/Runner.xcworkspace`。
1. **编 libbox**:`bash scripts/build-libbox.sh apple macos` → 得 `Libbox.xcframework`(~204MB,不入 git)。
2. **新 target**:File → New → Target → **Network Extension**(macOS)→ Packet Tunnel
- Product Name:`PacketTunnel`,bundle id `com.pangolin.pangolin.tunnel`,语言 Swift。
- 删掉模板生成的 `PacketTunnelProvider.swift`,把 `client/macos/PacketTunnel/` 下的三个文件
加入该 target(Provider/Info.plist/entitlements);Info.plist 与 entitlements 设为本 target 用。
3. **链接 libbox**:把 `Libbox.xcframework` 拖进工程,在 **PacketTunnel** target 的
*Frameworks and Libraries* 加入(Embed & Sign);解开 `PacketTunnelProvider.swift`
`import Libbox` 与被注释的真实接线段(`LibboxSetup`/`LibboxNewService`/`service.start()`)。
4. **补平台接口**:`PangolinPlatformInterface``LibboxPlatformInterfaceProtocol` 的完整实现
(openTun / writeLog / useProcFS / findConnectionOwner / defaultInterfaceMonitor /
getInterfaces / underNetworkExtension / systemCertificates …)——**对照官方
[sing-box-for-apple `ExtensionPlatformInterface`](https://github.com/SagerNet/sing-box-for-apple)
逐方法移植**(NE 部分两端高度一致,可大段复用)。这是 P1 唯一"重"的代码块。
5. **sysex 激活**:`VpnChannel.activateSystemExtensionIfNeeded()`
`OSSystemExtensionRequest.activationRequest(forExtensionWithIdentifier: tunnelBundleId, queue:)`
+ delegate 等结果;首启用户在「系统设置 → 隐私与安全性」点允许。
6. **接主 app(Runner)**:
-`client/macos/Runner/VpnChannel.swift` 加入 **Runner** target 的 *Compile Sources*
- 解开 `MainFlutterWindow.swift``VpnChannel.register(...)` 那行注释。
- 解开 `Runner/DebugProfile.entitlements``Release.entitlements``application-groups` 注释块
(注册 App Group 后)。
> 这三处在仓库里**有意保持注释/未接**,以免在 target/签名就绪前破坏现有 PoC 构建。
7. **签名**:两个 target(Runner + PacketTunnel)都用 Team **BYL4KQHMTN** + Developer ID;
开 Hardened Runtime;Runner 的 *System Extensions* capability 自动带出。
## 4. 速率/状态联调(libbox CommandServer)
- 扩展内 `LibboxNewCommandServer`(loopback)暴露状态/速率/连接;主 app 用 `LibboxCommandClient`
订阅 → 回填 `pangolin/vpn/stats``…/status`(替换 `VpnChannel` 里的占位 timer)。
- 连接页(`connect_page.dart`)与统计页已消费这两路流,**无需改动**。
## 5. 切换上线
- 全部联调通过(连真节点、出口 IP=节点、速率/延迟、Kill Switch、退出拆隧道、明暗/中英)后,
`vpn_bridge_provider.dart``kUseNativeVpnMacOS`**true**
- PoC 的 `DesktopVpnBridge`(sudo 子进程)保留作 fallback/调试,不删。
## 6. 待办清单(TODO,代码内已标 `TODO(P1)`)
- [ ] 开发者后台:App Group + 扩展 App ID + Developer ID 证书(§2)
- [ ] Xcode:新 PacketTunnel target + 加入 `Libbox.xcframework`(§3.13.3)
- [ ] 解开 `PacketTunnelProvider.swift` 真实接线 + 移植 `PangolinPlatformInterface`(§3.4)
- [ ] `OSSystemExtensionRequest` 激活流程(§3.5)
- [ ] `LibboxCommandClient` 接速率/状态(§4)
- [ ] `setKillSwitch` / `selectOutbound` 真实实现
- [ ] 签名 + 公证流水线(Team BYL4KQHMTN)
- [ ] 联调通过 → `kUseNativeVpnMacOS = true`(§5)