Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

提议制定 VMess 分享链接标准 #720

Closed
ghost opened this issue Jun 2, 2020 · 13 comments
Closed

提议制定 VMess 分享链接标准 #720

ghost opened this issue Jun 2, 2020 · 13 comments

Comments

@ghost
Copy link

ghost commented Jun 2, 2020

1. 为什么提议指定官方标准?

现有的主流 vmess:// 分享链接分为以下几种:

  1. V2RayN 格式
  2. ShadowRocket 格式
  3. Quantumult 格式
  4. 等……

以上分享链接协议仅仅适用于自家软件的导入/导出,普通用户如需要转换则需要第三方组件,在无形之中增加了链接配置被恶意盗用的可能性。

另外,V2Ray 现已然成为一个平台化程序,我认为有必要设计一个 VMess 协议的标准分享链接格式,这对于个人用户在设备间分享 / 机场进行标准化适配 / 新客户端编写都具有更多的便利性

2. 标准格式提议

新的 vmess:// 标准应当避免使用 Json 存储,同时应当避免大量使用 Base64:

  • Json 是数据交换格式,但不应用在 URL 中,URL 标准有 Query 项目可以存储协议相关设置

  • Base64 的输出会导致配置项不便于观察,在此基础上,Base64 并不能防止数据篡改或因为传输原因损坏:

    echo "SGVsbG8K" | base64 -d
    #---> Hello
    echo "SGRsbG8K" | base64 -d
    #---> Hdllo

3. 链接格式标准

下列标准使用类 Python 语法的伪代码编写

在标准中,bool 类型的值将遵循以下规定:

  • 表示 真 的值: true, True, Yes, On
  • 表示 假 的值:false, False, No, Off, 0
  • 其余值如果出现,将解析为真
PROTOCOL_OPTION_OBJECT = struct { 名称, 值类型, 默认值 }

# PROTOCOL_OPTIONS = [ PROTOCOL_OPTION_OBJECT ]

PROTOCOL_OPTIONS = []
# QUIC 和 KCP 所需的混淆类型
QUIC_KCP_HEADERS_TYPES = enum { "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" }
# QUIC 所需的 Security 类型
QUIC_SECURITY_TYPES = enum { "none", "aes-128-gcm", "chacha20-poly1305" }
# TCP 所需的 Type
TCP_TYPES = enum { "none", "http" }

switch streamSettings.protocol:
    case TCP:
        PROTOCOL = "tcp"
        PROTOCOL_OPTIONS += { "type", TCP_TYPES, "none" }
        PROTOCOL_OPTIONS += { "host", string, "" }

    case HTTP:
        PROTOCOL = "http"
        PROTOCOL_OPTIONS += { "path", string, "/" }
        # 每个 Host 项使用 "|" 分割
        PROTOCOL_OPTIONS += { "host", string, "" }

    case WS:
        PROTOCOL = "ws"
        PROTOCOL_OPTIONS += { "path", string, "/" }
        PROTOCOL_OPTIONS += { "host", string, "" }

    case KCP:
        PROTOCOL = "kcp"
        PROTOCOL_OPTIONS += { "type", QUIC_KCP_HEADERS_TYPES, "none" }
        PROTOCOL_OPTIONS += { "seed", string, "" }

    case QUIC:
        PROTOCOL = "quic"
        PROTOCOL_OPTIONS += { "security", QUIC_SECURITY_TYPES, "none" }
        PROTOCOL_OPTIONS += { "key", string, "" }
        PROTOCOL_OPTIONS += { "type", QUIC_KCP_HEADERS_TYPES, "none" }

TLS_OPTIONS = []
if hasTLS:
    # TLS 配置
    # e.g.
    #     ws+tls
    #     ws
    #     quic+tls
    #     tcp
    URL_USERNAME_PART = PROTOCOL + "+tls"

    # AllowInsecure 选项扬了
    TLS_OPTIONS += { "tlsServerName", string, "" }
else:
    URL_USERNAME_PART = PROTOCOL


