Files

11 KiB
Raw Permalink Blame History

sing-box 连接资产

当前 UI 称为「sing-box 代理」,在「代理管理」创建并供目标或 TCP 纯端口转发网关复用。共享 TCP 网关使用 tcpForward.mode="proxy" 与 outboundId,沿用本文相同的进程、安全和凭据边界,详见 网络代理管理。

目的与架构

sing-box 连接资产让目标服务复用 sing-box 的远程 outbound,而不把各协议实现嵌入 linkport。资产只保存一个 outbound JSON 对象;目标仍通过现有 outboundId 引用连接资产。业务链路为:

linkport DialFunc -> 127.0.0.1 随机端口的受控 SOCKS5 入站
                     -> linkport 管理的 sing-box 子进程
                     -> 资产中的单个远程 outbound
                     -> 目标主机:端口

当前实现选择管理外部 binary:

  • linkport 不链接 sing-box Go module,也不复用其内部 Go API。
  • linkport 不连接用户自行维护的常驻 sing-box、SOCKS 或 mixed 入口;监听地址、端口和认证由 linkport 每次生成。
  • 首次实际拨号时启动 sing-box run -c <临时配置> --disable-color。规范化 outbound JSON 与 binary 路径相同的并发连接共享子进程;最后一个连接关闭后终止该进程并删除临时目录。
  • 运行时因此可能有 linkport 和一个或多个 sing-box OS 进程。“单 EXE”只描述 linkport 交付物,不表示启用该出口后仍只有一个进程。

选择这个边界的原因是 sing-box 的 CLI/JSON 配置比其 Go 包更适合作为跨版本集成契约。官方面向部署的文档以 CLI 和配置 schema 为主;本次核对未找到对 Go library API 的跨版本稳定性承诺。官方 v1.14.2 源码的 go.mod 要求 Go 1.25.5,而本仓库因固定 Vitess 依赖使用 Go 1.25.0;直接嵌入当前 sing-box module 会把两套工具链和大量可选协议依赖带入同一构建。让用户自行运行代理虽可减少子进程管理,但会要求另行维护监听端口、认证、配置文件和生命周期,当前版本没有采用该模式。

安装与定位

sing-box 不包含在 linkport 源码、Windows 单 EXE 或其他发布包中。在运行 linkport 的同一台机器安装一个与配置匹配的 sing-box binary:

  1. 推荐把绝对路径写入进程环境变量 LINKPORT_SING_BOX。
  2. 未设置时,linkport 用 PATH 查找名为 sing-box 的程序(Windows 可解析 sing-box.exe)。
  3. 修改环境变量或 binary 后重启 linkport;路径不写入资产或 SQLite。

示例:

$env:LINKPORT_SING_BOX = 'C:\Tools\sing-box\sing-box.exe'
.\linkport.exe
LINKPORT_SING_BOX=/usr/local/bin/sing-box ./linkport

部署应固定并记录 binary 版本。linkport 当前不声明 sing-box 最低或最高版本,也不会根据版本号改写字段;最终兼容性由该 binary 对生成配置及 outbound schema 的解析结果决定。升级 binary 后先重新执行资产“检查配置”,再执行目标连接测试。

配置契约

输入可以是一个 UTF-8 outbound JSON object,也可以是包含 outbounds 的完整 sing-box JSON 配置或 JSON 文件。程序按 route.final 优先、否则按列表顺序自动提取一个远程 outbound;direct、selector 等本地/组合 outbound 不会被提取。不是分享 URI、订阅链接或数组。原始输入去除首尾空白后最多 64 KiB(65,536 字节),提取结果必须包含小写 type;用户提供的 tag 会移除,运行时统一改为 linkport-out。

例如:

{
  "type": "vless",
  "server": "proxy.example.com",
  "server_port": 443,
  "uuid": "00000000-0000-0000-0000-000000000000",
  "tls": {
    "enabled": true,
    "server_name": "proxy.example.com"
  }
}

linkport 不维护会随 sing-box 发布变化的远程协议白名单。官方 v1.14.2 outbound 目录包含 AnyTLS、HTTP、Hysteria/Hysteria 2、Naive、Shadowsocks、ShadowTLS、Snell、SOCKS、SSH、Trojan、TUIC、VLESS、VMess、WireGuard 等远程类型;具体字段、编译特性和废弃状态仍以部署的 binary 为准。未知但格式合法的远程类型可以进入 binary 检查,以便未来协议不必等待 linkport 发版。

以下能力会在交给 binary 前拒绝:

  • 未包含可提取远程 outbound 的完整配置;完整配置中的其他字段只用于定位 outbound,不会保存或传入运行时。
  • 单个 outbound 中的完整配置顶层字段,如 $schema、log、dns、inbounds、outbounds、route、services 和 experimental。
  • 不建立单一远程连接或可组合本地路由的类型,如 direct、block、bridge、selector、urltest、tor、tun 和 tailscale。
  • 任意层级的本地文件路径、外部进程、outbound detour、自定义解析器或宿主网络控制字段,包括 *_path、detour、*_detour、plugin、executable_path、data_directory、extra_args、bind_interface、routing_mark、netns、domain_resolver,以及 WireGuard 的 system_interface、interface_name 等。
  • 深度超过 24(根对象为 0)、总节点超过 4096、单数组超过 1024 项、单对象超过 256 个字段的结构,以及 __proto__、constructor、prototype 或含控制字符的对象键。

