Clash 订阅格式区别:YAML 配置、Base64 订阅与 URI 链接如何互转
对比三类常见订阅格式的结构与适用客户端,说明转换时字段如何对应、哪些信息会丢失,以及自建转换的注意事项。
先识别内容,再选择导入方式
优先使用服务提供方明确标注的 Clash 或 mihomo 订阅入口。拿到的如果是完整 YAML 配置,通常可以直接添加到客户端的配置列表;如果是 Base64 文本或一组协议 URI,则先确认客户端是否支持导入这些格式。不要只修改文件扩展名,也不要把“成功下载订阅”当成“内核已经接受配置”。
先区分两个容易混淆的对象:订阅地址是获取内容的入口,订阅格式是入口实际返回的数据结构。同一个 HTTPS 地址可能根据查询参数或请求头返回不同内容。地址以 .yaml 结尾不保证响应就是 YAML,没有扩展名也不影响它返回完整配置。
| 格式 | 常见内容特征 | 通常包含的信息 | 导入前检查 |
|---|---|---|---|
| Clash YAML | 出现 proxies、proxy-groups、rules 等键 | 节点、策略组、规则,也可能含 DNS 与端口设置 | 区分完整配置和节点片段 |
| Base64 订阅 | 一长段编码文本,解码后常为多行 URI | 取决于原始内容;常见情况只有节点信息 | 先解码,再识别内部格式 |
| URI 链接 | 以 ss://、vmess://、trojan:// 等开头 | 单个节点的协议、地址、认证及传输参数 | 确认导入器支持对应协议与参数 |
YAML 配置:区分完整配置与节点列表
先看顶层字段。YAML 只是数据表达格式,并不是 Clash 专属格式。能够被 YAML 解析器读取,不代表符合 Clash 配置结构;符合某个内核的结构,也不代表另一个内核支持其中全部协议与选项。
识别三类常见 YAML 内容
- 完整配置:通常同时组织
proxies、proxy-groups、rules,并可能设置监听端口、DNS、TUN 等。 - 节点集合:只包含
proxies。可供兼容的代理集合提供者使用,但不能据此推断已经配好了策略组与分流规则。 - 规则集合:常见顶层字段是
payload。它供rule-providers引用,不是节点订阅,也不能导入为代理列表。
下面是一份用于说明结构的配置。edge.example.com 和 demo-password 均为演示值,不能用于实际连接。示例设置本地混合端口为 7890,只监听回环地址,并用一个手动选择组承接所有匹配流量。
mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
proxies:
- name: DemoTLS
type: trojan
server: edge.example.com
port: 443
password: "demo-password"
sni: edge.example.com
udp: true
proxy-groups:
- name: Manual
type: select
proxies:
- DemoTLS
- DIRECT
rules:
- MATCH,Manual
这里的 443 是远端代理服务端口,7890 是本机应用连接客户端的代理端口,两者不能互换。把 YAML 转成节点 URI 时,远端端口需要保留;本机监听端口、策略组和兜底规则通常不会进入节点链接。
选择与实际内核匹配的配置
先在客户端的“关于”或内核信息页面确认内核名称,再查看该内核支持的协议。界面支持粘贴链接,不等于运行中的内核支持链接对应的协议。Clash Meta 延续发展的 mihomo 与较早的 Clash 内核在协议和字段支持上存在差异,转换目标不能只凭文件名决定。
Base64 订阅:解码不等于转换
先在本地解码并查看结果。Base64 是编码方式,不是代理协议,也不是加密措施。常见订阅把多条节点 URI 按行排列,再将整段文本编码;也有服务编码其他文本结构,因此不能预设解码后一定能直接导入 Clash。
注意两层编码:订阅外层可能使用 Base64,内部某条 vmess:// 链接又可能把 JSON 编码成 Base64;部分 ss:// 链接也会编码认证信息。正确顺序是先还原订阅外层,再交给理解协议的解析器处理单条链接,而不是对每一段字符串反复解码。
用 Python 在本地检查编码内容
将收到的编码正文保存为 subscription.txt,用 Python 3 执行以下代码。脚本兼容常见 Base64 和 URL 安全字母表,忽略空白并补齐末尾填充;输出写入 decoded.txt,不会主动访问网络。若输入实际是 YAML、网页或普通 URI,应该先按其真实格式处理。
from pathlib import Path
import base64
import binascii
source = Path("subscription.txt").read_text(encoding="utf-8")
compact = "".join(source.split())
compact += "=" * (-len(compact) % 4)
try:
raw = base64.b64decode(compact, altchars=b"-_", validate=True)
text = raw.decode("utf-8")
except (ValueError, binascii.Error, UnicodeDecodeError) as exc:
raise SystemExit("无法按 Base64 UTF-8 文本解码,请检查原始内容。") from exc
Path("decoded.txt").write_text(text, encoding="utf-8")
print("已写入 decoded.txt;请在本地查看内容类型。")
- 看到逐行的
ss://、trojan://等内容:进入 URI 到配置的字段映射步骤。 - 看到
proxies::先确认是否已经是 YAML,不要再执行一次“节点转换”。 - 看到 HTML 登录页、错误提示或 JSON 错误对象:先解决订阅请求问题,转换器无法补出不存在的节点数据。
反过来,把多行 URI 做 Base64 编码,只是重新包装同一组链接。它不会自动生成 rules 或 proxy-groups,也不会修复缺失的 TLS、WebSocket 或认证参数。
URI 转 YAML:逐项对应连接参数
先用一个节点核对字段,再批量转换。以下 Trojan URI 与前面的 YAML 节点对应。链接中的片段 #DemoTLS 表示显示名称,不是认证信息;查询参数 sni 用来指定 TLS 服务器名称。
trojan://[email protected]:443?sni=edge.example.com#DemoTLS
| URI 部分 | YAML 字段 | 处理要点 |
|---|---|---|
| trojan:// | type: trojan | 按协议映射,不改成其他代理类型 |
| demo-password | password | 按 URI 规则还原百分号编码 |
| edge.example.com | server | 保留连接地址,不用备注替代 |
| 443 | port | 写成端口数值,不填本地代理端口 |
| sni=edge.example.com | sni | 与 server 分开保存,两者可能不同 |
| #DemoTLS | name | 还原名称后检查重名与组引用 |
这条 URI 没有明确携带前面示例中的 udp: true,因此不能声称从 URI 还原后能逐字复原原配置。转换器可能采用自己的默认值;正式使用时,应按服务能力和目标内核要求显式确认 UDP 设置。
分别处理协议与传输层
- Shadowsocks:保留加密方法、密码、服务器和端口;带插件的链接还要检查插件名称与选项。只保存主机和密码可能无法建立连接。
- VMess:常见分享链接内部是编码后的 JSON,需要解析 UUID、端口、传输类型、TLS 等字段;不能把整段解码结果当成 YAML。
- VLESS 与其他协议:先确认目标内核及转换器都支持,再核对 flow、TLS、Reality 等协议相关参数,不能用名称相近的字段机械替换。
- WebSocket 或 gRPC:继续保留路径、Host 请求头或服务名等参数。代理协议相同,传输设置不同,也可能完全无法连通。
不要用“按冒号分割字符串”的方式手写通用解析器。IPv6 地址本身含冒号,密码可能含转义字符,节点名称可能包含中文。应使用 URI 解析工具并按各协议约定处理编码,避免重复解码把密码中的字面内容改掉。
YAML 转 URI:明确哪些信息会丢失
只把 URI 当作单节点的交换载体。完整 YAML 的内容范围更大,导出节点链接通常不能携带整个运行环境。如果目标是换客户端并保留分流逻辑,应优先迁移兼容的完整配置,而不是先导出 URI 再重新导入。
检查四类无法完整随节点迁移的设置
- 策略组:
select、url-test、fallback的组成员、探测地址和切换逻辑通常不属于节点 URI。 - 分流规则:
DOMAIN-SUFFIX、GEOIP、MATCH及规则提供者引用不会因为导出节点而自动保留。 - 本机环境:监听端口、系统代理、TUN、DNS、外部控制接口等设置需要在新配置或新客户端中单独安排。
- 扩展参数:特殊传输、证书处理、复用及内核扩展字段可能没有统一的 URI 表达方式,或只有部分导入器认识。
即使两端都支持同一种协议,分享链接参数名也可能存在实现差异。转换后应逐项对比服务器、端口、认证、TLS 名称和传输设置。不要为了让导入成功就删除无法识别的参数,更不要把跳过证书验证当成通用修复步骤。
自建转换:限制入口,固定输出模板
优先选择本地运行,或部署到仅自己可访问的环境。自建转换的重点不仅是生成 YAML,还包括保护源订阅凭据、约束远程抓取范围,以及固定可以复查的转换模板。
- 选择实现:确认转换器明确支持源协议、目标内核和所需扩展字段。记录部署版本与模板修订,更新前保留一份可工作的输出。
- 收紧监听:本地服务可只监听
127.0.0.1。例如使用本地端口25500时,不要直接把该端口开放到公网;实际端口以所选实现的配置为准。 - 固定模板:审核模板中的策略组、规则和远程资源地址。转换时只替换节点,不让来源不明的模板顺带改变 DNS、控制接口或流量出口。
- 处理远程 URL:对源订阅和远程模板使用允许列表,限制重定向、响应体积及请求超时,避免服务被用来访问内网或云实例元数据地址。
- 控制日志:避免记录完整查询字符串、认证头和订阅正文。需要分享日志时先遮盖令牌,定期清理生成文件与缓存。
通过 URL 参数传递源订阅时,要对整个源地址进行一次正确的百分号编码。例如源地址自身带有 ?token= 和 &type=,未经编码就嵌入另一条 URL,参数可能被外层请求截开。优先使用转换器文档支持的本地文件或请求正文入口,减少凭据出现在浏览器历史和访问日志中的机会。
同时区分静态转换与持续订阅:下载一次生成文件,只得到当时的快照。要自动更新,必须保留可靠的更新入口,或者在配置中使用内核支持的代理集合机制。远端更新能否覆盖本地修改,取决于客户端的合并与覆写方式,不能只看“已开启自动更新”的开关。
转换后验证:按结构、连接、分流逐层检查
先检查配置,再切换当前运行配置。保留原来的可用订阅,避免批量转换后失去对照。使用 mihomo 时,可以对生成文件执行配置测试;以下命令中的文件名是本地保存的输出文件。
mihomo -t -f ./converted.yaml
测试通过表示配置通过了该内核的检查,并不代表远端节点可用。引用远程资源的配置还可能受本地文件、网络访问和运行目录影响,测试环境应尽量与正式运行环境一致。
| 现象 | 优先检查 | 下一步操作 |
|---|---|---|
| 订阅下载成功但没有节点 | 响应是否为网页、错误对象或不受支持的编码 | 本地查看响应内容,确认格式后再导入 |
| 报告未知代理类型 | 内核是否支持该协议 | 核对内核能力与转换目标,不只更换扩展名 |
| 节点能显示但连接失败 | 密码、SNI、传输路径和服务名 | 与原始节点逐项比对,先测试单个节点 |
| 连接正常但分流改变 | 策略组、规则顺序和 MATCH 目标 | 查看连接记录中的命中规则及实际策略 |
| 更新后本地规则消失 | 本地修改是否直接写入远程配置副本 | 采用客户端支持的覆写或独立配置方式 |
完成一次最小验证
- 确认转换前后的节点数量与名称,检查是否发生过滤、重命名或解析失败。
- 只选择一个已知可用节点,确认 TLS 与传输参数完整,再扩大到整个列表。
- 若沿用示例的
7890混合端口,先确认实际监听成功,再让应用连接该端口。 - 分别检查普通网页访问、DNS 解析和需要 UDP 的应用;一次网页访问成功不能覆盖全部使用场景。
最后保留一份转换记录:源格式、目标内核、转换器与模板版本、手动补充的字段。以后遇到订阅更新失效,就能判断问题发生在源数据、解析过程还是本地运行配置,而不必反复尝试不同的在线转换入口。