# UUID: 带 "-" 分割的 UUID
# alterId: int
# host: string
# port: int
# e.g. "kcp+tls:aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee-64@server.com:1234"
URL_PART_A = f"{URL_USERNAME_PART}:{UUID}-{alterId}@{HOST}:{PORT}"

# 协议相关设置项,值使用 encodeURIComponent 编码
URL_PART_B = [for OPT in PROTOCOL_OPTIONS, f"{OPT.名称}={encodeURIComponent(OPT.)}"].join("&")

# TLS 相关设置项,值使用 encodeURIComponent 编码
URL_PART_C = [for OPT in TLS_OPTIONS, f"{OPT.名称}={encodeURIComponent(OPT.)}"].join("&")

# ALIAS: string
URL_PART_D = encodeURIComponent(ALIAS)

FULL_VMESS_URL = "vmess://" + URL_PART_A + "/?" + URL_PART_B + URL_PART_C + "#" + URL_PART_D

链接格式解析样例

vmess://ws+tls:7db04e8f-7cfc-46e0-9e18-d329c22ec353-64@myServer.com:12345/?path=%2FmyServerAddressPath%2F%E4%B8%AD%E6%96%87%E8%B7%AF%E5%BE%84%2F&host=www.myServer.com&tlsAllowInsecure=true&tlsServerName=%E4%BC%AA%E8%A3%85%E5%9F%9F%E5%90%8D.com#%E4%B8%AA%E6%80%A7%E5%8C%96%E9%93%BE%E6%8E%A5%E5%A4%87%E6%B3%A8

传输协议: WS + TLS
UUID/AlterID: 7db04e8f-7cfc-46e0-9e18-d329c22ec353 / 64
服务器地址/端口: myServer.com:12345
协议设置: path=/myServerAddressPath/中文路径/
		 host=www.myServer.com
TLS 设置:SNI: 伪装域名.com
连接名:"个性化链接备注"
vmess://kcp:ba1b8f8f-efe6-427f-99b2-50491f0adf86-10@baidu.com:443/?type=srtp#AirportConnection1

传输协议: KCP
UUID/AlterID: ba1b8f8f-efe6-427f-99b2-50491f0adf86/10
服务器地址/端口: baidu.com:443
协议设置: type=srtp
连接名: AirportConnection1
vmess://unknown:2e09f64c-c967-4ce3-9498-fdcd8e39e04e-10@google.com:4433/?query=Value1#Connection2
"unknown" 不是 V2Ray 已知传输协议,因此 vmess 链接非法
vmess://tcp:2e09f64c-c967-4ce3-9498-fdcd8e39e04e-10@google.com:4433/?query=Value1#Connection2

传输协议: TCP
UUID/AlterID: 2e09f64c-c967-4ce3-9498-fdcd8e39e04e/10
服务器地址/端口: google.com:4433
协议设置: TCP type 由于未在链接中出现,所以使用默认值 none
         链接中 "query" 项忽略
连接名: Connection2

Update: V2Ray-core 新增了 KCP Seed,因此更新
Update: 更新 TLSServerNametlsServerName
Update: 新增 TCP 在 HTTP 伪装时的 host 字段

Update: 移除了 tlsAllowInsecure

@ghost
Copy link
Author

ghost commented Jun 2, 2020

鉴于 #711 正在设计 vmess-v2, 此处 vmess:// 亦可修改为 vmess1://

@iseki0
Copy link

iseki0 commented Jul 22, 2020

有待完善的内容:uuid和query部分的大小写(个人建议大小写敏感),URIComponent所使用的字符编码(目前个人选择utf-8)

@ghost
Copy link
Author

ghost commented Jul 23, 2020

我认为 query 部分应全部按照小驼峰命名法,
UUID 建议全小写或全大写 (没人会写成 aBcD-00eF-db41-AffC-Ab5601Bdcf2E 吧?)

另:都 0202 年了,强制 UTF-8 是合理的

@yomnxkcs
Copy link

URI设计的时候就不是用来分享vmess的,反过来我们设计vmess分享链接的时候为什么非要死套“URI标准”不可呢?
设计一个简单实用的标准不是比设计一个花瓶更好吗?

