订阅链接本质上是什么
机场发给用户的"订阅链接"不是节点本身,而是一个可以反复访问的 HTTP(S) 地址。客户端定时请求这个地址,拿到一段文本,再把文本解析成节点列表和(可能存在的)分流规则。同一个订阅地址背后返回的内容格式并不统一,主要取决于机场用的面板软件、客户端类型的判断逻辑,以及有没有经过转换服务处理。这也是为什么同一条订阅链接,粘贴进 Clash 能用,粘贴进另一个纯节点客户端却报错——不是链接坏了,是客户端没能识别返回内容的格式。
理解格式差异,遇到订阅导入失败时能快速判断问题出在哪一层:是链接本身失效、机场没适配这个客户端,还是需要经过转换服务再中转一次。
三种常见格式与识别方法
Base64 节点列表
最早也最通用的一种。访问订阅链接返回的是一段 Base64 编码字符串,解码后是若干行 vmess://、ss://、ssr://、trojan:// 之类的单节点链接,一行一个节点。这种格式不包含代理组和分流规则,客户端拿到节点列表后按自己的默认策略生成分组。绝大多数纯代理客户端(不局限于 Clash 生态)都能识别这种格式,兼容性最好,但功能也最基础。
Clash YAML 订阅
返回内容是一份完整的 YAML 配置,包含 proxies、proxy-groups、rules 等区块,和手写的 config.yaml 结构一致。机场后台按 Clash 规范生成这份配置,客户端下载后直接使用,分流策略、代理组分组都是机场预先设计好的,用户拿到手就能用。判断方法很直接:用浏览器或命令行工具访问链接,如果开头是 port:、mode: 或 proxies: 这类 YAML 关键字,就是这一类。
sing-box JSON 配置
随着 sing-box 内核的普及,一些机场开始额外提供 JSON 格式的订阅,结构对应 sing-box 的 outbounds、route 字段。这类订阅只能被 sing-box 内核或兼容 sing-box 配置结构的客户端识别,不能直接丢给 Clash 内核的客户端使用。返回内容以 { 开头、能看到 "outbounds" 字段是明显特征。
同一个机场往往会为不同客户端类型返回不同格式:请求头里带 Clash 标识就返回 YAML,不带就返回 Base64 节点列表。这也是为什么用浏览器直接打开订阅链接看到的内容,和客户端实际拿到的内容可能不一致。
订阅转换服务的工作原理
订阅转换服务(常见的开源实现叫 subconverter)本质是一个中间代理:它先以合适的请求头访问原始订阅链接,拿到节点数据后按目标格式重新生成一份配置,再返回给客户端。整个链路是"客户端 → 转换服务 → 原始订阅地址 → 转换服务 → 客户端",转换服务在中间做了两件事:格式转换和规则套用。
格式转换负责把 Base64 节点列表、sing-box JSON 等格式统一"翻译"成客户端能识别的 Clash YAML;规则套用则是转换服务允许你额外指定一份分流规则模板(ACL4SSR 之类的规则集),把裸节点套上现成的分流策略,生成的订阅链接直接包含代理组和规则,不用手写。使用时把原始订阅地址作为参数拼进转换服务的接口地址,再把接口返回的新链接填入客户端,操作上和填一条普通订阅没有区别。
https://某转换服务域名/sub?target=clash&url=原始订阅链接&config=规则模板地址
需要注意,转换服务本身也要能访问到原始订阅地址,如果原始订阅在特定网络环境下才能访问,转换环节可能因为网络原因失败,这类报错和订阅链接是否过期无关。
自建转换服务的基本思路
公共转换服务存在稳定性和隐私两方面的顾虑:接口可能限流或下线,原始订阅地址(通常包含账号相关的 token)也会经过第三方服务器。对稳定性和隐私有要求的用户,可以自建转换服务,基本思路如下:
准备运行环境
找一台能长期在线的服务器或本地一直开机的设备,装好对应的运行环境(subconverter 提供预编译二进制,不需要额外安装语言运行时)。
下载转换程序与规则模板
获取 subconverter 程序本体,以及打算长期使用的分流规则模板文件,放在同一目录下,按项目自带的配置说明设置监听端口。
启动服务并验证
启动程序后,用本机浏览器访问
http://127.0.0.1:端口/sub?target=clash&url=测试订阅地址,确认能正常返回 YAML 内容。替换为自己的转换地址
把公共转换服务的域名换成自己服务器的地址(建议配合反向代理加上 HTTPS),后续所有订阅都通过自建服务转换,原始订阅地址不再经过第三方。
自建转换服务的维护成本主要在规则模板的更新上:分流规则会随着服务变化持续调整,长期不更新模板会导致分流准确率下降,建议定期同步上游规则仓库。
各格式在不同客户端里的兼容性对照
下表按常见客户端归纳对三种订阅格式的直接支持情况,不经过转换服务的前提下:
| 客户端 / 内核 | Base64 节点列表 | Clash YAML | sing-box JSON |
|---|---|---|---|
| Clash(原版内核) | 需转换后使用 | 原生支持 | 不支持 |
| Clash Meta / mihomo 内核 | 需转换后使用 | 原生支持,含扩展字段 | 不支持 |
| 纯代理客户端(仅认单节点链接) | 原生支持 | 不支持 | 不支持 |
| sing-box 内核客户端 | 需转换后使用 | 不支持 | 原生支持 |
可以看到,Clash YAML 只在 Clash 内核家族里通用,拿去喂给 sing-box 内核的客户端会直接解析失败;反过来 sing-box 的 JSON 订阅也不能直接导入 Clash 客户端。跨内核使用节点时,订阅转换是绕不开的一步,而不是可选步骤。
更换客户端内核类型(比如从 Clash 换到基于 sing-box 的客户端)时,先确认机场是否同时提供两种格式的订阅入口,不要假设同一条链接能跨内核通用。