订阅格式:先区分节点列表与完整配置
“订阅链接”描述的是获取内容的入口,不是文件格式。同一个地址可能根据请求参数、请求头或服务端设置返回不同内容。判断能否导入 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。
- 确认订阅来自账号管理页中对应的客户端入口,并检查有效期。
- 检查重定向后的实际内容,避免把错误页面提交给转换器。
- 已有
proxies:或 JSON 对象时,先按其结构判断用途,不重复 Base64 解码。 - 只有内容确实是编码文本时,才在本地解码;不要把含令牌的内容贴到公共在线解码网站。
本地解码示例
下面使用 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,缺失的信息不会自动恢复。
常见转换方向与边界
- Base64 → Clash YAML:先解码并解析链接,再生成
proxies,最后补齐所需策略组和规则。 - Clash YAML → Base64:通常只导出可表达为分享链接的节点,再对链接列表编码;这不是配置备份。
- Clash YAML → sing-box JSON:节点字段需要映射,路由和 DNS 则需要按目标版本重新组织。
- sing-box JSON → Clash YAML:必须检查出站类型和规则动作是否有对应实现;自定义路由逻辑可能只能人工重建。
原版 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
先处理未知字段、缺少出站、策略组引用不存在等错误,再启动代理。如果图形客户端会执行合并或覆写,还要检查客户端最终生成的运行配置:导入文件通过检查,并不能证明覆写之后仍然有效。
第二步:逐项检查容易丢失的连接参数
- 认证与端口:核对服务器域名、端口、密码或 UUID,避免把本地
7890当成服务端口。 - TLS:核对是否启用、服务器名称与证书验证。不要用关闭证书验证来掩盖 SNI 或服务器名称映射错误。
- 传输层:逐一核对 WebSocket 路径、Host 请求头、gRPC 服务名等,不能只保留协议名称。
- Reality 与指纹:核对公钥、短 ID、服务器名称及客户端指纹是否被目标实现支持并正确写出。
- UDP:确认协议、节点服务端和目标配置都支持所需 UDP 行为;一次网页访问成功不能证明 UDP 可用。
第三步:核对分流与 DNS
Clash 的 rules 按顺序匹配,末尾 MATCH 是常见兜底。sing-box 的路由规则、动作和 route.final 有自己的结构,不能逐行照抄。检查规则命中的目标是否存在,以及代理服务器域名的解析是否依赖尚未建立的代理,避免解析与连接互相等待。
DNS 的 fake-ip、域名解析策略、规则集格式与下载路径也不应机械搬运。Clash 的 rule-providers 与 sing-box 的规则集并非同一文件格式;可读取文本列表,并不意味着能直接互用二进制规则集。TUN 更涉及接口、路由与系统权限,不属于节点链接能完整表达的内容。
常见问题:导入、更新与格式选择
为什么转换后有节点,却不能连接?
先确认不是演示域名、过期订阅或端口冲突,再看日志中的错误层级。域名解析失败应检查 DNS;TCP 连接失败应检查地址、端口与本地网络;TLS 握手失败应检查系统时间、服务器名称和证书。只反复切换 Base64 与 YAML,通常无法修复这些连接层问题。
为什么订阅更新后,本地修改消失?
远程配置更新通常会替换下载内容。需要长期保留的 DNS、规则或策略组调整,应使用客户端支持的独立覆写或合并机制,并确认它在订阅更新后仍会执行。转换生成的静态文件也不会自行更新;要持续同步,必须保留可重新获取的源入口与可重复执行的转换流程。
应该选哪种格式?
- 只使用 mihomo:优先选择提供方明确标注适配 mihomo 的 YAML,检查它是完整配置还是节点提供者。
- 只使用 sing-box:优先选择适配当前内核版本的 JSON,避免经由其他完整配置反复转换。
- 多种内核共用节点:保留同一可信节点源,为各内核分别维护规则与 DNS 模板,而不是强行共享一份主配置。
- 仅有 Base64 链接列表:在可信环境完成解码与转换,记录输入节点数、输出节点数和被跳过的协议,再做加载测试。
可靠的转换结果应同时满足三个条件:节点参数没有遗漏,目标配置通过内核检查,实际流量按预期规则处理。保留原始订阅入口和上一份可用配置,能在模板或内核升级后更快定位差异。字段含义可继续查阅 YAML 手册,基础概念可参照 概念速查。