V2Ray 订阅格式详解:Base64 订阅、原生 JSON 与分享链接如何互转

梳理 Base64 编码订阅、完整 JSON 配置与 vmess/vless 分享链接三种格式的结构差异,说明各自适用的客户端场景与手动转换方法。

本文速览

先区分订阅地址、服务器分享链接与完整配置,再判断能否转换。Base64 订阅通常只是多条分享链接的编码包装;原生 JSON 还包含本地监听、DNS 与路由,不能靠换后缀变成订阅。本文适合遇到“订阅无法识别”“JSON 导入失败”或需要跨客户端迁移的用户,提供本地编码方法、字段对应关系与导入后的检查步骤。

先识别内容:订阅地址不等于订阅格式

日常所说的“V2Ray 订阅”并不是一种涵盖所有客户端的统一文件标准。一个以 https:// 开头的订阅地址,只表示客户端需要访问某个接口;服务器返回的正文,才决定它是链接列表、Base64 文本,还是某种配置文件。同一个接口也可能根据请求参数或客户端标识返回不同内容,因此不能只看地址后缀判断兼容性。

按响应正文识别三类常见内容
内容类型常见外观实际保存的内容合适的入口
链接列表订阅多行协议链接,或一整段 Base64多个服务器的连接参数订阅分组与更新功能
单条分享链接vmess:// 或 vless://一个服务器的连接参数及备注从剪贴板导入服务器
完整原生 JSON含 inbounds、outbounds 等字段内核的一套运行配置与内核匹配的自定义配置入口

取得订阅正文时,先留意是否实际收到了错误页。开头出现网页标签、登录提示,或者“访问已过期”等文字,意味着请求没有得到预期的节点内容。把错误页再次 Base64 编码,只会得到一个编码后的错误页,不会修复订阅。

按用途选格式:日常更新与整套配置分开管理

对 v2rayN、v2rayNG、v2flyNG 来说,服务器列表和运行配置属于不同层级。客户端可以依据服务器参数生成内核配置,但完整配置里包含的本地端口与分流策略,未必能反向装进一条分享链接。选格式时先确定需要迁移的是“节点”,还是“节点加本机策略”。

客户端兼容的链接列表订阅

推荐

保留远程订阅地址,由客户端定期或手动获取服务器列表。提供方变更节点时,可以通过更新订阅取得新内容。

适合:日常维护多个服务器、需要持续更新节点列表

单条 VMess / VLESS 分享链接

便于导入一个服务器,也便于逐项核对连接参数。导入后通常是本地服务器记录,不自动继承原订阅的更新关系。

适合:临时测试一个节点、手工迁移少量服务器

与内核匹配的完整 JSON

可以表达入站、出站、DNS 与路由等设置。需要确认目标内核支持相应字段,不能只依据文件扩展名判断。

适合:维护自定义路由、固定本地监听与多出站配置

v2rayNG 使用 Xray 内核,v2flyNG 使用 V2Fly 内核;v2rayN 的实际能力还要结合所选内核判断。同为 JSON 并不代表配置可以直接通用,同为 VLESS 也不意味着每种传输、安全设置都能被所有目标版本识别。转换前应以目标客户端与内核的实际支持范围为准。

Base64 订阅怎么解码:先去包装,再检查每行

常见的 Base64 订阅制作方式,是把多条分享链接按换行连接,再对整段文本编码。解开外层后,可能看到 vmess:// 和 vless:// 混排。特别要注意:传统 VMess 分享链接本身又包含一层 Base64,因此解开订阅外层,不等于已经解开每个 VMess 节点。

3 → 4
Base64 每 3 字节对应 4 个字符,不足时补位
443
下文 TLS 服务端口示例,不代表节点固定端口
10808
下文 JSON 本地 SOCKS 监听示例

Base64 是编码,不是加密。标准编码常用 +、/ 和尾部的 =;URL 安全变体会使用 -、_,有些输出还省略补位。中文备注应按 UTF-8 处理,否则直接使用字符编码转换可能产生乱码。

