订阅格式:先区分节点列表与完整配置

“订阅链接”描述的是获取内容的入口,不是文件格式。同一个地址可能根据请求参数、请求头或服务端设置返回不同内容。判断能否导入 Clash 客户端,应检查实际响应,而不是只看网址是否以 .yaml 结尾。

常见输入包括逐行排列的节点分享链接、对整份链接列表做 Base64 编码的文本,以及包含节点和路由的完整配置。Base64 是编码方式,不是加密,也不是代理协议。知道解码方法的人就能还原服务器地址和凭据,因此编码后的订阅同样需要保密。

内容类型 常见结构 通常包含 不能据此推定
节点链接列表 ss://、vmess://、vless:// 等,每行一条 节点地址、认证和部分传输参数 策略组、DNS 与分流规则已配置
Base64 订阅 整份列表编码后的文本 通常与解码后的链接列表相同 某客户端能直接识别全部协议
Clash YAML proxies、proxy-groups、rules 节点、策略组、规则及可选 DNS 等设置 所有 Clash 系列内核均支持全部字段
sing-box JSON inbounds、outbounds、route 入站、出站、路由及可选 DNS 等设置 与 Clash YAML 存在逐字段等价关系

内容识别:检查响应,再做 Base64 解码

先排除登录页与错误页

将订阅下载到本地后,先用文本编辑器检查开头。若出现 <!DOCTYPE html>、登录表单或访问受限提示,得到的是网页而不是配置。HTTP 状态为 200 也不能保证内容正确;订阅过期、请求被拦截或账号需要验证时,都可能返回 HTML。

  1. 确认订阅来自账号管理页中对应的客户端入口,并检查有效期。
  2. 检查重定向后的实际内容,避免把错误页面提交给转换器。
  3. 已有 proxies: 或 JSON 对象时,先按其结构判断用途,不重复 Base64 解码。
  4. 只有内容确实是编码文本时,才在本地解码;不要把含令牌的内容贴到公共在线解码网站。

本地解码示例

下面使用 Python 3 标准库读取本地 subscription.txt,兼容常见的标准与 URL 安全 Base64 字母表,并补齐末尾填充。它只处理编码层,不负责解析节点协议。请在个人终端运行,输出中可能包含密码,不应放入工单或公开日志。

from pathlib import Path
import base64

raw = Path("subscription.txt").read_text(encoding="utf-8").strip()
compact = "".join(raw.split())
compact += "=" * (-len(compact) % 4)
decoded = base64.b64decode(compact, altchars=b"-_", validate=True)
print(decoded.decode("utf-8"))

解码失败不一定意味着订阅损坏,也可能是内容原本就没有编码。成功得到 UTF-8 文本后,再检查是否为逐行节点链接。列表整体解码完成,并不意味着每条链接内部也应再次整体解码:例如 Shadowsocks 的用户信息和某些 VMess 分享格式各有自己的编码规则,需要协议解析器分别处理。

转换原理:解析节点,再生成目标配置

订阅转换不是把 YAML 的冒号换成 JSON 的花括号。转换器通常先解析源格式,提取协议、地址、端口、认证和传输参数,形成内部节点模型,再按目标内核支持的字段输出。策略组、规则、DNS 与入站往往由另一份模板补上。

因此,“转换成功”只说明生成了输出,不代表节点协议可用,也不代表源配置的行为完整保留。从完整 YAML 导出节点链接时,节点以外的策略组、规则提供者、DNS 分流和 TUN 设置通常无法放回链接中;再由这些链接生成 JSON,缺失的信息不会自动恢复。

常见转换方向与边界

原版 Clash 与 Clash Meta(现称 mihomo)的能力范围不同。面向较新协议的配置应明确选择支持该协议的目标内核;把文件扩展名改成 .yaml,不能让旧内核获得 VLESS、Reality 或其他新增能力。图形客户端还可能附带不同版本的内核,应以运行中的内核版本为准。

字段映射:用一个 Shadowsocks 节点对照

以下两份配置表达同一个示例 Shadowsocks 出口:服务器端口为 8388,本地混合代理端口为 7890。域名使用保留的 .invalid 后缀,密码为演示值,配置只用于理解字段,不能直接联网。两份配置均未启用 TUN 或系统代理。

mihomo YAML:节点、选择组与兜底规则

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info

proxies:
  - name: 示例节点
    type: ss
    server: node.example.invalid
    port: 8388
    cipher: aes-128-gcm
    password: "demo-only-password"

proxy-groups:
  - name: 出口选择
    type: select
    proxies:
      - 示例节点
      - DIRECT

rules:
  - MATCH,出口选择

sing-box JSON:入站、出站与最终路由

{
  "log": {
    "level": "info"
  },
  "inbounds": [
    {
      "type": "mixed",
      "tag": "mixed-in",
      "listen": "127.0.0.1",
      "listen_port": 7890
    }
  ],
  "outbounds": [
    {
      "type": "shadowsocks",
      "tag": "示例节点",
      "server": "node.example.invalid",
      "server_port": 8388,
      "method": "aes-128-gcm",
      "password": "demo-only-password"
    },
    {
      "type": "direct",
      "tag": "直连"
    },
    {
      "type": "selector",
      "tag": "出口选择",
      "outbounds": ["示例节点", "直连"],
      "default": "示例节点"
    }
  ],
  "route": {
    "final": "出口选择"
  }
}

这里的 cipher 对应 method,节点服务端口 port 对应 server_port,节点名称则变为被引用的 tag。Clash 的内置 DIRECT 在该 JSON 示例里由显式的 direct 出站表示。实际项目仍须按所用 sing-box 版本验证,尤其是 DNS、TUN 与路由动作等持续演进的配置部分。

两个程序不能同时绑定本机同一个 7890 监听端口。对照测试时先停止其中一个,或将另一份配置改为 7891,并同步修改测试工具的代理地址。否则“端口已被占用”容易被误判为订阅转换失败。

转换参数:目标、筛选与模板分别核对

转换服务没有统一的参数标准。某些基于 subconverter 的部署会接受 target、url、include、exclude、config 等参数,但名称相同也不保证语义一致。先读部署方的说明,不能把其他服务的转换地址直接套用。

参数类别 具体核对点 常见结果
目标类型 是否明确支持所用 mihomo 或 sing-box 版本 选错目标会丢弃不支持的协议或字段
源订阅地址 嵌套 URL 是否按接口要求编码 源地址中的 & 被当作外层参数分隔符
节点筛选 包含、排除是否使用正则表达式 筛选后节点数变为零,策略组引用失效
配置模板 是否覆盖 DNS、规则、组名或监听端口 节点未变,但流量走向和解析行为改变
重命名与排序 是否保留唯一名称并同步更新引用 重名节点或悬空引用导致加载错误

嵌套 URL 应作为一个参数值交给 URL 编码工具处理,而不是凭直觉只替换空格。也不要反复编码整个生成结果,否则源地址中的 % 可能继续变成 %25。转换器返回空列表时,应先暂时移除筛选条件,再检查目标兼容性。

转换后检查:语法通过,再验证实际行为

第一步:使用目标内核检查配置

JSON 语法合法不等于 sing-box 配置合法,YAML 能解析也不代表字段受内核支持。可以在安装了对应命令行程序的环境中执行以下检查;可执行文件名称与路径以实际安装为准。

mihomo -t -f converted.yaml
sing-box check -c converted.json

先处理未知字段、缺少出站、策略组引用不存在等错误,再启动代理。如果图形客户端会执行合并或覆写,还要检查客户端最终生成的运行配置:导入文件通过检查,并不能证明覆写之后仍然有效。

第二步:逐项检查容易丢失的连接参数

第三步:核对分流与 DNS

Clash 的 rules 按顺序匹配,末尾 MATCH 是常见兜底。sing-box 的路由规则、动作和 route.final 有自己的结构,不能逐行照抄。检查规则命中的目标是否存在,以及代理服务器域名的解析是否依赖尚未建立的代理,避免解析与连接互相等待。

DNS 的 fake-ip、域名解析策略、规则集格式与下载路径也不应机械搬运。Clash 的 rule-providers 与 sing-box 的规则集并非同一文件格式;可读取文本列表,并不意味着能直接互用二进制规则集。TUN 更涉及接口、路由与系统权限,不属于节点链接能完整表达的内容。

常见问题:导入、更新与格式选择

为什么转换后有节点,却不能连接?

先确认不是演示域名、过期订阅或端口冲突,再看日志中的错误层级。域名解析失败应检查 DNS;TCP 连接失败应检查地址、端口与本地网络;TLS 握手失败应检查系统时间、服务器名称和证书。只反复切换 Base64 与 YAML,通常无法修复这些连接层问题。

为什么订阅更新后,本地修改消失?

远程配置更新通常会替换下载内容。需要长期保留的 DNS、规则或策略组调整,应使用客户端支持的独立覆写或合并机制,并确认它在订阅更新后仍会执行。转换生成的静态文件也不会自行更新;要持续同步,必须保留可重新获取的源入口与可重复执行的转换流程。

应该选哪种格式?

  1. 只使用 mihomo:优先选择提供方明确标注适配 mihomo 的 YAML,检查它是完整配置还是节点提供者。
  2. 只使用 sing-box:优先选择适配当前内核版本的 JSON,避免经由其他完整配置反复转换。
  3. 多种内核共用节点:保留同一可信节点源,为各内核分别维护规则与 DNS 模板,而不是强行共享一份主配置。
  4. 仅有 Base64 链接列表:在可信环境完成解码与转换,记录输入节点数、输出节点数和被跳过的协议,再做加载测试。

可靠的转换结果应同时满足三个条件:节点参数没有遗漏,目标配置通过内核检查,实际流量按预期规则处理。保留原始订阅入口和上一份可用配置,能在模板或内核升级后更快定位差异。字段含义可继续查阅 YAML 手册,基础概念可参照 概念速查。