# sing-box 连接资产 当前 UI 称为「sing-box 代理」,在「代理管理」创建并供目标或 TCP 纯端口转发网关复用。共享 TCP 网关使用 `tcpForward.mode="proxy"` 与 `outboundId`,沿用本文相同的进程、安全和凭据边界,详见 [网络代理管理](network-proxies.md)。 ## 目的与架构 sing-box 连接资产让目标服务复用 sing-box 的远程 outbound,而不把各协议实现嵌入 linkport。资产只保存一个 outbound JSON 对象;目标仍通过现有 `outboundId` 引用连接资产。业务链路为: ```text 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。 示例: ```powershell $env:LINKPORT_SING_BOX = 'C:\Tools\sing-box\sing-box.exe' .\linkport.exe ``` ```sh 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`。 例如: ```json { "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,再以资产“检查配置”作为部署侧校验。 ## 运行与测试边界 资产页面的“检查配置”执行: ```text 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,应自行保留其许可证、版权声明并履行对应版本的发布义务。本文是工程边界说明,不替代法律意见。 官方依据: - [v1.14.2 release](https://github.com/SagerNet/sing-box/releases/tag/v1.14.2) - [v1.14.2 go.mod](https://github.com/SagerNet/sing-box/blob/v1.14.2/go.mod) - [v1.14.2 LICENSE](https://github.com/SagerNet/sing-box/blob/v1.14.2/LICENSE) - [Outbound 配置目录](https://sing-box.sagernet.org/configuration/outbound/) - [JSON Schema 说明](https://sing-box.sagernet.org/configuration/schema/) - [`check` 命令实现](https://github.com/SagerNet/sing-box/blob/v1.14.2/cmd/sing-box/cmd_check.go) 与 [`run -c` 配置读取](https://github.com/SagerNet/sing-box/blob/v1.14.2/cmd/sing-box/cmd_run.go) ## 兼容、迁移与验证 新增字段位于既有加密 `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 验证。实际命令与结果见 [测试记录](testing.md)。