Files
pangolin/app/kernel/poc/reality_client.config.json.tmpl
wangjia 83dd5369ab feat(M4/M5): URLTest 自动选线 + Kill-switch + 弹性重连 [tsk_xAQhC1xuCd8x]
M4 URLTest 自动选线:
- ClashApiClient.getGroupDelay() — GET /group/<name>/delay 触发按需测速
- ClashApiClient.extractUrltestResults() — 从 /proxies 响应解析 URLTest
  组成员最新延迟,填充 stats 帧的 urltestResults 字段
- DesktopKernelProcess._startStatsPoll() — 每秒并行拉取连接统计 + URLTest
  延迟(_clashApi.getProxies()),URLTest 失败不影响主统计
- DesktopVpnBridge.selectOutbound(tag) — Clash API PUT /proxies/proxy,
  tag 可传节点 tag 或 urltest 组 tag(如 "auto-select")恢复自动
- DesktopVpnBridge.getActiveOutbound() — GET /proxies 读 proxy.now
- app/kernel/poc/reality_client.config.json.tmpl — 增加 urltest("auto-select")
  + selector("proxy") 出口组,route.final 改为 "proxy"

M5 Kill-switch + 弹性重连:
- DesktopVpnBridge.setKillSwitch({required bool on}) — 将 _killSwitchEnabled
  写入 TUN inbound strict_route 字段(applyKillSwitchToConfig);内核运行中
  触发静默重载(kill → start(lastConfig))
- DesktopVpnBridge.applyKillSwitchToConfig() — static,killSwitch=true ↔
  TUN strict_route=true,killSwitch=false ↔ strict_route=false
- 自动退避重连:kernel 崩溃推 error → _scheduleReconnect() 退避序列
  1s/2s/4s/8s/16s/30s(上限),stop() 取消,重连成功后重置计数器
- DesktopKernelProcess 意外退出清理 _clashApi(避免下次 spawn 残留)
- app/pangolin/test/killswitch_checklist.md — 三端故障注入验收清单
  (Desktop ,iOS/Android 欠账说明)

新增测试(client/test/bridge/desktop_vpn_bridge_m4m5_test.dart):
- M4: extractUrltestResults 解析/空/无 history 边界
- M4: getGroupDelay HTTP 请求格式验证
- M4: selectOutbound / getActiveOutbound Clash API 调用断言
- M5: applyKillSwitchToConfig 字段覆盖 + 无 TUN 边界
- M5: setKillSwitch 状态注入 + 同值幂等
- M5: 崩溃→error 不崩 / 首次重连在退避延迟内触发 / stop 后不再重连

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 00:11:09 +08:00

128 lines
3.1 KiB
Cheetah
Raw Permalink 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.
{
"_comment": "sing-box 客户端配置模板 — VLESS+REALITY+TUNPoC tsk_SLCsjNgtmng3 / M4/M5 tsk_xAQhC1xuCd8x",
"_usage": "渲染脚本: app/kernel/poc/gen-poc-config.sh;占位符一律 __UPPER_SNAKE__",
"_m4_note": "URLTest 自动选线:auto-select(urltest) → 成员节点延迟最低者。手动切换经 Clash API PUT /proxies/proxy",
"log": {
"level": "info",
"timestamp": true
},
"dns": {
"servers": [
{
"tag": "dns-remote",
"address": "tls://1.1.1.1",
"address_resolver": "dns-local",
"detour": "proxy"
},
{
"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": [
{
"_comment": "M4: URLTest 自动选优出口组(成员:所有实际代理节点 tag)",
"type": "urltest",
"tag": "auto-select",
"outbounds": ["reality-out"],
"url": "http://www.gstatic.com/generate_204",
"interval": "3m",
"tolerance": 50
},
{
"_comment": "M4: Selector 出口组(Clash API 操作此组来手动覆盖 / 切回自动)",
"type": "selector",
"tag": "proxy",
"outbounds": ["auto-select", "reality-out"],
"default": "auto-select"
},
{
"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": "proxy",
"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"
}
}
}