m-ui 里的“线路”是什么
每个代理面板都得回答"我到底在编辑什么"。多数面板用内核自己的词汇回答:入站、出站、路由规则。m-ui 的回答是一条记录 —— 线路 —— 其余的渲染出来。
定义
线路 = 入口协议 + 端口 → 流量从哪出去,加上该协议需要的选项(TLS 模式、传输层、协议专属字段),以及部署到哪些服务器。整条记录就这些。用户通过分配表挂到线路上;上游按 id 作为出口被引用。
| 字段 | 含义 |
|---|---|
| protocol、port | sing-box 要打开的监听器 —— UDP 24443 上的 Hysteria2、TCP 443 上的 VLESS,等等。 |
| tls | 无、证书(服务器自己的)、或带密钥与握手目标的 Reality。 |
| transport | tcp、WebSocket、gRPC、HTTPUpgrade、HTTP,以及各自的路径与 host。 |
| options | 协议附加项:Hysteria2 的带宽提示、混淆、端口跳跃;Shadowsocks 的加密方法;VLESS 的 Vision 流控。 |
| upstream | 直连,或一条上游记录(另一个代理、WARP)。它会变成出站和路由规则。 |
| servers | 空 = 所有服务器;否则是应当跑这个监听器的那几台副机。 |
渲染做了什么
m-ui 需要某台服务器的配置时 —— 保存、重启、或者给副机推快照 —— 它遍历部署到该服务器的线路,为每条生成:一个 sing-box 入站,带上分配给它的用户(凭据来自用户记录),TLS 为"证书"时带上该服务器自己的证书路径,再加一条把进入这个入站的流量送到线路出口的路由规则。出口各渲染一次成为出站;direct 与 block 是内置的。结果是一份完整的 sing-box JSON,内嵌内核加载它,或者在保存落库前由它的解析器检查它。
渲染是数据库的纯函数,所以线路相同的两台服务器生成相同的入站;线路改一次,下一个 5 秒快照里到处都变。
刻意不放进线路的
- 按用户的路由。用户拿到的是线路,不是各自的规则。按目的地分流在出口(上游)或客户端做,不按用户做。
- 任意的路由表。路由段归面板所有,没有编辑器。多服务器渲染能保持确定性,靠的就是这个。
- sing-box 的每一个选项。表单覆盖支持的协议需要的东西;每条线路有一个"高级"JSON 字段,把额外的入站选项合并进去。
为什么不直接暴露 JSON
三个原因,按跑面板的人被坑的频率排序:
- 跨服务器一致。手工维护的入站会走样;渲染出来的线路不会。加一台副机是"把这条线路部署过去",不是"复制这段再改证书路径"。
- 校验。形状固定的表单能在进内核之前检查;m-ui 还把完整渲染结果在保存事务里交给 sing-box 的解析器,内核启动时会拒绝的,保存时就被拒绝。
- 重载分级。知道一次改动只碰了用户、只碰了上游、还是碰了线路本身,m-ui 才能选热换而不是重启。自由编辑的 JSON 给不了这种信息。
实际后果
- 端口按线路唯一,并对照面板和本机其它进程检查;新线路会推荐一个空闲的五位端口。
- 同一条线路部署到 N 台,每个被分配的用户订阅里出现 N 次,命名为 线路 – 服务器。
- 删掉一台服务器时,只部署在它上面的线路会被停用,而不是悄悄铺到所有服务器。
- 把线路的出口从直连换成上游是热换出站;改端口是带回滚的重启。