3c6a8a517a
实现桌面端(macOS PoC)内核子进程管理,打通 sing-box TUN 模式全链路:
### client/lib/bridge/kernel_process.dart(完整实现,替换原有 stub)
- ClashApiClient: HTTP 客户端,支持 /connections / /proxies / /traffic(SSE) / /traffic(plain)
- Bearer Token 鉴权;getConnections 用于就绪探测与流量统计;getTraffic SSE 读首帧后断开
- KernelProcess 接口: 新增 statusStream / statsStream 至接口定义
- DesktopKernelProcess:
- spawn(configPath): 解析 Clash API 端口/secret → sudo sing-box run(macOS PoC)→
轮询 /connections 等待就绪(20s 超时)→ emit connecting→on
- kill(): SIGTERM + 等待 gracePeriod(5s) → SIGKILL → emit off
- 意外退出: emit error(UI 可一键重连,不崩溃)
- 统计轮询: 每秒 GET /connections,差分算 uploadSpeed/downloadSpeed
- 二进制解析: ENV > exe同目录 > macOS Bundle Resources > 开发目录 > /usr/local/bin
- 辅助函数: generateClashApiPort(高位随机)、generateClashApiSecret(32B hex)
### client/lib/bridge/desktop_vpn_bridge.dart(新文件)
- DesktopVpnBridge implements VpnBridge:
- start(configJson): injectClashApi(注入随机端口+secret)→ writeConfig(0600)→ kernel.spawn
- stop(): kernel.kill(5s)
- statusStream / statsStream: 代理 KernelProcess 事件流
- selectOutbound: Clash API PUT /proxies/{group}
- getActiveOutbound: 从 /proxies 读 now 字段
- configDirOverride: 测试注入支持
- injectClashApi: 静态方法,尊重已有 clash_api 配置,合并保留 experimental 其他字段
### client/test/bridge/kernel_process_test.dart(新文件)
- ClashApiClient 完整测试: headers / 解析 / PUT body / DELETE / 非 200 抛 HttpException
- generateClashApiPort / generateClashApiSecret 生成范围和格式测试
- DesktopVpnBridge.injectClashApi: 注入 / 尊重已有 / 保留字段 / 保留其他 experimental / 非法 JSON
- DesktopVpnBridge + FakeKernelProcess 集成: connecting→on / stop→off / statsStream / 意外退出 / spawn失败
### app/kernel/poc/(新目录)
- reality_client.config.json.tmpl: VLESS+REALITY+TUN 客户端配置模板
- TUN inbound: auto_route + strict_route(macOS kill-switch 基础保护)
- DNS: 防泄露(remote via VPN + cn 直连)
- experimental.clash_api: 随机端口 + secret 占位符
- gen-poc-config.sh: 渲染模板为可用 JSON(从环境变量读 REALITY 参数)
- README.md: 完整 PoC 接线与 M1 验收步骤
提权说明(macOS PoC):
· sudo 提权(开发机需配 /etc/sudoers.d/pangolin-singbox 或有 sudo 缓存)
· 正式版: SMJobBless Helper + 公证(BACKLOG-11D-HELPER)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
111 lines
2.4 KiB
Cheetah
111 lines
2.4 KiB
Cheetah
{
|
||
"_comment": "sing-box 客户端配置模板 — VLESS+REALITY+TUN(PoC tsk_SLCsjNgtmng3)",
|
||
"_usage": "渲染脚本: app/kernel/poc/gen-poc-config.sh;占位符一律 __UPPER_SNAKE__",
|
||
|
||
"log": {
|
||
"level": "info",
|
||
"timestamp": true
|
||
},
|
||
|
||
"dns": {
|
||
"servers": [
|
||
{
|
||
"tag": "dns-remote",
|
||
"address": "tls://1.1.1.1",
|
||
"address_resolver": "dns-local",
|
||
"detour": "reality-out"
|
||
},
|
||
{
|
||
"tag": "dns-local",
|
||
"address": "local",
|
||
"detour": "direct"
|
||
},
|
||
{
|
||
"tag": "dns-block",
|
||
"address": "rcode://success"
|
||
}
|
||
],
|
||
"rules": [
|
||
{ "outbound": "any", "server": "dns-local" },
|
||
{ "geosite": "cn", "server": "dns-local" },
|
||
{ "geoip": "private", "server": "dns-local" }
|
||
],
|
||
"final": "dns-remote",
|
||
"independent_cache": true
|
||
},
|
||
|
||
"inbounds": [
|
||
{
|
||
"type": "tun",
|
||
"tag": "tun-in",
|
||
"inet4_address": "172.19.0.1/30",
|
||
"inet6_address": "fdfe:dcba:9876::1/126",
|
||
"mtu": 1492,
|
||
"auto_route": true,
|
||
"strict_route": true,
|
||
"stack": "system",
|
||
"sniff": true,
|
||
"sniff_override_destination": false
|
||
}
|
||
],
|
||
|
||
"outbounds": [
|
||
{
|
||
"type": "vless",
|
||
"tag": "reality-out",
|
||
"server": "__SERVER_HOST__",
|
||
"server_port": __SERVER_PORT__,
|
||
"uuid": "__UUID__",
|
||
"flow": "xtls-rprx-vision",
|
||
"tls": {
|
||
"enabled": true,
|
||
"server_name": "__REALITY_SNI__",
|
||
"utls": {
|
||
"enabled": true,
|
||
"fingerprint": "chrome"
|
||
},
|
||
"reality": {
|
||
"enabled": true,
|
||
"public_key": "__REALITY_PUBLIC_KEY__",
|
||
"short_id": "__REALITY_SHORT_ID__"
|
||
}
|
||
},
|
||
"packet_encoding": "xudp"
|
||
},
|
||
{
|
||
"type": "direct",
|
||
"tag": "direct"
|
||
},
|
||
{
|
||
"type": "block",
|
||
"tag": "block"
|
||
},
|
||
{
|
||
"type": "dns",
|
||
"tag": "dns-out"
|
||
}
|
||
],
|
||
|
||
"route": {
|
||
"rules": [
|
||
{ "protocol": "dns", "outbound": "dns-out" },
|
||
{ "geosite": "cn", "outbound": "direct" },
|
||
{ "geoip": "cn", "outbound": "direct" },
|
||
{ "geoip": "private", "outbound": "direct" }
|
||
],
|
||
"final": "reality-out",
|
||
"auto_detect_interface": true
|
||
},
|
||
|
||
"experimental": {
|
||
"clash_api": {
|
||
"external_controller": "127.0.0.1:__CLASH_API_PORT__",
|
||
"secret": "__CLASH_API_SECRET__"
|
||
},
|
||
"cache_file": {
|
||
"enabled": true,
|
||
"path": "/tmp/pangolin-poc.db"
|
||
}
|
||
}
|
||
}
|