订阅格式科普:base64、原生 JSON 与分享链接怎么互相转换

订阅地址打开是一串乱码,vmess 链接导入后节点名变问号,手写 JSON 少一个字段就连不上。三种格式的边界在哪、转换时哪一步最容易掉字段,本文按字段逐条对照。

本文速览

把 base64 订阅、原生 JSON 配置与 vmess、vless 分享链接三种格式拆开对照,给出「订阅 → 链接列表 → 单节点字段 → 原生 JSON」的完整转换路径,并列出转换过程中最容易丢失的字段。适合已经能连上节点、需要手工改配置或跨客户端迁移的读者。

三种格式各是什么

同一组节点信息,放进不同载体后长得完全不一样。base64 订阅是批量清单,原生 JSON 是完整配置,分享链接是单条记录。

三者的信息量并不对等:订阅里的一条链接通常只描述一个出站(outbound),而原生 JSON 还要额外承担入站、路由、DNS、日志这些客户端侧设置。搞混这一点,是后面所有转换问题的起点。

维度base64 订阅原生 JSON分享链接
承载内容多行分享链接完整配置,含出站、入站与路由单个节点的连接参数
自动更新客户端定时拉取手动替换文件不支持
典型来源面板批量导出服务端配置文件或手工编写客户端、面板单条复制
适用场景多设备共用一份节点清单精细分流与固定本地端口临时导入、跨客户端迁移
1 次
订阅整体解码次数
2 层
vmess 节点总解码层数
443
TLS 与 Reality 常用端口
0
VMess 的 alterId 默认值

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://。同一条订阅混用多种前缀是正常的,客户端按行逐条解析。

如果解出来的第一行不是 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。反向走一遍就是导出。

  1. 取出订阅原文

    浏览器打开订阅地址,把返回内容整段存成 sub.txt。返回的可能是一整段 base64,也可能是明文链接列表。

  2. 解出链接列表

    执行 base64 -d sub.txt > nodes.txt,得到每行一条的分享链接;协议前缀在行首,备注在行尾 # 之后。

  3. 还原单个节点

    vmess 把 vmess:// 后的内容再解一次 base64 得到 JSON;vless 直接读 ? 后的查询参数,不需要再解码。

  4. 拼成原生 JSON

    把字段填进 outboundsvnextstreamSettings: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 就是链接参数的展开形式,把 addressportid 取出来,再按协议规则编码回 URI 即可。VMess 还要把 alterId 写回 aid

客户端里还有两条更省事的路径:v2rayN 支持「自定义配置」类型的服务器,把完整 JSON 粘进配置框后内核直接读取,不再由客户端拼装出站;反过来,从订阅列表里复制单条节点的分享链接,可以直接粘到另一台设备的 v2rayNG 里,走「⋮」→「从剪贴板导入配置」。

转换时最容易丢的字段

掉字段几乎都发生在手工搬运环节:复制粘贴时被截断、字符串与数字混用、缩写看漏一个字母。下面这些位置逐条对一遍,能覆盖大部分「导入成功但连不上」的情况。

注意

手改原生 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,同时补齐 pbksidfp 三组参数。

自己写的 JSON 被判为无效配置?

先查尾随逗号与引号,再把 port 从字符串改成数字,最后核对 routing.rules[].outboundTag 与出站的 tag 是否一致。

三种格式的转换关系并不复杂:订阅解一层得到链接,vmess 链接再解一层得到字段,字段展开就是原生 JSON。真正费时间的从来不是解码,而是把字段一个不落地搬对位置。

下载 v2rayN / v2rayNG

Windows、macOS、Linux 桌面版与安卓版入口在下载页;订阅导入与分流设置见教程。

下载客户端