From e20ff16a2fce50a90eaed4a9dd597bb4be124f68 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sun, 27 Feb 2022 17:03:38 +0800 Subject: [PATCH] update: support gRPC multi-mode --- ProxyBuilder/V2ray.py | 23 ++++++++++------------ ProxyBuilder/Xray.py | 19 +++++++++++++++++- ProxyFilter/V2ray.py | 8 ++++++++ ProxyTester/Trojan.py | 5 +++++ ProxyTester/V2ray.py | 46 +++++++++++++++++++++++++++++-------------- ProxyTester/VLESS.py | 5 +++++ Run.py | 2 +- docs/ProxyObject.md | 31 +++++++++++++++++++++++++++-- 8 files changed, 107 insertions(+), 32 deletions(-) diff --git a/ProxyBuilder/V2ray.py b/ProxyBuilder/V2ray.py index f367c76..ec748d7 100644 --- a/ProxyBuilder/V2ray.py +++ b/ProxyBuilder/V2ray.py @@ -73,7 +73,7 @@ def kcpConfig(streamInfo: dict, secureFunc) -> dict: # mKCP传输方式配置 'kcpSettings': kcpObject }, **secureFunc(streamInfo['secure'])} -def wsConfig(streamInfo: dict, edInPath: bool, secureFunc) -> dict: # WebSocket传输方式配置 +def wsConfig(streamInfo: dict, secureFunc) -> dict: # WebSocket传输方式配置 wsObject = { 'path': streamInfo['path'] } @@ -81,14 +81,8 @@ def wsConfig(streamInfo: dict, edInPath: bool, secureFunc) -> dict: # WebSocket wsObject['headers'] = {} wsObject['headers']['Host'] = streamInfo['host'] if streamInfo['ed'] is not None: - if not edInPath: - wsObject['maxEarlyData'] = streamInfo['ed'] - wsObject['earlyDataHeaderName'] = 'Sec-WebSocket-Protocol' - else: # ed参数写入路径 -> /...?ed=xxx - if wsObject['path'].find('?') == -1: # 原路径不带参数 - wsObject['path'] += '?ed=' + str(streamInfo['ed']) - else: - wsObject['path'] += '&ed=' + str(streamInfo['ed']) + wsObject['maxEarlyData'] = streamInfo['ed'] + wsObject['earlyDataHeaderName'] = 'Sec-WebSocket-Protocol' return {**{ 'network': 'ws', 'wsSettings': wsObject @@ -118,11 +112,14 @@ def quicConfig(streamInfo: dict, secureFunc) -> dict: # QUIC传输方式配置 }, **secureFunc(streamInfo['secure'])} def grpcConfig(streamInfo: dict, secureFunc) -> dict: # gRPC传输方式配置 + grpcObject = { + 'serviceName': streamInfo['service'] + } + if streamInfo['mode'] == 'multi': # gRPC multi-mode not work in v2fly-core + grpcObject['multiMode'] = True return {**{ 'network': 'grpc', - 'grpcSettings': { - 'serviceName': streamInfo['service'] - } + 'grpcSettings': grpcObject }, **secureFunc(streamInfo['secure'])} def v2rayStreamConfig(streamInfo: dict) -> dict: # 生成v2ray传输方式配置 @@ -132,7 +129,7 @@ def v2rayStreamConfig(streamInfo: dict) -> dict: # 生成v2ray传输方式配置 elif streamType == 'kcp': return kcpConfig(streamInfo, __secureConfig) elif streamType == 'ws': - return wsConfig(streamInfo, False, __secureConfig) + return wsConfig(streamInfo, __secureConfig) elif streamType == 'h2': return h2Config(streamInfo, __secureConfig) elif streamType == 'quic': diff --git a/ProxyBuilder/Xray.py b/ProxyBuilder/Xray.py index b41b24e..391cf0d 100644 --- a/ProxyBuilder/Xray.py +++ b/ProxyBuilder/Xray.py @@ -28,6 +28,23 @@ def __secureConfig(secureInfo: dict or None) -> dict: # TLS/XTLS加密传输配 else: raise Exception('Unknown secure type') +def wsConfig(streamInfo: dict, secureFunc) -> dict: # WebSocket传输方式配置 + wsObject = { + 'path': streamInfo['path'] + } + if streamInfo['host'] != '': + wsObject['headers'] = {} + wsObject['headers']['Host'] = streamInfo['host'] + if streamInfo['ed'] is not None: # ed参数写入路径 -> /...?ed=xxx + if wsObject['path'].find('?') == -1: # 原路径不带参数 + wsObject['path'] += '?ed=' + str(streamInfo['ed']) + else: + wsObject['path'] += '&ed=' + str(streamInfo['ed']) + return {**{ + 'network': 'ws', + 'wsSettings': wsObject + }, **secureFunc(streamInfo['secure'])} + def xrayStreamConfig(streamInfo: dict) -> dict: # 生成xray传输方式配置 streamType = streamInfo['type'] if streamType == 'tcp': @@ -35,7 +52,7 @@ def xrayStreamConfig(streamInfo: dict) -> dict: # 生成xray传输方式配置 elif streamType == 'kcp': return V2ray.kcpConfig(streamInfo, __secureConfig) elif streamType == 'ws': - return V2ray.wsConfig(streamInfo, True, __secureConfig) + return wsConfig(streamInfo, __secureConfig) elif streamType == 'h2': return V2ray.h2Config(streamInfo, __secureConfig) elif streamType == 'quic': diff --git a/ProxyFilter/V2ray.py b/ProxyFilter/V2ray.py index 61d06e4..724a499 100644 --- a/ProxyFilter/V2ray.py +++ b/ProxyFilter/V2ray.py @@ -187,6 +187,14 @@ v2rayStreamRules = { 'type': str, 'format': baseFunc.toStr }, + 'mode': { + 'optional': False, + 'default': 'gun', + 'type': str, + 'format': baseFunc.toStrTidy, + 'filter': lambda mode: mode in ['gun', 'multi'], + 'errMsg': 'Unknown gRPC mode' + }, 'secure': { 'optional': False, 'default': None, diff --git a/ProxyTester/Trojan.py b/ProxyTester/Trojan.py index 133c34c..bc7b185 100644 --- a/ProxyTester/Trojan.py +++ b/ProxyTester/Trojan.py @@ -140,4 +140,9 @@ def trojanTest(trojanConfig: dict) -> list: streamInfo = Xray.addTlsConfig(streamInfo, config['cert'], config['key'], config['host']) result.append(loadTrojanStream(streamInfo, None)) + streamInfo = Xray.loadGrpcStream(config['service'], multiMode = True) + result.append(loadTrojanStream(streamInfo, None)) + streamInfo = Xray.addTlsConfig(streamInfo, config['cert'], config['key'], config['host']) + result.append(loadTrojanStream(streamInfo, None)) + return result diff --git a/ProxyTester/V2ray.py b/ProxyTester/V2ray.py index 6ef445b..8592818 100644 --- a/ProxyTester/V2ray.py +++ b/ProxyTester/V2ray.py @@ -24,13 +24,13 @@ httpHeader = { } kcpSetting = { - "mtu": 1350, - "tti": 20, - "uplinkCapacity": 5, - "downlinkCapacity": 20, - "congestion": False, - "readBufferSize": 1, - "writeBufferSize": 1, + 'mtu': 1350, + 'tti': 20, + 'uplinkCapacity': 5, + 'downlinkCapacity': 20, + 'congestion': False, + 'readBufferSize': 1, + 'writeBufferSize': 1, } udpObfsList = [ @@ -165,26 +165,42 @@ def loadQuicStream(method: str, passwd: str, obfs: str) -> dict: 'server': { 'network': 'quic', 'quicSettings': { - "security": method, - "key": passwd, - "header": { - "type": obfs + 'security': method, + 'key': passwd, + 'header': { + 'type': obfs } } } } -def loadGrpcStream(service: str) -> dict: +def loadGrpcStream(service: str, multiMode: bool = False) -> dict: + if not multiMode: + return { + 'caption': 'gRPC', + 'client': { + 'type': 'grpc', + 'service': service + }, + 'server': { + 'network': 'grpc', + 'grpcSettings': { + 'serviceName': service + } + } + } return { - 'caption': 'gRPC', + 'caption': 'gRPC multi-mode', 'client': { 'type': 'grpc', - 'service': service + 'service': service, + 'mode': 'multi' }, 'server': { 'network': 'grpc', 'grpcSettings': { - "serviceName": service + 'serviceName': service, + 'multiMode': True # gRPC multi-mode not work in v2fly-core } } } diff --git a/ProxyTester/VLESS.py b/ProxyTester/VLESS.py index 6ccb6ed..5f79249 100644 --- a/ProxyTester/VLESS.py +++ b/ProxyTester/VLESS.py @@ -101,4 +101,9 @@ def vlessTest(vlessConfig: dict) -> list: streamInfo = Xray.addTlsConfig(streamInfo, config['cert'], config['key'], config['host']) result.append(loadVlessStream(streamInfo, None)) + streamInfo = Xray.loadGrpcStream(config['service'], multiMode = True) + result.append(loadVlessStream(streamInfo, None)) + streamInfo = Xray.addTlsConfig(streamInfo, config['cert'], config['key'], config['host']) + result.append(loadVlessStream(streamInfo, None)) + return result diff --git a/Run.py b/Run.py index 108e1ab..dbfc892 100644 --- a/Run.py +++ b/Run.py @@ -37,7 +37,7 @@ def __getCheckInfo() -> tuple[str or None, dict or None]: key = checkList[0] # 选取首个任务 taskContent = redisObject.get(key) # 获取任务信息 redisObject.delete(key) # 删除任务记录 - tag = str(key[len(redisPrefix) + 8:], encoding = "utf-8") # {prefix}check-x-{tag} + tag = str(key[len(redisPrefix) + 8:], encoding = 'utf-8') # {prefix}check-x-{tag} except: return None, None try: diff --git a/docs/ProxyObject.md b/docs/ProxyObject.md index 719c625..0f47e81 100644 --- a/docs/ProxyObject.md +++ b/docs/ProxyObject.md @@ -424,6 +424,7 @@ { 'type': 'grpc', 'service': ..., + 'mode': ..., 'secure': ... } ``` @@ -436,6 +437,14 @@ + 可选值:不限 + 建议值:英文大小写字母、数字、下划线及英文句号组成 +**mode** + ++ 类型:*str* ++ 说明:gRPC传输模式 ++ 缺省:'gun' ++ 可选值:`gun`,`multi` ++ 建议值:'multi' + **secure** + 类型:*None* / *secureObject* @@ -738,6 +747,7 @@ { 'type': 'grpc', 'service': ..., + 'mode': ..., 'secure': ... } ``` @@ -750,6 +760,14 @@ + 可选值:不限 + 建议值:英文大小写字母、数字、下划线及英文句号组成 +**mode** + ++ 类型:*str* ++ 说明:gRPC传输模式 ++ 缺省:'gun' ++ 可选值:`gun`,`multi` ++ 建议值:'multi' + **secure** + 类型:*None* / *tlsObject* @@ -814,7 +832,7 @@ + 类型:*bool* + 说明:是否验证服务端证书 + 缺省:True -+ 可选值:True / False ++ 可选值:不限 + 建议值:True ### xtlsObject @@ -1096,6 +1114,7 @@ { 'type': 'grpc', 'service': ..., + 'mode': ..., 'secure': ... } ``` @@ -1108,6 +1127,14 @@ + 可选值:不限 + 建议值:英文大小写字母、数字、下划线及英文句号组成 +**mode** + ++ 类型:*str* ++ 说明:gRPC传输模式 ++ 缺省:'gun' ++ 可选值:`gun`,`multi` ++ 建议值:'multi' + **secure** + 类型:*None* / *tlsObject* @@ -1172,7 +1199,7 @@ + 类型:*bool* + 说明:是否验证服务端证书 + 缺省:True -+ 可选值:True / False ++ 可选值:不限 + 建议值:True ### xtlsObject