如果跳出“URI标准”就个思想束缚,那么一楼第2点所说的json问题就不存在了。然后便于观查这点就我个人而言,除非链接没法导入不然我是不会去看链接里面有什么鬼东西的。因为分享链接和二维码一样是给机器看的,不是给人看的。最后一个防篡改问题,粗略看了下这个issue提的标准也没解决这个问题吧,同时我不认为防篡改很重要。

接着就是FOV001二楼提的IPv6和正则问题也没解决。二楼所提的正则问题应该是说,在一堆乱七八槽的文本里面尽可能多的提取出合法分享链接,而不是用正则来切分分享链接中的各项。

比如在一些用bb code的论坛里面一个链接可能会是这样的:
[color=#f00]vmess://...[/color] <- 和FOV001三楼所提的给IPv6加括号冲突

比如有时wordpress会很“智能”的把半角标点替换成全角标点:
vmess://...,vmess://...,

比如有些好心的分享者在分享链接前加上个序号:
1.vmess://... 2.vmess://...

或者放进表格里:
<tr><td>vmess://...</td></tr><tr><td>vmess://...</td></tr>

但是在这些稀奇古怪的场景之下,v2rayN的“土制”分享链接都可以很容易的被提取出来。

当然v2rayN的标准也不完美,我一直想吐槽订阅格式最后套的那层Base64很多余。vmess://...每项和config.json的对应关系有点乱。不过这个分享标准设计得比较早,v2ray也在不断添内容,所以可以理解。
要是现在重新设计分享链接,我建议在v2rayN分享链接上改良。以下是我头脑一热想出来的,可能有些欠缺考虑的地方。

{
  "v": "3",
  "proto": "vmess/vless/socks/http/...",
  "add": "hostname/ipv6",
  "port": "port",
  "auth": ["uuid"] or ["username", "password"] or [],
  "stream":["ws", "tls", "/websocket", "www.baidu.com"] or [],
}

@ghost
Copy link
Author

ghost commented Aug 18, 2020

你在什么时候需要 "提取" 一个链接呢
此外,防篡改问题本身就无法避免,只是单纯说明 base64 起不到保护作用

@yomnxkcs
Copy link

上面已经说了使用场景了。bbcode就是各种讨论区,wordpress就是各种博客。这些其实就是多年以前v2ray萌芽期分享服务器的地方。这些也是很难完全封锁地方。
同时这是个“为什么不”的问题,既然有生命力更顽强的标准,为什么要自废武功,采用只能在温室里存活的标准。

@ghost
Copy link
Author

ghost commented Sep 9, 2020

相关讨论请去 v2fly

@ghost ghost closed this as completed Sep 9, 2020
@trulyliu
Copy link

什么时候能出确定标准呢?

@iwoomi
Copy link

iwoomi commented Jul 28, 2023

相关讨论请去 v2fly

这个在v2fly中有相关的讨论没?能不能贴个链接,我想接着看下文, 感谢!

@yomnxkcs
Copy link

这个在v2fly中有相关的讨论没?能不能贴个链接,我想接着看下文, 感谢!

没下文了,这个讨论3个月之后出了个 vless分享链接标准 ,现在过了一坤年,我说的那些缺点开始慢慢出现了。

vmess现在用的是 v2rayN分享链接标准 为主,其他标准的分享链接几乎没影了(我说的是公共渠道可以找到的分享)。

还有个用得比较多的是直接分享clash的yml配置文件,不过这不属于分享链接讨论范围。

@xiebruce
Copy link

xiebruce commented Aug 1, 2023

这个在v2fly中有相关的讨论没?能不能贴个链接,我想接着看下文, 感谢!

没下文了,这个讨论3个月之后出了个 vless分享链接标准 ,现在过了一坤年,我说的那些缺点开始慢慢出现了。

vmess现在用的是 v2rayN分享链接标准 为主,其他标准的分享链接几乎没影了(我说的是公共渠道可以找到的分享)。

还有个用得比较多的是直接分享clash的yml配置文件,不过这不属于分享链接讨论范围。

解析分享链接的话,我试了一下,遇到了一个问题,trojan的密码是放在前面的,它的密码中不允许出现?,#,%,同时kcp的seed和h2的key也不能出现这三个符号,主要是因为?是区别queryString的标记,#是区分hash的标记,%是url encode后会出现的符号,如果出现了这三个符号,将导致url parse出错,其它方面倒是没遇到什么问题。

为了避免这个问题,倒是可以对这trojan密码、kcp seed、h2 key做url encode(kcp也没人用了吧),不过这就会导致人类可读性降低,而且也许还不止这三个地方可能会用到?,#,%这三个符号,另一个方法就是避免使用这三个符号(有些人可能并不知道)。

其实我倒是我觉得base64方案简单粗暴,而且有它的优点:那就是我并不希望我复制分享链接的时候被剪贴板获取(用了kde connect,还有mac和iPhone的剪贴板都会同步的),虽然base64 decode一下就能得到原始字符串,不过一些获取剪贴板内容的(用于广告分析的)软件真的会这样做吗?我自己感觉这些软件应该会识别原文吧?(而原文是base64的话应该不会被识别到?)😂

我觉得二维码我们人类也看不见里面的信息,但它一样能分享节点,把分享链接看作是二维码就好了,又何必知道它里面是什么内容呢,想要知道是什么内容用程序看就好了。

不过人类可读可能对调试程序比较方便吧

@Hassan198813
Copy link

1. 为什么提议指定官方标准?

现有的主流vmess://分享链接分为以下几种:

  1. V2RayN Description
  2. ShadowRocket en anglais
  3. Quantumult 格式
  4. 等……

以上分享链接协议仅仅适用于自家软件的导入/导出,普通用户如需要转换则需要笨三方组件,圀无形之中增加了链接配置被恶意盗用的可能性。

V2Ray s'occupe de VMess于个人用户在设备间分享 / 机场进行标准化适配 / 新客户端编写都具有更多的便利性

2. 标准格式提议

Json est vmess://basé sur Base64 :

  • Json 是数据交换格式,但不应用在 URL 中,URL 标准有 Requête 项目可以存储协议相关设置
  • Base64 的输出会导致配置项不便于观察,在此基础上,Base64 并不能防止数据篡改或因为传输原因损坏:
    echo "SGVsbG8K" | base64 -d
    #---> Hello
    echo "SGRsbG8K" | base64 -d
    #---> Hdllo

3. 链接格式标准

下列标准使用类 Python 语法的伪代码编写

在标准中,bool类型的值将遵循以下规定:

  • 表示 真 的值 :true, True, Yes, On
  • 表示 假 的值 :false, False, No, Off, 0
  • 其余值如果出现,将解析为真
PROTOCOL_OPTION_OBJECT = struct { 名称, 值类型, 默认值 }

# PROTOCOL_OPTIONS = [ PROTOCOL_OPTION_OBJECT ]

PROTOCOL_OPTIONS = []
# QUIC 和 KCP 所需的混淆类型
QUIC_KCP_HEADERS_TYPES = enum { "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" }
# QUIC 所需的 Security 类型
QUIC_SECURITY_TYPES = enum { "none", "aes-128-gcm", "chacha20-poly1305" }
# TCP 所需的 Type
TCP_TYPES = enum { "none", "http" }

switch streamSettings.protocol:
    case TCP:
        PROTOCOL = "tcp"
        PROTOCOL_OPTIONS += { "type", TCP_TYPES, "none" }
        PROTOCOL_OPTIONS += { "host", string, "" }

    case HTTP:
        PROTOCOL = "http"
        PROTOCOL_OPTIONS += { "path", string, "/" }
        # 每个 Host 项使用 "|" 分割
        PROTOCOL_OPTIONS += { "host", string, "" }

    case WS:
        PROTOCOL = "ws"
        PROTOCOL_OPTIONS += { "path", string, "/" }
        PROTOCOL_OPTIONS += { "host", string, "" }

    case KCP:
        PROTOCOL = "kcp"
        PROTOCOL_OPTIONS += { "type", QUIC_KCP_HEADERS_TYPES, "none" }
        PROTOCOL_OPTIONS += { "seed", string, "" }

    case QUIC:
        PROTOCOL = "quic"
        PROTOCOL_OPTIONS += { "security", QUIC_SECURITY_TYPES, "none" }
        PROTOCOL_OPTIONS += { "key", string, "" }
        PROTOCOL_OPTIONS += { "type", QUIC_KCP_HEADERS_TYPES, "none" }

TLS_OPTIONS = []
if hasTLS:
    # TLS 配置
    # e.g.
    #     ws+tls
    #     ws
    #     quic+tls
    #     tcp
    URL_USERNAME_PART = PROTOCOL + "+tls"

    # AllowInsecure 选项扬了
    TLS_OPTIONS += { "tlsServerName", string, "" }
else:
    URL_USERNAME_PART = PROTOCOL


# UUID: 带 "-" 分割的 UUID
# alterId: int
# host: string
# port: int
# e.g. "kcp+tls:aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee-64@server.com:1234"
URL_PART_A = f"{URL_USERNAME_PART}:{UUID}-{alterId}@{HOST}:{PORT}"

# 协议相关设置项,值使用 encodeURIComponent 编码
URL_PART_B = [for OPT in PROTOCOL_OPTIONS, f"{OPT.名称}={encodeURIComponent(OPT.)}"].join("&")

# TLS 相关设置项,值使用 encodeURIComponent 编码
URL_PART_C = [for OPT in TLS_OPTIONS, f"{OPT.名称}={encodeURIComponent(OPT.)}"].join("&")

# ALIAS: string
URL_PART_D = encodeURIComponent(ALIAS)

FULL_VMESS_URL = "vmess://" + URL_PART_A + "/?" + URL_PART_B + URL_PART_C + "#" + URL_PART_D

链接格式解析样例

vmess://ws+tls:7db04e8f-7cfc-46e0-9e18-d329c22ec353-64@myServer.com:12345/?path=%2FmyServerAddressPath%2F%E4%B8%AD%E6%96%87%E8%B7%AF%E5%BE%84%2F&host=www.myServer.com&tlsAllowInsecure=true&tlsServerName=%E4%BC%AA%E8%A3%85%E5%9F%9F%E5%90%8D.com#%E4%B8%AA%E6%80%A7%E5%8C%96%E9%93%BE%E6%8E%A5%E5%A4%87%E6%B3%A8

传输协议: WS + TLS
UUID/AlterID: 7db04e8f-7cfc-46e0-9e18-d329c22ec353 / 64
服务器地址/端口: myServer.com:12345
协议设置: path=/myServerAddressPath/中文路径/
		 host=www.myServer.com
TLS 设置:SNI: 伪装域名.com
连接名:"个性化链接备注"
vmess://kcp:ba1b8f8f-efe6-427f-99b2-50491f0adf86-10@baidu.com:443/?type=srtp#AirportConnection1

传输协议: KCP
UUID/AlterID: ba1b8f8f-efe6-427f-99b2-50491f0adf86/10
服务器地址/端口: baidu.com:443
协议设置: type=srtp
连接名: AirportConnection1
vmess://unknown:2e09f64c-c967-4ce3-9498-fdcd8e39e04e-10@google.com:4433/?query=Value1#Connection2
"unknown" 不是 V2Ray 已知传输协议,因此 vmess 链接非法
vmess://tcp:2e09f64c-c967-4ce3-9498-fdcd8e39e04e-10@google.com:4433/?query=Value1#Connection2

传输协议: TCP
UUID/AlterID: 2e09f64c-c967-4ce3-9498-fdcd8e39e04e/10
服务器地址/端口: google.com:4433
协议设置: TCP type 由于未在链接中出现,所以使用默认值 none
         链接中 "query" 项忽略
连接名: Connection2

Mise à jour : V2Ray-core pour KCP Seed, et mise à TLSServerNamejourtlsServerName : mise à jour actuelle Mise à jour : TCP et HTTP pour l'hôte

Mise à jour : 移除了tlsAllowInsecure

@Hassan198813
Copy link

#720 (comment)

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants