把 base64 订阅、原生 JSON 配置与 vmess、vless 分享链接三种格式拆开对照,给出「订阅 → 链接列表 → 单节点字段 → 原生 JSON」的完整转换路径,并列出转换过程中最容易丢失的字段。适合已经能连上节点、需要手工改配置或跨客户端迁移的读者。
三种格式各是什么
同一组节点信息,放进不同载体后长得完全不一样。base64 订阅是批量清单,原生 JSON 是完整配置,分享链接是单条记录。
三者的信息量并不对等:订阅里的一条链接通常只描述一个出站(outbound),而原生 JSON 还要额外承担入站、路由、DNS、日志这些客户端侧设置。搞混这一点,是后面所有转换问题的起点。
| 维度 | base64 订阅 | 原生 JSON | 分享链接 |
|---|---|---|---|
| 承载内容 | 多行分享链接 | 完整配置,含出站、入站与路由 | 单个节点的连接参数 |
| 自动更新 | 客户端定时拉取 | 手动替换文件 | 不支持 |
| 典型来源 | 面板批量导出 | 服务端配置文件或手工编写 | 客户端、面板单条复制 |
| 适用场景 | 多设备共用一份节点清单 | 精细分流与固定本地端口 | 临时导入、跨客户端迁移 |
base64 订阅的编码规则
base64 订阅只多一层编码:服务端把多行分享链接拼成纯文本,整体做一次 base64,再作为 HTTP 响应返回。客户端拉取后先解码,拿到每行一条的链接列表。
解码失败时,客户端会退回按明文处理,所以同一套解析逻辑能同时吃下 base64 与明文两种订阅。自己动手解码时,记住下面这条命令就够。
# 订阅返回的原文存成 sub.txt,整体解码一次
base64 -d sub.txt > nodes.txt # GNU coreutils
base64 -D sub.txt > nodes.txt # macOS / BSD
wc -l nodes.txt # 行数一般等于节点条数
head -n 2 nodes.txt
解码结果里每行开头就是协议前缀,常见的是 vmess:// 与 vless://。同一条订阅混用多种前缀是正常的,客户端按行逐条解析。
- URL-safe 变体:部分面板把
+、/换成-、_,解码前要换回来,或直接用支持 URL-safe 的解码器。 - padding:结尾的
=常被去掉,长度不是 4 的倍数时手动补齐再解。 - 逐行与整体:少数订阅对每行链接单独编码,这种情况要按行解码,整体解一次只会得到乱码。
如果解出来的第一行不是 vmess:// 也不是 vless://,说明原文本来就是明文订阅,不需要再解。
分享链接的字段结构
vmess 与 vless 的差别在编码方式上:vmess 链接是「base64 包一层 JSON」,vless 链接是「URI 加查询参数」。前者解出来的字段名全是缩写,后者直接在地址栏里就能读。
把 vmess:// 后面的整段 base64 解一次,得到的是下面这个对象:
{
"v": "2", // 链接格式版本,固定为 2
"ps": "香港-01", // 备注,导入后作为节点名
"add": "example.com", // 服务器地址
"port": "443", // 端口,这里是字符串
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
"aid": "0", // alterId,仅 VMess 有
"scy": "auto", // 加密方式
"net": "ws", // 传输层
"type": "none", // 伪装类型
"host": "example.com", // WS 的 Host 头
"path": "/ws", // WS 路径
"tls": "tls" // 是否启用 TLS
}
vless 链接没有内层 base64,所有参数都写在 ? 之后的查询串里,# 之后是备注。参数名比 vmess 的缩写更直观,但要按 URI 规则做 URL 编码。
vless://[email protected]:443?encryption=none&security=reality&sni=www.example.com&fp=chrome&pbk=UuMBgl8KtNqHqY7p&sid=0123abcd&flow=xtls-rprx-vision&type=tcp#香港-01
两种链接描述的是同一件事,只是字段名和摆放位置不同。下面四张卡把常用字段、原生 JSON 的顶层结构和本地端口约定放在一起对照。
vmess 链接字段
- add / port
- 地址与端口,port 是字符串
- id / aid
- UUID 与 alterId
- scy
- 加密方式,常用 auto 或 none
- net / type
- 传输层与伪装类型
- path / host
- WS 路径与 Host 头
整段是 base64(JSON),解一次即可读。
vless 链接参数
- encryption
- 固定 none,不可省略
- security
- none / tls / reality
- sni
- TLS 证书域名
- flow
- Reality 节点填 xtls-rprx-vision
- pbk / sid
- Reality 公钥与短 ID
参数写在查询串里,注意 URL 编码。
原生 JSON 顶层
- inbounds
- 本机监听,如 SOCKS 10808
- outbounds
- 出站节点,含 tag 与 streamSettings
- routing
- 分流规则,按 outboundTag 指向出站
- dns
- 解析方式与上游服务器
- log
- 日志级别,排查时用 debug
字段名区分大小写,port 必须是数字。
本机端口约定
- SOCKS
- 10808
- HTTP
- 10809
- 日志级别
- warning / debug
- 出站 tag
- proxy、direct、block 三个常用名
端口与 tag 由本地配置决定,与订阅无关。
三种格式怎么互相转换
转换路径固定为四步:订阅解出链接列表,链接还原成字段,字段再拼成原生 JSON。反向走一遍就是导出。
取出订阅原文
浏览器打开订阅地址,把返回内容整段存成 sub.txt。返回的可能是一整段 base64,也可能是明文链接列表。
解出链接列表
执行
base64 -d sub.txt > nodes.txt,得到每行一条的分享链接;协议前缀在行首,备注在行尾#之后。还原单个节点
vmess 把
vmess://后的内容再解一次 base64 得到 JSON;vless 直接读?后的查询参数,不需要再解码。拼成原生 JSON
把字段填进
outbounds的vnext与streamSettings:port改成数字,tag自己起名,address不带协议前缀。
第四步拼出来的出站大致长这样,字段与上面的 vless 链接一一对应:
{
"outbounds": [{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [{
"address": "example.com",
"port": 443,
"users": [{
"id": "b831381d-6324-4d53-ad4f-8cda48b30811",
"encryption": "none",
"flow": "xtls-rprx-vision"
}]
}]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "www.example.com",
"publicKey": "UuMBgl8KtNqHqY7p",
"shortId": "0123abcd",
"fingerprint": "chrome"
}
}
}] // 出站数组
}
反向转换同理:原生 JSON 里的 settings.vnext[0] 与 streamSettings 就是链接参数的展开形式,把 address、port、id 取出来,再按协议规则编码回 URI 即可。VMess 还要把 alterId 写回 aid。
客户端里还有两条更省事的路径:v2rayN 支持「自定义配置」类型的服务器,把完整 JSON 粘进配置框后内核直接读取,不再由客户端拼装出站;反过来,从订阅列表里复制单条节点的分享链接,可以直接粘到另一台设备的 v2rayNG 里,走「⋮」→「从剪贴板导入配置」。
转换时最容易丢的字段
掉字段几乎都发生在手工搬运环节:复制粘贴时被截断、字符串与数字混用、缩写看漏一个字母。下面这些位置逐条对一遍,能覆盖大部分「导入成功但连不上」的情况。
flow=xtls-rprx-vision:Reality 节点必填。漏掉后客户端按普通 VLESS 处理,服务端侧握手直接失败。pbk与sid:Reality 的公钥与短 ID 成对出现,只抄其中一个等于没抄。encryption=none:VLESS 的固定值,漏写时部分客户端会拒绝导入这条链接。aid:VMess 的 alterId,链接里是字符串,原生 JSON 里是数字;老服务端常用 2 或 64,漏填按 0 处理会握手失败。port的类型:链接 JSON 里是"443",原生 JSON 里必须是443,带引号会被内核判为无效配置。serviceName:type=grpc时用它代替path,两者填反会导致请求路径对不上。host与sni:前者是 WS 的 Host 头,后者是 TLS SNI。CDN 场景两者不同是正常的,填反会返回 403。outboundTag:routing.rules里的值必须与outbounds的tag逐字一致,大小写敏感。
注意
手改原生 JSON 时,保存前用编辑器跑一次 JSON 语法检查,尾随逗号和缺失的引号是最常见的两类报错。排查阶段先把 log.loglevel 设为 debug,让内核把出错字段写进日志,定位完再改回 warning。
什么场景用哪一种
三种格式没有优劣,只有分工。判断依据只有两条:节点清单会不会变,以及本机要不要分流规则。
选择依据:节点是否会变、是否需要本机分流
base64 订阅
- 一条地址管理全部节点
- 换设备只填一次,列表自动同步
- 节点增删由服务端决定,本地不用改
- 适合多设备、节点会调整的场景
原生 JSON
- 可以写 routing 分流规则与 DNS 策略
- 本地 SOCKS 10808、HTTP 10809 端口固定
- 节点改动要手工替换文件
- 适合单机、需要精细化控制的场景
两者可以并存:订阅负责节点清单,原生 JSON 里的 routing 负责决定哪些流量走代理。
分享链接站在中间:它比订阅更适合临时导入,比原生 JSON 更适合跨客户端复制。同一条链接粘进 v2rayN 与 v2rayNG,得到的出站参数是一样的,差别只在客户端把本地端口和分流规则放在了自己的设置里。
实际使用中更常见的组合是:服务端维护一条订阅地址,客户端里再补一份本机路由规则。节点跟随订阅更新,分流逻辑留在本地,两边互不干扰。
常见问题
订阅地址在浏览器里打开是一串乱码?
那是 base64 原文,不是出错。整段复制下来解一次,或直接把地址填进客户端的订阅设置里更新。
vmess 链接导入后节点名变成问号?
ps 字段是 UTF-8 中文,解码工具按 GBK 处理就会乱码。换 UTF-8 重新解一次再导入。
vless 链接导入后提示缺少 flow?
Reality 节点要在 flow 里填 xtls-rprx-vision,同时补齐 pbk、sid、fp 三组参数。
自己写的 JSON 被判为无效配置?
先查尾随逗号与引号,再把 port 从字符串改成数字,最后核对 routing.rules[].outboundTag 与出站的 tag 是否一致。
三种格式的转换关系并不复杂:订阅解一层得到链接,vmess 链接再解一层得到字段,字段展开就是原生 JSON。真正费时间的从来不是解码,而是把字段一个不落地搬对位置。