这些限制是 linkport 的宿主安全边界,不表示对应字段在 sing-box 中无效。因为子进程继承 linkport 的 OS 身份,允许文件、进程或宿主路由字段会把资产编辑权限扩大为本机资源访问权限。

sing-box 1.14 起可用 sing-box schema 生成与该 binary 构建特性一致的 Draft 2020-12 schema;在线 $schema 只供编辑器补全,不参与运行时校验。资产本身不能携带 $schema。先用对应版本文档编写单 outbound,再以资产“检查配置”作为部署侧校验。

运行与测试边界

资产页面的“检查配置”执行:

sing-box check -c <临时配置>/config.json --disable-color

检查最多等待 10 秒。它会让安装的 binary 解析完整生成配置并构造实例,但不会调用长期 run,也不向用户目标发起 linkport 协议认证;因此通过只证明“当前 binary 接受这份受控配置”,不证明代理服务器、目标服务或账号可达。检查失败响应只包含固定安全 error 类别和 durationMs,不附带连接 diagnostics 或 sing_box_start 阶段,也不返回 binary stderr 或原配置。

要验证网络链路,应在引用该代理的目标或 TCP 纯转发网关上执行“测试连接”。实际拨号会启动/复用子进程,并记录 sing_box_start、sing_box_connect、sing_box_negotiation 和 sing_box_authentication:它完成本地 SOCKS5 连接、协商和随机凭据认证,把目的主机名原样交给 sing-box;协议目标再完成 TLS、握手、认证和查询,纯 TCP 网关只检查连接建立。任何阶段失败都不会回退直连。当前只承载 TCP,不提供 UDP、TUN 或系统代理。

资产检查与运行命令的 stdout/stderr 均丢弃,因为 binary 的错误可能复述 outbound 秘密。对外只返回稳定错误类别。配置检查、进程本地端口就绪和目标连接是三个不同证据,不应互相替代。

秘密与本机安全

整个 singBoxOutbound 都按秘密处理,而不尝试猜测各协议的密码、UUID、私钥或令牌字段:

  • 保存时规范化后随连接资产密封存入 SQLite;管理 API 永不回显正文,只返回 secretStatus.singBoxOutbound 和派生的 singBoxType 摘要。
  • 编辑已有资产时输入框为空;留空保留旧值,只有应用新 JSON 才替换。前端应用后立即清空原始输入。
  • 配置历史和导入预览只返回 secretChanged,不展示前后 JSON。调用 RedactBundle 的模板和脱敏视图会清空正文;口令加密的完整备份和加密 WebDAV 同步仍包含恢复所需秘密,应按凭据材料保护。
  • 运行配置关闭 sing-box 日志,并为本地 SOCKS5 入口生成随机账号密码。入口只监听 127.0.0.1,不设置系统代理。
  • 临时目录请求 0700、配置文件请求 0600,并在检查结束、进程退出或启动失败后删除。Windows 上最终访问控制还取决于临时目录 ACL 和运行 linkport 的账号;不要与不可信进程共用高权限服务账号。

输入限制降低宿主能力暴露,但 sing-box 仍是与 linkport 同身份运行的第三方程序。只安装可信来源的 binary,核对发布校验值,限制 LINKPORT_SING_BOX 和 PATH 的写权限,并避免以管理员/root 身份运行。

版本、许可证与升级

截至 2026-09-27,官方 GitHub 最新非预发布版本是 v1.14.2(2026-09-24 发布)。该源码声明 go 1.25.5;这是从源码构建或嵌入 module 的要求,不是运行官方预编译 binary 时对 linkport Go 版本的要求。

sing-box 由 SagerNet 上游仓库发布;官方 LICENSE 的版权声明人为 nekohasekai,正文采用 GNU GPL v3 或更高版本,并另有衍生作品名称/关联声明限制。linkport 不捆绑或重新发布该程序;若部署者另行分发 sing-box,应自行保留其许可证、版权声明并履行对应版本的发布义务。本文是工程边界说明,不替代法律意见。

官方依据:

兼容、迁移与验证

新增字段位于既有加密 outbounds 记录,没有 SQLite 表结构迁移。已有 direct、SOCKS5、SSH 和 Kubernetes 配置不变;新版本可以把 sing-box 资产绑定到普通目标。独立 tcp 网关当前仍只接受 SOCKS5 或 Kubernetes 转发,不能引用 sing-box 资产。旧版 linkport 不认识新 mode,跨版本回退前须停止服务并保留完整加密备份。

本实现的自动化验证覆盖:单对象/64 KiB/复杂度与危险字段拒绝、tag 规范化、API 和配置差异脱敏、脱敏配置包、受控 loopback SOCKS 配置、随机认证接线,以及 SOCKS5 目标域名不在 linkport 本地解析。测试使用本地 fixture 和伪造协议交互;本次环境未安装 sing-box,也未连接真实代理或目标服务器,因此没有把 fixture 覆盖描述为 live-server 验证。实际命令与结果见 测试记录。