先看返回内容:订阅地址不等于配置格式
导入 Clash 订阅失败,先别急着换客户端。同一个 HTTPS 地址,可能返回可直接运行的 YAML 配置,也可能返回一串 Base64 文本,甚至是登录页面。地址以什么后缀结尾并不可靠:没有 .yaml 后缀的接口也可以返回 YAML,带这个后缀的地址也可能因为鉴权失效而返回错误信息。
把订阅分成三层更容易判断:订阅地址是获取入口,Base64 是文本编码,YAML 或 URI 才描述具体数据。其中 YAML 还要继续区分完整配置与只含节点的数据。把节点列表当完整配置导入,是常见的报错来源。
| 看到的内容 | 通常代表什么 | 下一步 |
|---|---|---|
proxies:、proxy-groups:、rules: |
可能是完整 Clash 配置 | 检查节点、分组引用与内核兼容性 |
只有 proxies: 和节点条目 |
节点集合或 provider 数据 | 通过节点提供器接入,或合并到完整配置 |
多行 ss://、trojan:// 等链接 |
URI 节点列表 | 使用支持节点导入的界面,或转换格式 |
| 连续字母、数字及少量符号 | 可能是 Base64 编码内容 | 本地解码,再确认解码后的格式 |
<html>、登录提示、JSON 错误 |
网页或接口错误响应 | 检查订阅有效期、鉴权和访问限制 |
YAML 配置:节点、策略组和规则各管一层
YAML 是数据序列化格式,并非 Clash 专属。能被 YAML 解析器读取,只说明语法成立;客户端还会检查字段、节点协议和引用关系。对于基于 mihomo 的客户端,实际支持范围由正在运行的内核决定,不能只看界面名称里有没有 Clash。
一份最小示例的结构
下面展示本地入口、一个 Shadowsocks 节点、一个选择组和规则之间的关系。node.example.invalid 是保留的示例域名,密码也是演示值,不能用于实际连接。端口 7890 是这里明确设置的本地混合代理端口,不代表每个客户端都使用它。
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
proxies:
- name: "Demo SS"
type: ss
server: node.example.invalid
port: 443
cipher: aes-128-gcm
password: "demo-pass"
proxy-groups:
- name: "手动选择"
type: select
proxies:
- "Demo SS"
- DIRECT
rules:
- IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- MATCH,手动选择
proxies:保存服务器地址、协议、端口及认证信息。proxy-groups:组织节点或其他策略,供用户选择或执行自动策略。rules:从上到下匹配流量;上例末尾的MATCH接住剩余连接。mixed-port:提供 HTTP 和 SOCKS 代理入口。客户端的覆盖设置可能改写这个值,应以运行配置为准。
这个示例用于解释结构,没有展开 DNS、TUN 和局域网访问策略。它不是通用的网络优化方案,也不能据此判断 DNS 请求实际走向。导入真实配置前,应保留服务提供方要求的传输层和认证字段。
YAML 最容易出错的三个位置
- 缩进:使用空格,不要使用 Tab。上例列表项缩进 2 个空格,节点属性缩进 4 个空格。
- 字符串:包含特殊符号的密码、节点名建议加引号。未被引号保护的
#在特定位置会开始注释,导致内容被截断。 - 引用:节点名、策略组名要完全一致。把
Demo SS改成Demo-SS后,组内引用也必须同步修改。
Base64 节点串:先解码,再谈导入
常说的“Base64 订阅”,通常是把多条 URI 链接用换行分隔,再将整段文本编码成 Base64。解码后得到的仍是节点列表,不会凭空出现规则、策略组或 DNS 配置。也有服务编码其他内容,所以最终判断依据始终是解码结果。
标准 Base64 常见字符有 +、/,结尾可能有 =;URL 安全变体则使用 - 和 _。部分接口省略末尾补位。不要因为没有等号就断定它不是 Base64,也不要把整个 HTTPS 订阅地址拿去解码。
本地查看解码结果
电脑已安装 Python 3 时,可以把订阅返回的编码正文保存为 subscription.txt,在该文件所在目录执行以下命令。脚本只读取本地文件,把结果写入 decoded.txt,不会上传内容。输出文件同样含有敏感凭据,用完应妥善清理。
python3 - <<'PY'
from pathlib import Path
import base64
import binascii
raw = Path("subscription.txt").read_text(encoding="utf-8-sig")
encoded = "".join(raw.split())
encoded += "=" * (-len(encoded) % 4)
try:
decoded = base64.b64decode(
encoded, altchars=b"-_", validate=True
).decode("utf-8")
except (binascii.Error, UnicodeDecodeError, ValueError) as error:
raise SystemExit("解码失败:请检查输入是否为 Base64 文本") from error
Path("decoded.txt").write_text(decoded, encoding="utf-8")
print("已写入 decoded.txt,请在本地查看")
PY
这段命令使用类 Unix shell 的 here-document 写法,适用于 macOS、Linux 等环境;Windows 可将中间的 Python 代码保存为脚本后运行。解码失败时,先检查是否误存了网页内容、是否复制不完整,以及是否把文件外层的引号也复制进去了。
URI 链接:一条链接描述一个节点
URI 通常以协议名开头,例如 ss://、vmess://、vless:// 或 trojan://。它们并不共用同一种内部编码。常见 VMess 分享链接把 JSON 编码后放入链接,其他协议则可能使用用户信息、主机、端口和查询参数组合描述连接。
Shadowsocks 示例:只编码认证部分
ss://[email protected]:443#Demo%20SS
这条示例中,YWVzLTEyOC1nY206ZGVtby1wYXNz 解码后是 aes-128-gcm:demo-pass;node.example.invalid:443 是服务器和端口;#Demo%20SS 是经过百分号编码的显示名称。它对应前文的演示节点,但没有携带策略组与分流规则。
- 百分号编码与 Base64 不同:
%20表示空格,应按 URI 组件解码,不要当作 Base64 处理。 - 名称不等于参数:链接末尾的备注通常只影响显示;查询参数里的传输设置可能直接影响能否连接。
- IPv6 地址注意方括号:在 URI 的主机位置通常需要用
[IPv6地址]:端口的结构,不能简单按每个冒号切割。 - SS 分享格式存在变体:认证信息编码、旧式整体编码、插件参数的兼容情况不同,转换器需要识别具体形式。
不要手工套用“找到冒号就拆开”的处理办法。密码可能含特殊字符,IPv6 自带冒号,WebSocket 路径也可能包含查询参数。可靠的转换需要按协议解析,而不是把所有链接用同一套字符串替换规则处理。
格式互转:哪些能保留,哪些会丢失
格式转换的核心是字段映射,不是简单改扩展名。只有源格式携带了某项数据,而且目标格式与目标内核都支持,转换器才有机会完整保留它。先确定目标是“节点列表”“provider 数据”还是“完整配置”,再选择转换方式。
| 转换方向 | 实际操作 | 主要限制 |
|---|---|---|
| Base64 → URI 列表 | 解码外层文本 | 不增加规则和策略组 |
| URI 列表 → Base64 | 按行整理后整体编码 | 只改变包装,不提高兼容性 |
| URI 列表 → Clash YAML | 解析节点,再补充分组和规则 | 模板决定分流行为,协议字段可能无法完整映射 |
| 完整 YAML → URI 列表 | 导出能映射成链接的节点 | 通常丢失规则、DNS、TUN 和策略组 |
| 完整 YAML → provider 文件 | 抽取节点,按 provider 格式输出 | 主配置仍需定义如何引用这些节点 |
转换后逐项核对这些字段
- 基础连接:服务器、端口、密码或 UUID、协议类型。端口必须保留原值,不能把所有节点都改成
443。 - 加密与 TLS:Shadowsocks 的加密方法、TLS 开关、SNI、ALPN,以及证书验证设置。不要为了通过测试而随意开启跳过证书验证。
- 传输层:WebSocket 的路径和 Host、gRPC 的 service name 等。相同地址与密码,传输层不同也可能无法连接。
- 协议扩展:Reality 公钥与 short ID、VLESS flow 等字段需同时得到转换器和内核支持。
- 命名与引用:重复节点名要明确处理,重命名后更新策略组引用,避免只改节点列表而留下失效名称。
原版 Clash 与 mihomo 的能力范围并不相同。目标内核不支持的协议,不能靠“转换为 Clash 格式”变成受支持协议。遇到新协议时,核对当前内核版本和对应字段文档,比反复切换订阅转换模板更有效。
导入路径:完整配置与节点提供器分开处理
完整 YAML:按配置导入并启用
客户端界面通常把完整配置放在“配置”或“Profiles”页面。不同客户端的菜单名称并不统一,操作时确认选择的是“从 URL 导入配置”或“导入本地配置”,而不是“添加单个节点”。导入完成后还要启用该配置,再检查运行日志。文件出现在列表里,不代表已经成为当前配置。
只有节点:使用 provider 或受控合并
mihomo 的代理提供器可以把节点来源与主配置分开管理。为便于跨客户端迁移,优先使用明确含 proxies: 的 YAML provider 文件;其他输入形式是否可用,要按所用内核版本核实。下面示例引用一个本地节点文件,并通过 use 将节点接入策略组。
proxy-providers:
local-nodes:
type: file
path: ./providers/nodes.yaml
proxy-groups:
- name: "订阅节点"
type: select
use:
- local-nodes
rules:
- MATCH,订阅节点
./providers/nodes.yaml 应包含类似前文的 proxies: 节点集合。相对路径的解析位置受内核工作目录与客户端管理方式影响,不一定是下载文件所在目录。该片段需要合并到主配置中,不要与已有配置重复声明同名顶层键或同名策略组。
远程 HTTP provider 还涉及更新地址、缓存路径和更新间隔。若设置 interval: 86400,单位是秒,即每 24 小时更新一次。远程节点列表更新与主配置更新是两条流程:前者更新节点,后者可能覆盖规则、DNS 等整份设置。
导入失败排查:按响应、语法、内核、运行顺序检查
- 检查返回内容。下载到本地后查看开头几行。HTTP
200只代表请求成功返回,不保证正文就是配置;401、403则优先检查鉴权与访问限制。某些服务根据 User-Agent 返回不同格式,浏览器与客户端看到的内容可能不同。 - 检查外层编码。如果是 Base64,先解码一次并查看结果。不要反复盲目解码,也不要把订阅地址、网页正文和编码节点串混在一起处理。
- 检查 YAML 语法。“mapping”“indentation”等错误通常与缩进、冒号、引号有关。记录报错行号,并检查前后几行;在线 YAML 检查器不适合直接粘贴含凭据的真实配置。
- 检查字段支持。“unsupported proxy type”通常指向协议与内核能力不匹配。先确认客户端实际启动的是哪个内核,再查看该内核的版本与支持列表。
- 检查名称引用。“proxy not found”一类错误要查节点名、策略组名、provider 名称是否一致。完整配置里只有节点、没有可用策略,也可能导致预期分流无法生效。
- 检查运行状态。配置加载成功后,再确认本地代理端口、系统代理或 TUN 是否按需启用。导入成功、代理入口启用、节点能够连接,是三个不同检查点。
转换后出现“节点能测速,网页打不开”,也不应立即归因于编码。测速仅覆盖指定测试请求;真实访问还受 DNS、路由规则、UDP 支持和应用代理设置影响。先查看失败连接命中了哪个策略、选中了哪个节点,再定位具体环节。
格式选型结论:优先拿到目标客户端原生可用的数据
- 需要直接导入并使用:优先选择服务提供方明确标注适用于当前内核的完整 Clash 或 mihomo 配置,再核对分流与 DNS 设置。
- 已有自己的规则:优先使用 provider 节点数据,保持主配置独立,减少订阅更新覆盖本地设置的机会。
- 在不同客户端间迁移节点:URI 列表便于传递单节点,但要逐项复核协议扩展,不要期待它携带原来的全部策略。
- 收到 Base64 文本:先本地解码识别内容。编码只是外壳,真正决定导入方式的是内部数据结构。
确实需要转换时,优先使用本地运行的工具或自己控制的服务。远程转换服务会接触订阅凭据或节点信息,输出还可能引入额外规则与配置。保存原始输入、转换结果和一份可用备份,按“结构检查 → 字段对照 → 启用测试”的顺序处理,出问题才有清晰的回退点。