下面是可在本地浏览器空白页开发者工具中使用的函数。它只处理传入的文本,不请求网络;示例域名、UUID 和端口用于说明结构,不是可连接的服务。

function decodeBase64Utf8(input) {
  let text = input.trim().replace(/\s+/g, "")
    .replace(/-/g, "+").replace(/_/g, "/");
  if (text.length % 4 === 1) {
    throw new Error("Base64 长度无效");
  }
  text = text.padEnd(Math.ceil(text.length / 4) * 4, "=");
  const bytes = Uint8Array.from(atob(text), ch => ch.charCodeAt(0));
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
}

function encodeBase64Utf8(input) {
  const bytes = new TextEncoder().encode(input);
  const binary = Array.from(bytes, byte => String.fromCharCode(byte)).join("");
  return btoa(binary);
}

const exampleLink = "vless://[email protected]:443?encryption=none&security=tls&type=tcp&sni=example.com#TLS-demo";
const encodedList = encodeBase64Utf8(exampleLink + "\n");
console.log(decodeBase64Utf8(encodedList));
  1. 先确认正文是不是已经明文列出协议链接;如果是,直接检查列表,不必再解码。
  2. 若正文是整段编码文本,用解码函数去掉外层包装,然后按换行拆分,忽略空行。
  3. 检查每行的协议前缀。只有明确识别为传统 VMess 编码结构时,才继续解开其前缀后的内容。
  4. 如果解码失败,保留原文排查截断、网页内容或字符替换,不要把多次盲目解码当作修复办法。

VMess 与 VLESS 分享链接:结构不同,不能互换前缀

传统 VMess 链接:JSON 再编码

常见的传统 VMess 分享形式为 vmess:// 加 Base64 编码后的节点 JSON。这份节点 JSON 不是内核完整配置;它没有描述本机所有入站和路由。下面展示编码前的常见字段结构,其中 v 是分享结构版本标识,不是客户端或内核版本号。

{
  "v": "2",
  "ps": "VMess TLS 示例",
  "add": "example.com",
  "port": "443",
  "id": "11111111-1111-4111-8111-111111111111",
  "aid": "0",
  "scy": "auto",
  "net": "tcp",
  "type": "none",
  "host": "",
  "path": "",
  "tls": "tls",
  "sni": "example.com"
}

将这段对象序列化后,可以使用前面的编码函数组合出传统链接:"vmess://" + encodeBase64Utf8(JSON.stringify(node)),其中 node 为上述对象。反向解析时移除前缀,再解码并用 JSON.parse 读取。这里的 aid: "0" 对应常见 VMess AEAD 配置,不应因为旧教程而自行改成其他数值。

VLESS 链接:URI 字段与查询参数

VLESS 通常直接使用 URI 结构:用户标识位于 @ 前,服务器地址与端口位于其后,传输和安全参数放在查询部分,备注放在 # 后。中文备注需要百分号编码;字段中的特殊字符也应由 URI 工具正确编码,不能简单拼接未处理的文本。

vless://[email protected]:443?encryption=none&security=tls&type=tcp&sni=example.com#TLS-demo

原生 JSON 如何转换:提取节点,不是保留整套行为

完整配置包含“本地怎样接收流量”和“流量怎样发往远端”两部分。下面是 Xray 风格的精简结构示例:本机只在回环地址监听 SOCKS 端口,再通过一个 VLESS TLS 出站连接示例域名。它用于展示字段层级,不包含可用服务凭据,也不是各内核通用配置。

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "local-socks",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    }
  ],
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "example.com",
            "port": 443,
            "users": [
              {
                "id": "11111111-1111-4111-8111-111111111111",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls",
        "tlsSettings": {
          "serverName": "example.com"
        }
      }
    }
  ]
}
该 JSON 示例到 VLESS 链接的对应关系
JSON 字段分享链接位置示例值
settings.vnext[0].address主机名example.com
settings.vnext[0].port远端端口443
settings.vnext[0].users[0].idURI 用户信息示例 UUID
streamSettings.securitysecurity 查询参数tls
tlsSettings.serverNamesni 查询参数example.com
inbounds[0].port不写入服务器分享链接10808 是本机端口

