先区分订阅地址、订阅响应和节点分享链接,再用一组 VLESS + WebSocket + TLS 示例对照 URI 与 Xray JSON 字段。本文适合遇到“订阅能打开但无法导入”“Base64 解码后仍不是配置”或需要迁移节点的用户;读完可以判断应使用哪种导入入口,并识别转换时会丢失的路由、DNS 和本地监听设置。
订阅地址、Base64 与 JSON 的层次区别
订阅地址通常是一个 HTTPS URL,客户端访问它后才获得节点数据。URL 本身不是 Base64,也不是节点配置;真正需要识别的是服务器返回的响应正文。同一个订阅地址可能根据请求参数或客户端标识返回不同内容,因此不能只凭地址后缀判断格式。
| 内容形式 | 识别线索 | 适用入口与边界 |
|---|---|---|
| 订阅地址 | https:// 开头,可能含访问令牌 | 添加到订阅设置,保留后续更新能力 |
| Base64 订阅正文 | 解码后常为按行排列的分享链接 | 一般由客户端订阅更新功能解析;不是完整运行配置 |
| 单节点分享链接 | vless:// 或常见的 vmess:// 开头 | 适合从剪贴板导入节点;通常不携带本地路由 |
| 内核原生 JSON | 具有 inbounds、outbounds 等字段 | 使用匹配内核的自定义配置入口,字段受内核支持范围约束 |
Base64 只是字节编码,不是加密。持有订阅正文的人通常可以还原服务器地址和身份信息。JSON 也只是数据语法:一段以花括号开头的文本,可能是节点描述、接口错误消息,或完整内核配置。必须检查内部字段,不能把“合法 JSON”等同于“可直接运行”。
Base64 订阅解码与重新编码
常见的 Base64 订阅先将多条分享链接以换行符连接,再把整段 UTF-8 文本编码。解码后如果看到多行 vless:// 或 vmess://,外层订阅已经还原;不需要再对每条 VLESS 链接做 Base64 解码。部分服务直接返回明文链接列表,这种情况应跳过外层解码。
- 先确认拿到的是响应正文,而不是浏览器登录页、访问限制提示或带状态码的错误信息。
- 对疑似 Base64 正文移除空格与换行,兼容 URL 安全变体中的
-、_,再补齐末尾填充。 - 将解码后的字节按 UTF-8 读取,逐行检查协议前缀,并保留每条链接内部的参数。
- 重新编码前确认客户端确实需要 Base64 列表;本地编码得到的是静态文本,并不会生成可自动更新的 HTTPS 订阅服务。
下面是可在本机浏览器开发者工具中使用的纯 JavaScript 函数。它通过字节数组处理中文备注,避免直接用 btoa 编码中文产生错误。函数只转换传入文本,不发起网络请求;输入应来自你信任的内容。
function decodeSubscription(source) {
const compact = source.trim().replace(/\s+/g, "")
.replace(/-/g, "+").replace(/_/g, "/");
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(compact)) {
throw new Error("输入不是有效的 Base64 字符序列");
}
const padded = compact + "=".repeat((4 - compact.length % 4) % 4);
const bytes = Uint8Array.from(atob(padded), ch => ch.charCodeAt(0));
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
}
function encodeSubscription(linkText) {
const bytes = new TextEncoder().encode(linkText);
let binary = "";
for (const byte of bytes) binary += String.fromCharCode(byte);
return btoa(binary);
}
const sampleText = "示例节点";
console.log(decodeSubscription(encodeSubscription(sampleText)));
解码函数报错时,不要反复套用多层转换。先检查正文是否被截断、是否带有引号或网页标签,再确认它是不是明文列表。即使成功解码,也仍需由客户端验证每条链接的协议、必填字段和传输设置。
vless:// 与 vmess:// 的字段结构
VLESS 分享链接通常采用 URI 结构:用户信息位置放 UUID,主机与端口描述服务器,查询参数描述传输和安全层,井号后面保存节点备注。下例使用文档示例域名与演示 UUID,只用于字段对照,不代表可连接的服务。
vless://[email protected]:443?encryption=none&security=tls&type=ws&host=example.net&path=%2Fws&sni=example.net#WS-TLS-demo
path=%2Fws 解码后是 /ws。查询参数里的路径、备注和特殊字符应使用百分号编码;不要把整条 URI 一次性编码,也不要对完整 URI 先解码再手动拆分,否则路径中的 & 等字符可能被误认成参数分隔符。IPv6 地址位于主机位置时还需要使用方括号。
VLESS 分享链接
- 身份
- UUID 位于 @ 之前
- 传输
- type=ws
- 安全层
- security=tls
- 路径
- path=%2Fws
本例使用 WebSocket 与 TLS,不应额外添加 Vision flow。
常见 VMess 分享格式
- 外层
- vmess:// 后接 Base64
- 服务器
- JSON 中的 add、port
- 身份
- JSON 中的 id
- 传输
- JSON 中的 net、path
这是常见客户端分享约定,不是可直接交给内核运行的 JSON。
常见 VMess 分享 JSON 中的 v 表示分享格式版本,不是 VMess 协议版本;ps 通常是备注。它与内核出站中的 settings.vnext 结构不同。VMess 的分享约定还存在变体,迁移时应优先使用两端客户端的导入、导出功能,而不是假设所有 vmess:// 内容都有完全相同的内部结构。
从 VLESS 链接生成 Xray 原生 JSON
将分享链接转成完整 JSON,需要补上链接中没有的本地入站与出口标签。下面配置与前面的 VLESS 示例对应,使用 Xray 配置结构;本地只监听 127.0.0.1:10808。实际使用前须替换为已获授权的真实服务器参数,示例域名本身不能提供代理服务。
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "example.net",
"port": 443,
"users": [
{
"id": "9f2a54d1-8bc6-4d71-a903-0be458e623fd",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"serverName": "example.net"
},
"wsSettings": {
"path": "/ws",
"headers": {
"Host": "example.net"
}
}
}
}
]
}
example.net:443对应出站的address与port;UUID 对应users[0].id。type=ws对应streamSettings.network,security=tls对应传输安全层。sni对应tlsSettings.serverName,host对应 WebSocket 的 Host 请求头,两者用途不同。encryption=none是 VLESS 用户字段,不表示 TLS 已关闭;是否启用 TLS 要看streamSettings.security。- 本例没有额外分流规则,流量使用第一个出站;它也没有替你开启操作系统或应用的代理设置。
在 v2rayN 与 v2rayNG 中选择导入入口
先区分“保留订阅关系”和“导入单个节点”。把订阅解码后逐条导入虽然能生成节点,但通常会失去订阅来源及自动更新关系。若希望以后继续更新服务器列表,应保存原始订阅 URL,而不是只保存当前导出的分享链接。
v2rayN:订阅、剪贴板与自定义配置分开处理
- 订阅 URL:打开「订阅分组」→「订阅分组设置」,新增分组,填写备注与 URL,保存后使用「订阅分组」中的更新订阅功能。更新完成后检查新增节点,而不是把 URL 当成单节点地址填写。
- 分享链接:复制完整的
vless://或vmess://文本,再使用「服务器」→「从剪贴板导入批量 URL」。导入后编辑节点,核对地址、端口、TLS、SNI 与传输路径。 - 完整 JSON:使用「服务器」→「添加自定义配置服务器」一类的自定义配置入口,选择与文件匹配的内核,再按界面要求选择配置文件。不要将整份 JSON 粘贴到订阅 URL 输入框。
v2rayNG:先建立订阅分组,再执行更新
- 在主界面菜单进入「订阅分组设置」,通过新增按钮填写订阅名称与地址,保存后返回主界面执行「更新订阅」。
- 对单条分享链接,复制完整文本,再点主界面「+」→「从剪贴板导入」。确认生成的配置类型与来源一致后再连接。
- 对 Xray 原生 JSON,使用「+」菜单里的自定义配置导入入口,按所用版本选择文件或剪贴板方式。不要把常见 VMess 分享 JSON 当成完整自定义配置导入。
不同发行版本的菜单文案可能略有调整,应按“订阅分组”“剪贴板链接”“自定义配置”这三个入口含义寻找。使用 v2flyNG 时,还要单独确认订阅中协议与传输的兼容性;v2rayNG 能识别某条 Xray 节点,不代表另一内核客户端也能运行同样配置。
JSON 反向导出与转换时的信息损失
“互相转换”不意味着三种格式总能完整往返。单节点链接主要描述远端连接,而完整 JSON 可能包含多个入站、多个出站、DNS、路由、策略和日志。把 JSON 导成一条 VLESS 链接,本质上是在选择其中一个出站并提取它的连接参数,其余本地行为通常无法放进链接。
| 转换方向 | 通常可以保留 | 需要额外处理 |
|---|---|---|
| 链接列表与 Base64 互转 | 原始链接文本与顺序 | 字符编码、换行与 URL 安全变体 |
| VLESS 链接转 JSON | 地址、身份、常见传输与安全参数 | 补充入站、出口标签及本地路由 |
| JSON 出站转分享链接 | 目标客户端支持的单节点字段 | 选择出站,处理扩展字段,另存 DNS 与分流规则 |
| VMess 转 VLESS | 仅能参考共用的地址与传输信息 | 服务端必须实际提供 VLESS,不能靠改前缀切换协议 |
迁移时优先在源客户端选择节点并使用导出分享链接功能,再在目标客户端检查字段。如果手头只有多出站 JSON,先根据 outbounds 中的 tag 与 protocol 确定目标,不能把直连或阻断出站误当成服务器。涉及扩展参数时,应保留原 JSON 备份,并在目标端查看实际生成的配置。
- 仅迁移一个节点:使用客户端导出的分享链接,随后核对传输和安全参数。
- 迁移整个订阅:保存原订阅 URL,并在目标客户端重新创建订阅分组。
- 迁移完整行为:另行备份路由、DNS 和自定义配置,同时排查本地端口冲突。
订阅解码与导入常见问题
订阅地址在浏览器能打开,为什么客户端更新失败?
先看返回内容是否真的是节点列表,而不是登录网页或接口错误 JSON。再核对完整 URL 是否遗漏令牌与查询参数。若当前网络无法直接访问该地址,可在已有可用节点的前提下选择通过代理更新;不要用同一个尚未导入的节点作为更新所需的唯一网络出口。
Base64 解码成功,却提示没有可导入的服务器?
检查解码结果每一行的协议前缀。外层 Base64 成功只证明编码可还原,不证明内容受客户端支持。若得到的是 JSON,继续判断它是分享字段对象还是完整配置;若是 HTML,就回到订阅请求本身排查,不要继续编码。
分享链接能导入,但连接仍然超时怎么办?
打开节点编辑界面,对照来源检查端口、传输路径、TLS 和 SNI。本文示例的远端端口是 443,本地 10808 只是 SOCKS 监听端口,不能互换。再查看核心日志,区分域名解析、连接超时和 TLS 握手错误;“导入成功”仅说明解析器接受了字段。
为什么转换后国内直连规则消失了?
节点分享链接一般不承载整套本地路由。请在目标客户端单独恢复路由设置;若使用自定义 JSON,检查 routing.rules 与出口标签是否对应。需要设置 domainStrategy 时,应放在 routing 层级,而不是塞进单条规则。
最后验证时,每次只改变一个层次:先保证内容格式正确,再确认字段完整,最后检查网络与内核运行。这样可以把“订阅获取失败”“链接解析失败”和“节点连接失败”分开处理,避免在编码工具与代理设置之间反复试错。