diff --git a/design/prototype/screens/routing-rules.html b/design/prototype/screens/routing-rules.html new file mode 100644 index 0000000..fa8990f --- /dev/null +++ b/design/prototype/screens/routing-rules.html @@ -0,0 +1,163 @@ + + +
+ + +Task 3 原型(用 v2 真实设计系统重建:全走 atoms.css / tokens.css / icons.js,非独立 mockup)。让用户像 Shadowrocket 那样自定义"直连 / 走隧道 / 拒绝"。规则模型与实现见 配置说明文档。
{ "domain_suffix":
+ ["git.51yanmei.com"],
+ "outbound": "direct" }| 类型 | 值 | 动作 | 说明 | 启用 | |
|---|---|---|---|---|---|
| ≡ | 域名后缀 | git.51yanmei.com | 直连 | CI 源 | |
| ≡ | 域名后缀 | aliyun.com | 直连 | 镜像 | |
| ≡ | 域名后缀 | github.com | 走隧道 | — | |
| ≡ | GeoSite | category-ads | 拒绝 | 广告 | |
| ≡ | IP-CIDR | 35.190.0.0/16 | 走隧道 | — |
本屏所有组件(段选 .segswitch、设置行 .setting-row、开关 .toggle、卡片 .card、胶囊 .pill、按钮 .btn)都来自 v2 设计系统真原子,颜色全走 token,与线上 App 一致——不是独立 mockup。动作语义色(直连绿/走隧道橙/拒绝红)是原型内联,实现时收进 atoms。
①规则粒度够不够 ②要不要分应用代理(per-app,建议后置)③「从文本导入」Phase 1 还是 2 ④档案 per-user 还是 per-device。确认后出 Phase 1 实现计划。
Task 3 设计 · 让用户像 Shadowrocket 那样自定义路由规则(哪些直连 / 走隧道 / 拒绝)。
+配套视觉原型:交互原型 → · 状态:设计待确认(未开发)
+ +当前 pangolin 客户端的分流是服务端固定渲染的:LAN 直连、DNS 劫持、可选国内分流(geoip/geosite-cn)、私有域名走隧道,用户无法自定义。实际需求(如 CI 编译源、公司内网、某些国内站要直连;某些站要强制走隧道;广告要拒绝)无处配置——这次暴露的「CI 流量被灌进隧道拖垮小节点」就是典型。
+本设计给用户一套可配置路由规则,心智模型对齐 Shadowrocket 的 [Rule] 段:有序规则表,首命中生效,动作三选一(直连 / 走隧道 / 拒绝)。
ARCHITECTURE.md §3.1:Dart/Flutter 客户端不得自行拼装或修改 sing-box 配置——配置一律服务端渲染、原样下发。所以"客户端可配置"不能变成"客户端本地改 config"。解法:用户在 App 编规则 → 存为服务端 per-user「路由档案(routing profile)」→ connect 时服务端把档案翻译进渲染的配置。客户端只负责编辑 UI + 存/取档案,永不碰 sing-box JSON。
+App 规则编辑器 ──PUT /v1/routing-profile──▶ 服务端存 per-user 档案(DB)
+ │
+App 点连接 ──POST /v1/nodes/{id}/connect──▶ BuildClientConfig(读档案→翻译成 route.rules)
+ │
+App ◀────────── 完整 sing-box 配置(含用户规则)─────┘ 原样喂内核
+
+ 一条规则 = { type, value, action, note?, enabled }。整个档案:
{
+ "mode": "rule", // global | rule | direct(对齐 shadowrocket 三模式)
+ "builtin": {
+ "china_direct": true, // 国内分流(geoip-cn/geosite-cn → 直连)开关
+ "lan_direct": true, // LAN/私网直连(强制,不可关)
+ "private_via_tunnel": true // 私有服务域名走隧道(服务端下发,不可关)
+ },
+ "rules": [ // 用户自定义,有序,首命中生效
+ { "type": "domain_suffix", "value": "git.51yanmei.com", "action": "direct", "note": "CI 源", "enabled": true },
+ { "type": "geosite", "value": "category-ads", "action": "reject" },
+ { "type": "ip_cidr", "value": "35.190.0.0/16", "action": "proxy" }
+ ],
+ "final": "proxy" // 兜底:未命中任何规则的动作
+}
+
+ | type | 值示例 | sing-box 字段 |
|---|---|---|
domain | example.com | domain(精确) |
domain_suffix | aliyun.com | domain_suffix(含子域) |
domain_keyword | domain_keyword | |
ip_cidr | 35.190.0.0/16 · ::/0 | ip_cidr(v4/v6) |
geoip | CN · US | rule_set(自托管 geoip-*.srs) |
geosite | cn · netflix · category-ads | rule_set(自托管 geosite-*.srs) |
| action | outbound | 说明 |
|---|---|---|
| direct | direct | 物理网卡直连(配合 route_exclude/reverse_mapping 真直连) |
| proxy | auto | 经节点(REALITY/Hy2 urltest 择优) |
| reject | block | 阻断 |
服务端把规则按固定层级拼进 route.rules,自上而下首命中:
PANGOLIN_PRIVATE_SPLIT_DOMAINS)· 服务端rules[] 顺序展开)← 新增china_direct 开时)final:proxy / direct)direct outbound 让 sing-box 从物理网卡直接出连接。但 TUN strict_route 会把包重新捕回隧道——已有两个机制解决,用户规则复用:
route_exclude_address(在 auto_route 层排除,已用于 LAN)。用户加的 ip_cidr → direct 需同步进 route_exclude,否则被 strict_route 抓回。dns.reverse_mapping(记 IP↔域名,按 IP 连接时补回域名元数据让 domain 规则命中)+ local DNS(223.5.5.5,国内解析)。已用于私有域名分流,机制现成。| 端点 | 作用 |
|---|---|
GET /v1/routing-profile | 拉当前用户档案(App 编辑器初始化;无则返回内置默认) |
PUT /v1/routing-profile | 保存档案(服务端校验:CIDR 合法、type 合法、条数上限、去重) |
POST …/connect(现有) | 渲染时读该用户档案,翻译进 route.rules |
档案存 DB(routing_profiles 表:user_id · profile_json · updated_at),不走 connect body(与现有 split_cn 走 query 的约束一致——大规则集不塞 query/body)。客户端本地也缓存一份(离线可看/编,连接时以服务端为准)。
ip_cidr 可解析、type 在白名单、geosite/geoip 值在自托管规则集清单内、总条数 ≤ 上限(如 200)。非法整体拒绝(4xx + 逐条错误),不半保存。| 现有 | 本设计如何吸收 |
|---|---|
| SplitCN(geoip/geosite-cn 直连,#5) | 降为档案里的 builtin.china_direct 开关(层级 5) |
| PrivateSplitDomains(走隧道) | 保留为系统层 3(服务端 env,用户不可动) |
| route_exclude_address(LAN) | 保留 + 扩展:用户 ip_cidr→direct 规则动态并入 |
| reverse_mapping / local DNS | 复用:域名直连规则靠它命中 |
换句话说,本设计是把三个散落的分流机制统一收进一个用户可见、可配的规则模型,底层复用已验证的 sing-box 手法。
+ +确认这份设计后,我用 writing-plans 出 Phase 1 的实现计划(TDD、多端、服务端翻译逐条测),再开发。