上表中的出站子字段均相对于 outbounds[0]。手动提取时,先选中实际代理出站,再读取该出站的协议和传输参数。不要一律取数组第一项:真实配置的第一项可能是直连出站,也可能存在多个代理出站、链式连接或负载选择。

  1. JSON 转分享链接:提取一个目标出站能够表达的字段,按对应协议的分享规范生成链接;DNS、路由、本地监听及其他出站另行保存。
  2. 分享链接转 JSON:先在客户端导入节点,让客户端按当前设置生成内核运行配置;如需手写,除远端字段外,还要明确本地入站和默认出站行为。
  3. 链接列表转 Base64 订阅正文:将有效分享链接逐行连接,再进行一次 UTF-8 Base64 编码。得到的是订阅正文,不是能够远程更新的订阅地址。
  4. Base64 转完整 JSON:先解码识别内容,再逐节点转换。直接把编码文本放进 outbounds,不符合内核配置结构。

客户端导入与迁移:先备份,再用单节点验证

手动转换前先导出或备份现有设置,并保留原订阅地址。不要直接覆盖正在使用的订阅分组;新建一个测试分组导入少量节点,可以区分“格式解析失败”和“服务器连接失败”。下列菜单按常见中文界面描述,具体文字可能随客户端版本变化。

迁移方案:服务器信息与本机配置分别处理

桌面端:v2rayN
  • 远程地址使用「订阅分组」→「订阅分组设置」添加,再更新目标分组。
  • 单条链接使用「服务器」→「从剪贴板导入批量 URL」,先检查导入结果。
  • 核对本地监听端口、所选内核与路由设置,不把远端 443 当成本机代理端口。
安卓端:v2rayNG / v2flyNG
  • 远程订阅在订阅分组设置中添加;单条链接使用主界面的剪贴板导入入口。
  • v2rayNG 按 Xray 能力检查参数,v2flyNG 按 V2Fly 能力检查参数。
  • 重新确认 VPN 授权与分应用设置,这些本机选项不会随普通节点链接迁移。

同一订阅可以作为两端的共同来源,但更新时点、协议支持与本机策略仍需分别核对。

导入后先打开节点编辑界面,对照原始内容检查地址、端口、用户标识、传输类型与 TLS 参数,再启动连接查看日志。如果列表正常但握手失败,应检查连接参数和服务端状态;如果节点数量为零,则优先排查响应正文与导入入口,而不是先修改路由。

订阅转换常见问题:能解码不代表能连接

Base64 解出来还是 vmess 开头,是不是没解完?

这通常是正常的外层订阅列表。先按行拆分;对于传统 VMess 链接,再取 vmess:// 后的部分解码为节点 JSON。不要对整份混合链接列表重复解码,否则会把 URI 标点也当成编码内容处理。

拿到 JSON,为什么“从剪贴板导入”提示没有服务器?

先看顶层字段。若含 inbounds、outbounds,它可能是完整内核配置,应使用目标版本支持的自定义配置入口,或者按本文步骤提取单个代理出站。剪贴板分享链接入口不是通用 JSON 导入器。

改成 Base64 以后,为什么仍然导不进客户端?

先解码回原文确认内容没有损坏,再检查每行是否为目标客户端支持的协议链接。Base64 只改变文本表示,不会补齐缺失的用户标识,不会把网页转换成节点,也不会增加内核不具备的协议支持。

转换后节点能用了,为什么分流规则没跟过来?

普通分享链接主要表达单个远端节点,不负责完整迁移 DNS、路由和分应用设置。回到目标客户端核对本机策略;需要复现整套路由时,保留原生配置并确认内核字段兼容,不能把节点连接成功当作配置迁移完成。

最终判断顺序是:先确认拿到的是正确正文,再确认编码层次,然后核对节点字段,最后检查目标内核和本机流量入口。订阅、分享链接与原生 JSON 各有用途;只有明确每一步保留什么、丢失什么,手动转换才不会把连接问题和配置问题混在一起。相关概念可继续查看名词解释,路由与内核设置可查阅配置进阶。

下载v2rayN