diff --git a/Basis/Api.py b/Basis/Api.py index 9cc84d9..506c5c3 100644 --- a/Basis/Api.py +++ b/Basis/Api.py @@ -15,17 +15,20 @@ webApi = Flask(__name__) # init flask server def formatProxy(raw: str or dict) -> dict: - from ProxyFilter import filte + from Filter import Filter from ProxyDecoder import decode if type(raw) == str: raw = decode(raw) if raw is None: raise RuntimeError('decode error') - print(raw) - status, raw = filte(raw, isExtra = True) - if not status: + try: + return { + 'type': raw['type'], + 'name': raw['info']['remark'] if 'remark' in raw['info'] else '', + 'info': Filter(raw['type'], raw['info']) + } + except: raise RuntimeError('filter error') - return raw def jsonResponse(data: dict) -> Response: # return json mime diff --git a/ProxyFilter/Brook.py b/ProxyFilter/Brook.py deleted file mode 100644 index 5ba774a..0000000 --- a/ProxyFilter/Brook.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter import baseFunc - -brookFilterRules = { - 'rootObject': { - 'remark': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'server': { - 'optional': True, - 'type': str, - 'format': baseFunc.toHost, - 'filter': baseFunc.isHost, - 'errMsg': 'Illegal server address' - }, - 'port': { - 'optional': True, - 'type': int, - 'format': baseFunc.toInt, - 'filter': baseFunc.isPort, - 'errMsg': 'Illegal port number' - }, - 'passwd': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'ws': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': 'wsObject' - } - }, - 'wsObject': { - 'host': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'path': { - 'optional': False, - 'default': '/', - 'type': str, - 'format': baseFunc.toStr - }, - 'secure': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': 'secureObject' - } - }, - 'secureObject': { - 'verify': { - 'optional': False, - 'default': True, - 'type': bool, - 'format': baseFunc.toBool - } - } -} - -def filte(rawInfo: dict, isExtra: bool) -> tuple[bool, str or dict]: - """ - Brook节点合法性检查 - - 不合法: - return False, {reason} - - 合法: - return True, { - 'type': 'brook', - ... - } - """ - try: - if not isExtra: # 去除非必要参数 - brookFilterRules['rootObject'].pop('remark') - status, result = baseFunc.ruleFilter(rawInfo, brookFilterRules, {}) - if not status: # 节点格式错误 - return False, result - if result['ws'] is not None and result['ws']['host'] == '': - result['ws']['host'] = result['server'] - return True, result - except: - return False, 'Unknown error' diff --git a/ProxyFilter/Hysteria.py b/ProxyFilter/Hysteria.py deleted file mode 100644 index 5498f5b..0000000 --- a/ProxyFilter/Hysteria.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter import baseFunc - -hysteriaFilterRules = { - 'rootObject': { - 'remark': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'server': { - 'optional': True, - 'type': str, - 'format': baseFunc.toHost, - 'filter': baseFunc.isHost, - 'errMsg': 'Illegal server address' - }, - 'port': { - 'optional': True, - 'type': int, - 'format': baseFunc.toInt, - 'filter': baseFunc.isPort, - 'errMsg': 'Illegal port number' - }, - 'protocol': { - 'optional': False, - 'default': 'udp', - 'type': str, - 'format': baseFunc.toStr, - 'filter': lambda protocol: protocol in ['udp', 'wechat-video', 'faketcp'], - 'errMsg': 'Unknown Hysteria protocol' - }, - 'obfs': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'auth': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'sni': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'alpn': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'verify': { - 'optional': False, - 'default': True, - 'type': bool, - 'format': baseFunc.toBool - } - } -} - -def filte(rawInfo: dict, isExtra: bool) -> tuple[bool, str or dict]: - """ - Hysteria节点合法性检查 - - 不合法: - return False, {reason} - - 合法: - return True, { - 'type': 'hysteria', - ... - } - """ - try: - if not isExtra: # 去除非必要参数 - hysteriaFilterRules['rootObject'].pop('remark') - return baseFunc.ruleFilter(rawInfo, hysteriaFilterRules, {}) - except: - return False, 'Unknown error' diff --git a/ProxyFilter/Plugin.py b/ProxyFilter/Plugin.py deleted file mode 100644 index 41ca8cc..0000000 --- a/ProxyFilter/Plugin.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -pluginList = [ # 插件列表 - 'obfs-local', - 'simple-tls', - 'v2ray-plugin', - 'xray-plugin', - 'kcptun-client', - 'gost-plugin', - 'ck-client', - 'gq-client', - 'mtt-client', - 'rabbit-plugin', - 'qtun-client', - 'gun-plugin' -] - -pluginAlias = { # 插件别名 - 'obfs-local': [ - 'obfs', - 'obfs-plugin', - 'obfs-client', - 'obfs-server', - 'simple-obfs', - ], - 'simple-tls': [ - 'tls-local', - 'tls-client', - 'tls-server', - 'tls-plugin', - 'simple-tls-local', - 'simple-tls-client', - 'simple-tls-server', - 'simple-tls-plugin', - ], - 'v2ray-plugin': [ - 'v2ray', - 'v2ray-local', - 'v2ray-client', - 'v2ray-server', - ], - 'xray-plugin': [ - 'xray', - 'xray-local', - 'xray-client', - 'xray-server', - ], - 'kcptun-client': [ - 'kcptun', - 'kcptun-local', - 'kcptun-server', - 'kcptun-plugin', - ], - 'gost-plugin': [ - 'gost', - 'gost-local', - 'gost-client', - 'gost-server', - ], - 'ck-client': [ - 'ck', - 'ck-local', - 'ck-server', - 'ck-plugin', - 'cloak', - 'cloak-local', - 'cloak-client', - 'cloak-server', - 'cloak-plugin', - ], - 'gq-client': [ - 'gq', - 'gq-local', - 'gq-server', - 'gq-plugin', - 'goquiet', - 'goquiet-local', - 'goquiet-client', - 'goquiet-server', - 'goquiet-plugin', - ], - 'mtt-client': [ - 'mtt', - 'mtt-local', - 'mtt-server', - 'mtt-plugin', - 'mos-tls-tunnel', - 'mos-tls-tunnel-local', - 'mos-tls-tunnel-client', - 'mos-tls-tunnel-server', - 'mos-tls-tunnel-plugin', - ], - 'rabbit-plugin': [ - 'rabbit', - 'rabbit-tcp', - 'rabbit-local', - 'rabbit-client', - 'rabbit-server', - ], - 'qtun-client': [ - 'qtun', - 'qtun-local', - 'qtun-server', - 'qtun-plugin', - ], - 'gun-plugin': [ - 'gun', - 'gun-local', - 'gun-client', - 'gun-server', - ] -} - -def isPlugin(plugin: str) -> bool: # 插件是否合法 - return plugin in pluginList - -def pluginFormat(plugin: str) -> str: # 插件格式化 - plugin = plugin.replace('_', '-').lower().strip() - if plugin not in pluginList: # 非标插件名 - for pluginName in pluginAlias: - if plugin in pluginAlias[pluginName]: # 匹配别名列表 - return pluginName - return plugin # 匹配不到时返回原值 diff --git a/ProxyFilter/Shadowsocks.py b/ProxyFilter/Shadowsocks.py deleted file mode 100644 index 257f871..0000000 --- a/ProxyFilter/Shadowsocks.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter import Plugin -from ProxyFilter import baseFunc - -ssMethodList = [ # Shadowsocks加密方式 - 'aes-128-gcm', - 'aes-192-gcm', - 'aes-256-gcm', - 'aes-128-ctr', - 'aes-192-ctr', - 'aes-256-ctr', - 'aes-128-ocb', - 'aes-192-ocb', - 'aes-256-ocb', - 'aes-128-ofb', - 'aes-192-ofb', - 'aes-256-ofb', - 'aes-128-cfb', - 'aes-192-cfb', - 'aes-256-cfb', - 'aes-128-cfb1', - 'aes-192-cfb1', - 'aes-256-cfb1', - 'aes-128-cfb8', - 'aes-192-cfb8', - 'aes-256-cfb8', - 'aes-128-cfb128', - 'aes-192-cfb128', - 'aes-256-cfb128', - 'camellia-128-cfb', - 'camellia-192-cfb', - 'camellia-256-cfb', - 'camellia-128-cfb128', - 'camellia-192-cfb128', - 'camellia-256-cfb128', - 'plain', - 'none', - 'table', - 'rc4', - 'rc4-md5', - 'rc2-cfb', - 'bf-cfb', - 'cast5-cfb', - 'des-cfb', - 'idea-cfb', - 'seed-cfb', - 'salsa20', - 'salsa20-ctr', - 'xchacha20', - 'chacha20', - 'chacha20-ietf', - 'chacha20-poly1305', - 'chacha20-ietf-poly1305', - 'xchacha20-ietf-poly1305' -] - -ssFilterRules = { - 'rootObject': { - 'remark': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'server': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': baseFunc.isHost, - 'errMsg': 'Illegal server address' - }, - 'port': { - 'optional': True, - 'type': int, - 'format': baseFunc.toInt, - 'filter': baseFunc.isPort, - 'errMsg': 'Illegal port number' - }, - 'method': { - 'optional': True, - 'type': str, - 'format': lambda s: baseFunc.toStrTidy(s).replace('_', '-'), - 'filter': lambda method: method in ssMethodList, - 'errMsg': 'Unknown Shadowsocks method' - }, - 'passwd': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'plugin': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': 'pluginObject' - } - }, - 'pluginObject': { - 'type': { - 'optional': True, - 'type': str, - 'format': lambda pluginType: Plugin.pluginFormat(baseFunc.toStrTidy(pluginType)), - 'filter': Plugin.isPlugin, - 'errMsg': 'Unknown SIP003 plugin' - }, - 'param': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - } - } -} - -def ssFilter(rawInfo: dict, isExtra: bool) -> tuple[bool, str or dict]: - """ - Shadowsocks节点合法性检查 - - 不合法: - return False, {reason} - - 合法: - return True, { - 'type': 'ss', - ... - } - """ - try: - if not isExtra: # 去除非必要参数 - ssFilterRules['rootObject'].pop('remark') - return baseFunc.ruleFilter(rawInfo, ssFilterRules, {}) - except: - return False, 'Unknown error' diff --git a/ProxyFilter/ShadowsocksR.py b/ProxyFilter/ShadowsocksR.py deleted file mode 100644 index 4d598f5..0000000 --- a/ProxyFilter/ShadowsocksR.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter import baseFunc - -ssrMethodList = [ # ShadowsocksR加密方式 - 'aes-128-cfb', - 'aes-192-cfb', - 'aes-256-cfb', - 'aes-128-cfb1', - 'aes-192-cfb1', - 'aes-256-cfb1', - 'aes-128-cfb8', - 'aes-192-cfb8', - 'aes-256-cfb8', - 'aes-128-ctr', - 'aes-192-ctr', - 'aes-256-ctr', - 'aes-128-gcm', - 'aes-192-gcm', - 'aes-256-gcm', - 'aes-128-ofb', - 'aes-192-ofb', - 'aes-256-ofb', - 'camellia-128-cfb', - 'camellia-192-cfb', - 'camellia-256-cfb', - 'none', - 'table', - 'rc4', - 'rc4-md5', - 'rc4-md5-6', - 'bf-cfb', - 'cast5-cfb', - 'des-cfb', - 'idea-cfb', - 'seed-cfb', - 'rc2-cfb', - 'salsa20', - 'xsalsa20', - 'chacha20', - 'xchacha20', - 'chacha20-ietf', -] - -ssrProtocolList = [ # ShadowsocksR协议 - 'origin', - 'verify_sha1', - 'verify_simple', - 'verify_deflate', - 'auth_simple', - 'auth_sha1', - 'auth_sha1_v2', - 'auth_sha1_v4', - 'auth_aes128', - 'auth_aes128_md5', - 'auth_aes128_sha1', - 'auth_chain_a', - 'auth_chain_b', - 'auth_chain_c', - 'auth_chain_d', - 'auth_chain_e', - 'auth_chain_f', -] - -ssrObfsList = [ # ShadowsocksR混淆方式 - 'plain', - 'http_post', - 'http_simple', - 'tls_simple', - 'tls1.2_ticket_auth', - 'tls1.2_ticket_fastauth', - 'random_head', -] - -def __ssrProtocol(protocol) -> str: - protocol = baseFunc.toStrTidy(protocol).replace('-', '_') - if protocol == '': - return 'origin' - return protocol - -def __ssrObfs(obfs) -> str: - obfs = baseFunc.toStrTidy(obfs).replace('-', '_') - if obfs == '': - return 'plain' - return obfs - -ssrFilterRules = { - 'rootObject': { - 'remark': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'group': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'server': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': baseFunc.isHost, - 'errMsg': 'Illegal server address' - }, - 'port': { - 'optional': True, - 'type': int, - 'format': baseFunc.toInt, - 'filter': baseFunc.isPort, - 'errMsg': 'Illegal port number' - }, - 'method': { - 'optional': True, - 'type': str, - 'format': lambda s: baseFunc.toStrTidy(s).replace('_', '-'), - 'filter': lambda method: method in ssrMethodList, - 'errMsg': 'Unknown ShadowsocksR method' - }, - 'passwd': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'protocol': { - 'optional': False, - 'default': 'origin', - 'type': str, - 'format': __ssrProtocol, - 'filter': lambda protocol: protocol in ssrProtocolList, - 'errMsg': 'Unknown ShadowsocksR protocol' - }, - 'protocolParam': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'obfs': { - 'optional': False, - 'default': 'plain', - 'type': str, - 'format': __ssrObfs, - 'filter': lambda obfs: obfs in ssrObfsList, - 'errMsg': 'Unknown ShadowsocksR obfs' - }, - 'obfsParam': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - } - } -} - -def ssrFilter(rawInfo: dict, isExtra: bool) -> tuple[bool, str or dict]: - """ - ShadowsocksR节点合法性检查 - - 不合法: - return False, {reason} - - 合法: - return True, { - 'type': 'ssr', - ... - } - """ - try: - if not isExtra: # 去除非必要参数 - ssrFilterRules['rootObject'].pop('remark') - ssrFilterRules['rootObject'].pop('group') - status, result = baseFunc.ruleFilter(rawInfo, ssrFilterRules, {}) - if not status: # 节点格式错误 - return False, result - if result['protocol'] == 'origin': # origin无参数 - result['protocolParam'] = '' - if result['obfs'] == 'plain': # plain无参数 - result['obfsParam'] = '' - return True, result - except: - return False, 'Unknown error' diff --git a/ProxyFilter/Trojan.py b/ProxyFilter/Trojan.py deleted file mode 100644 index cc2e8a5..0000000 --- a/ProxyFilter/Trojan.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter import baseFunc -from ProxyFilter import Xray - -trojanFilterRules = { - 'rootObject': { - 'remark': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'server': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': baseFunc.isHost, - 'errMsg': 'Illegal server address' - }, - 'port': { - 'optional': True, - 'type': int, - 'format': baseFunc.toInt, - 'filter': baseFunc.isPort, - 'errMsg': 'Illegal port number' - }, - 'passwd': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'stream': { - 'optional': False, - 'default': { - 'type': 'tcp' - }, - 'type': [ - 'tcpObject', - 'kcpObject', - 'wsObject', - 'h2Object', - 'quicObject', - 'grpcObject', - ] - } - } -} - -def trojanFilter(rawInfo: dict, isExtra: bool) -> tuple[bool, str or dict]: - """ - Trojan节点合法性检查 - - 不合法: - return False, {reason} - - 合法: - return True, { - 'type': 'trojan', - ... - } - """ - try: - if not isExtra: # 去除非必要参数 - trojanFilterRules['rootObject'].pop('remark') - for key, obj in Xray.xrayStreamRules.items(): # xray.stream -> trojan - trojanFilterRules[key] = obj - status, result = baseFunc.ruleFilter(rawInfo, trojanFilterRules, {}) - if not status: # 节点格式错误 - return False, result - Xray.addSni(result) - return True, result - except: - return False, 'Unknown error' diff --git a/ProxyFilter/TrojanGo.py b/ProxyFilter/TrojanGo.py deleted file mode 100644 index de0b532..0000000 --- a/ProxyFilter/TrojanGo.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter import baseFunc -from ProxyFilter import Plugin - -trojanGoFilterRules = { - 'rootObject': { - 'remark': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'server': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': baseFunc.isHost, - 'errMsg': 'Illegal server address' - }, - 'port': { - 'optional': True, - 'type': int, - 'format': baseFunc.toInt, - 'filter': baseFunc.isPort, - 'errMsg': 'Illegal port number' - }, - 'passwd': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'sni': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'alpn': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': lambda alpn: alpn in ['h2', 'http/1.1', 'h2,http/1.1'], - 'errMsg': 'Illegal alpn option' - }, - 'verify': { - 'optional': False, - 'default': True, - 'type': bool, - 'format': baseFunc.toBool - }, - 'ws': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': 'wsObject' - }, - 'ss': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': 'ssObject' - }, - 'plugin': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': 'pluginObject' - } - }, - 'ssObject': { - 'method': { - 'optional': False, - 'default': 'AES-128-GCM', - 'type': str, - 'format': lambda s: baseFunc.toStrTidy(s).replace('_', '-').upper(), - 'filter': lambda method: method in ['AES-128-GCM', 'AES-256-GCM', 'CHACHA20-IETF-POLY1305'], - 'errMsg': 'Unknown Shadowsocks method' - }, - 'passwd': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStr - }, - }, - 'wsObject': { - 'host': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'path': { - 'optional': False, - 'default': '/', - 'type': str, - 'format': baseFunc.toStr - } - }, - 'pluginObject': { - 'type': { - 'optional': True, - 'type': str, - 'format': lambda pluginType: Plugin.pluginFormat(baseFunc.toStrTidy(pluginType)), - 'filter': Plugin.isPlugin, - 'errMsg': 'Unknown SIP003 plugin' - }, - 'param': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - } - } -} - -def trojanGoFilter(rawInfo: dict, isExtra: bool) -> tuple[bool, str or dict]: - """ - Trojan-Go节点合法性检查 - - 不合法: - return False, {reason} - - 合法: - return True, { - 'type': 'trojan-go', - ... - } - """ - try: - if not isExtra: # 去除非必要参数 - trojanGoFilterRules['rootObject'].pop('remark') - return baseFunc.ruleFilter(rawInfo, trojanGoFilterRules, {}) - except: - return False, 'Unknown error' diff --git a/ProxyFilter/V2ray.py b/ProxyFilter/V2ray.py deleted file mode 100644 index 2cc1b13..0000000 --- a/ProxyFilter/V2ray.py +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter import baseFunc - -udpObfsList = [ - 'none', - 'srtp', - 'utp', - 'wechat-video', - 'dtls', - 'wireguard' -] - -quicMethodList = [ - 'none', - 'aes-128-gcm', - 'chacha20-poly1305', -] - -v2rayStreamRules = { - 'tcpObject': { - 'type': { - 'optional': True, - 'type': str, - 'indexKey': True, - 'format': baseFunc.toStrTidy, - 'filter': lambda streamType: streamType == 'tcp', - 'errMsg': 'Unexpected stream type' - }, - 'obfs': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': 'obfsObject' - }, - 'secure': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': 'secureObject' - } - }, - 'kcpObject': { - 'type': { - 'optional': True, - 'type': str, - 'indexKey': True, - 'format': baseFunc.toStrTidy, - 'filter': lambda streamType: streamType == 'kcp', - 'errMsg': 'Unexpected stream type' - }, - 'seed': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'obfs': { - 'optional': False, - 'default': 'none', - 'type': str, - 'format': lambda s: baseFunc.toStrTidy(s).replace('_', '-'), - 'filter': lambda obfs: obfs in udpObfsList, - 'errMsg': 'Unknown mKCP obfs method' - }, - 'secure': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': 'secureObject' - } - }, - 'wsObject': { - 'type': { - 'optional': True, - 'type': str, - 'indexKey': True, - 'format': baseFunc.toStrTidy, - 'filter': lambda streamType: streamType == 'ws', - 'errMsg': 'Unexpected stream type' - }, - 'host': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'path': { - 'optional': False, - 'default': '/', - 'type': str, - 'format': baseFunc.toStr - }, - 'ed': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': int, - 'format': baseFunc.toInt, - 'filter': lambda ed: ed > 0, - 'errMsg': 'Illegal Max-Early-Data length' - }, - 'secure': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': 'secureObject' - } - }, - 'h2Object': { - 'type': { - 'optional': True, - 'type': str, - 'indexKey': True, - 'format': baseFunc.toStrTidy, - 'filter': lambda streamType: streamType == 'h2', - 'errMsg': 'Unexpected stream type' - }, - 'host': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'path': { - 'optional': False, - 'default': '/', - 'type': str, - 'format': baseFunc.toStr - }, - 'secure': { - 'optional': False, - 'default': {}, - 'type': 'secureObject' - } - }, - 'quicObject': { - 'type': { - 'optional': True, - 'type': str, - 'indexKey': True, - 'format': baseFunc.toStrTidy, - 'filter': lambda streamType: streamType == 'quic', - 'errMsg': 'Unexpected stream type' - }, - 'method': { - 'optional': False, - 'default': 'none', - 'type': str, - 'format': lambda s: baseFunc.toStrTidy(s).replace('_', '-'), - 'filter': lambda method: method in quicMethodList, - 'errMsg': 'Unknown QUIC method' - }, - 'passwd': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'obfs': { - 'optional': False, - 'default': 'none', - 'type': str, - 'format': lambda s: baseFunc.toStrTidy(s).replace('_', '-'), - 'filter': lambda obfs: obfs in udpObfsList, - 'errMsg': 'Unknown QUIC obfs method' - }, - 'secure': { - 'optional': False, - 'default': {}, - 'type': 'secureObject' - } - }, - 'grpcObject': { - 'type': { - 'optional': True, - 'type': str, - 'indexKey': True, - 'format': baseFunc.toStrTidy, - 'filter': lambda streamType: streamType == 'grpc', - 'errMsg': 'Unexpected stream type' - }, - 'service': { - 'optional': True, - '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, - 'allowNone': True, - 'type': 'secureObject' - } - }, - 'obfsObject': { - 'host': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'path': { - 'optional': False, - 'default': '/', - 'type': str, - 'format': baseFunc.toStr - } - }, - 'secureObject': { - 'sni': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'alpn': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': lambda alpn: alpn in ['h2', 'http/1.1', 'h2,http/1.1'], - 'errMsg': 'Illegal alpn option' - }, - 'verify': { - 'optional': False, - 'default': True, - 'type': bool, - 'format': baseFunc.toBool - } - } -} - -def addSni(info: dict) -> None: - stream = info['stream'] - if stream['secure'] is None or stream['secure']['sni'] != '': # 未指定SNI - return - if baseFunc.isDomain(info['server']): - stream['secure']['sni'] = info['server'] - - sniContent = '' - if stream['type'] == 'tcp' and stream['obfs'] is not None: - sniContent = stream['obfs']['host'].split(',')[0] - elif stream['type'] == 'ws': - sniContent = stream['host'] - elif stream['type'] == 'h2': - sniContent = stream['host'].split(',')[0] - - if sniContent != '': - stream['secure']['sni'] = sniContent diff --git a/ProxyFilter/VLESS.py b/ProxyFilter/VLESS.py deleted file mode 100644 index 1a87779..0000000 --- a/ProxyFilter/VLESS.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter import baseFunc -from ProxyFilter import Xray - -vlessMethodList = ['none'] - -vlessFilterRules = { - 'rootObject': { - 'remark': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'server': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': baseFunc.isHost, - 'errMsg': 'Illegal server address' - }, - 'port': { - 'optional': True, - 'type': int, - 'format': baseFunc.toInt, - 'filter': baseFunc.isPort, - 'errMsg': 'Illegal port number' - }, - 'method': { - 'optional': False, - 'default': 'none', - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': lambda method: method in vlessMethodList, - 'errMsg': 'Unknown VLESS method' - }, - 'id': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'stream': { - 'optional': False, - 'default': { - 'type': 'tcp' - }, - 'type': [ - 'tcpObject', - 'kcpObject', - 'wsObject', - 'h2Object', - 'quicObject', - 'grpcObject', - ] - } - } -} - -def vlessFilter(rawInfo: dict, isExtra: bool) -> tuple[bool, str or dict]: - """ - VLESS节点合法性检查 - - 不合法: - return False, {reason} - - 合法: - return True, { - 'type': 'vless', - ... - } - """ - try: - if not isExtra: # 去除非必要参数 - vlessFilterRules['rootObject'].pop('remark') - for key, obj in Xray.xrayStreamRules.items(): # xray.stream -> vless - vlessFilterRules[key] = obj - status, result = baseFunc.ruleFilter(rawInfo, vlessFilterRules, {}) - if not status: # 节点格式错误 - return False, result - Xray.addSni(result) - return True, result - except: - return False, 'Unknown error' diff --git a/ProxyFilter/VMess.py b/ProxyFilter/VMess.py deleted file mode 100644 index 3cb8dfd..0000000 --- a/ProxyFilter/VMess.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter import baseFunc -from ProxyFilter import V2ray - -vmessMethodList = [ - 'aes-128-gcm', - 'chacha20-poly1305', - 'auto', - 'none', - 'zero', -] - -vmessFilterRules = { - 'rootObject': { - 'remark': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'server': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': baseFunc.isHost, - 'errMsg': 'Illegal server address' - }, - 'port': { - 'optional': True, - 'type': int, - 'format': baseFunc.toInt, - 'filter': baseFunc.isPort, - 'errMsg': 'Illegal port number' - }, - 'method': { - 'optional': False, - 'default': 'auto', - 'type': str, - 'format': lambda s: baseFunc.toStrTidy(s).replace('_', '-'), - 'filter': lambda method: method in vmessMethodList, - 'errMsg': 'Unknown VMess method' - }, - 'id': { - 'optional': True, - 'type': str, - 'format': baseFunc.toStr - }, - 'aid': { - 'optional': False, - 'default': 0, - 'type': int, - 'format': baseFunc.toInt, - 'filter': lambda aid: aid in range(0, 65536), # 0 ~ 65535 - 'errMsg': 'Illegal alter Id' - }, - 'stream': { - 'optional': False, - 'default': { - 'type': 'tcp' - }, - 'type': [ - 'tcpObject', - 'kcpObject', - 'wsObject', - 'h2Object', - 'quicObject', - 'grpcObject', - ] - } - } -} - -def vmessFilter(rawInfo: dict, isExtra: bool) -> tuple[bool, str or dict]: - """ - VMess节点合法性检查 - - 不合法: - return False, {reason} - - 合法: - return True, { - 'type': 'vmess', - ... - } - """ - try: - if not isExtra: # 去除非必要参数 - vmessFilterRules['rootObject'].pop('remark') - for key, obj in V2ray.v2rayStreamRules.items(): # v2ray.stream -> vmess - vmessFilterRules[key] = obj - status, result = baseFunc.ruleFilter(rawInfo, vmessFilterRules, {}) - if not status: # 节点格式错误 - return False, result - V2ray.addSni(result) - return True, result - except: - return False, 'Unknown error' diff --git a/ProxyFilter/Xray.py b/ProxyFilter/Xray.py deleted file mode 100644 index a9f8e6d..0000000 --- a/ProxyFilter/Xray.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -import copy - -from ProxyFilter import baseFunc -from ProxyFilter import V2ray - -xrayFlowList = [ - 'xtls-origin', - 'xtls-direct', - 'xtls-splice', -] - -xrayStreamRules = copy.deepcopy(V2ray.v2rayStreamRules) -xrayStreamRules.pop('secureObject') - -xrayStreamRules['tcpObject']['secure']['type'] = ['tlsObject', 'xtlsObject'] -xrayStreamRules['kcpObject']['secure']['type'] = ['tlsObject', 'xtlsObject'] -xrayStreamRules['wsObject']['secure']['type'] = 'tlsObject' -xrayStreamRules['h2Object']['secure']['type'] = 'tlsObject' -xrayStreamRules['quicObject']['secure']['type'] = 'tlsObject' -xrayStreamRules['grpcObject']['secure']['type'] = 'tlsObject' - -xrayStreamRules['tcpObject']['secure']['default'] = {'type': 'tls'} -xrayStreamRules['kcpObject']['secure']['default'] = {'type': 'tls'} -xrayStreamRules['wsObject']['secure']['default'] = {'type': 'tls'} -xrayStreamRules['h2Object']['secure']['default'] = {'type': 'tls'} -xrayStreamRules['quicObject']['secure']['default'] = {'type': 'tls'} -xrayStreamRules['grpcObject']['secure']['default'] = {'type': 'tls'} - -xrayStreamRules['tlsObject'] = { - 'type': { - 'optional': True, - 'type': str, - 'indexKey': True, - 'format': baseFunc.toStrTidy, - 'filter': lambda secureType: secureType == 'tls', - 'errMsg': 'Unexpected secure type' - }, - 'sni': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'alpn': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': lambda alpn: alpn in ['h2', 'http/1.1', 'h2,http/1.1'], - 'errMsg': 'Illegal alpn option' - }, - 'verify': { - 'optional': False, - 'default': True, - 'type': bool, - 'format': baseFunc.toBool - } -} - -xrayStreamRules['xtlsObject'] = { - 'type': { - 'optional': True, - 'type': str, - 'indexKey': True, - 'format': baseFunc.toStrTidy, - 'filter': lambda secureType: secureType == 'xtls', - 'errMsg': 'Unexpected secure type' - }, - 'sni': { - 'optional': False, - 'default': '', - 'type': str, - 'format': baseFunc.toStr - }, - 'alpn': { - 'optional': False, - 'default': None, - 'allowNone': True, - 'type': str, - 'format': baseFunc.toStrTidy, - 'filter': lambda alpn: alpn in ['h2', 'http/1.1', 'h2,http/1.1'], - 'errMsg': 'Illegal alpn option' - }, - 'verify': { - 'optional': False, - 'default': True, - 'type': bool, - 'format': baseFunc.toBool - }, - 'flow': { - 'optional': False, - 'default': 'xtls-direct', - 'type': str, - 'format': lambda s: baseFunc.toStrTidy(s).replace('_', '-'), - 'filter': lambda flow: flow in xrayFlowList, - 'errMsg': 'Unknown XTLS flow method' - }, - 'udp443': { - 'optional': False, - 'default': False, - 'type': bool, - 'format': baseFunc.toBool - } -} - -addSni = V2ray.addSni diff --git a/ProxyFilter/__init__.py b/ProxyFilter/__init__.py deleted file mode 100644 index 7198490..0000000 --- a/ProxyFilter/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter.filter import * - -__all__ = ['filte'] diff --git a/ProxyFilter/baseFunc.py b/ProxyFilter/baseFunc.py deleted file mode 100644 index 65a00c9..0000000 --- a/ProxyFilter/baseFunc.py +++ /dev/null @@ -1,301 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -import re -import IPy -import copy - -def isIpAddr(content: str) -> bool: - """ - 判断是否为IP地址(IPv4 / IPv6) - - 域名: return True - - 非域名: return False - - """ - try: - if content.find('/') != -1: # filter CIDR - return False - if content.find('.') == -1 and content.find(':') == -1: - return False - IPy.IP(content) - return True # IP地址合法 - except: - return False - - -def isDomain(content: str) -> bool: - """ - 判断是否为域名 - - 域名: return True - - 非域名: return False - - """ - try: - return re.search( # 域名匹配 - r'^(?=^.{3,255}$)[a-zA-Z0-9_][a-zA-Z0-9_-]{0,62}(\.[a-zA-Z0-9_][a-zA-Z0-9_-]{0,62})+$', content - ) is not None - except: # 异常错误 - return False - - -def isHost(host: str) -> bool: - """ - 判断host是否合法 - - IPv4 / IPv6 / Domain - - 合法: return True - - 不合法: return False - - """ - if isIpAddr(host) or isDomain(host): - return True - return False - - -def isPort(port: int) -> bool: - """ - 判断端口是否合法 - - 1 ~ 65535 - - 合法: return True - - 不合法: return False - - """ - try: - if 1 <= port <= 65535: # 1 ~ 65535 - return True - except: # illegal - pass - return False - - -def toInt(raw) -> int: # change to int - if isinstance(raw, (int, float)): # int / float -> int - return int(raw) - elif isinstance(raw, bytes): # bytes -> str - raw = str(raw, encoding = 'utf-8') - elif not isinstance(raw, str): - raise Exception('type not allowed') - try: - return int(raw) - except: - raise Exception('not a integer') - - -def toStr(raw) -> str: # change to str - if raw is None: - return '' - elif isinstance(raw, str): - return raw - elif isinstance(raw, bytes): - return str(raw, encoding = 'utf-8') - else: - raise Exception('type not allowed') - - -def toBool(raw) -> bool: # change to bool - if isinstance(raw, bool): - return raw - if isinstance(raw, int): - raw = str(raw) - elif isinstance(raw, bytes): - raw = str(raw, encoding = 'utf-8') - elif not isinstance(raw, str): - raise Exception('type not allowed') - raw = raw.strip().lower() - if raw == 'true': - return True - elif raw == 'false': - return False - else: - try: - raw = int(raw) - return raw != 0 - except: - raise Exception('not a boolean') - - -def toStrTidy(raw) -> str: # change to str with trim and lower - return toStr(raw).strip().lower() - - -def toHost(raw) -> str: # format to IP address or domain - raw = toStrTidy(raw) - if raw[:1] == '[' and raw[-1:] == ']': # [IPv6] - raw = raw[1:-1] - return raw - - -class filterException(Exception): # 检测异常 - def __init__(self, reason): - self.reason = reason - - -def __dictCheck(data: dict, objectList: dict, limitRules: dict, keyPrefix: str) -> dict: # 递归检查dict - result = {} - for key, option in limitRules.items(): # 遍历规则 - keyName = key if keyPrefix == '' else keyPrefix + '.' + key - - # 检查必选key 补全可选key - if key not in data: - if option['optional']: # 必选 - raise filterException('Missing `' + keyName + '` option') # 必选值缺失 - else: # 可选 - data[key] = option['default'] # 补全可选值 - - allowNone = False - if 'allowNone' in option and option['allowNone']: # 允许为None - allowNone = True - - if not (data[key] is None and allowNone): # 忽略允许None且为None的情况 - if 'format' in option: # 预处理数据 - try: - data[key] = option['format'](data[key]) - except Exception as reason: - raise filterException('Illegal `' + keyName + '`: ' + str(reason)) # 格式化错误 - - # 检查value类型 - if data[key] is None: # 值为None - if not allowNone: # 不允许为None - raise filterException('Unexpected None in `' + keyName + '`') - result[key] = None - else: - dataValue = copy.deepcopy(data[key]) - if isinstance(option['type'], (str, list)) and not isinstance(dataValue, dict): # 子对象下必为dict - raise filterException('Illegal `' + keyName + '`: should be dictionary') - if isinstance(option['type'], str): # 单子对象 - result[key] = __dictCheck(dataValue, objectList, objectList[option['type']], keyName) # 检查子对象 - elif isinstance(option['type'], list): # 多子对象 - subResult = None - errMsg = None - for valueType in option['type']: # 遍历子Object - try: - subResult = __dictCheck(dataValue, objectList, objectList[valueType], keyName) # 尝试检查子对象 - except filterException as reason: - errMsg = str(reason) # 捕获抛出信息 - except Exception as reason: - if str(reason)[:10] == 'index-key:': # index-key匹配错误 - errMsg = str(reason)[10:] - continue - else: # 子对象匹配成功 - break - if subResult is None: # 无匹配子级 - if errMsg is not None: # 存在子级异常信息 - raise filterException(errMsg) - raise filterException('Error in `' + keyName + '` option') - result[key] = subResult - elif not isinstance(data[key], option['type']): # 类型不匹配 - raise filterException('Illegal `' + keyName + '` option') - else: # 检查无误 - result[key] = dataValue - - if result[key] is not None and 'filter' in option: # 值不为None且有检查函数 - errFlag = False - try: - if not option['filter'](result[key]): # 格式检查 - errFlag = True - except: - raise filterException('Filter error in `' + keyName + '`') - else: - if errFlag: - if 'indexKey' in option and option['indexKey']: - raise Exception('index-key:' + option['errMsg']) - raise filterException(option['errMsg']) - return result - - -def __ruleCheck(ruleSet: dict) -> None: # 规则集合法性检查 - if 'rootObject' not in ruleSet: # 根对象检查 - raise Exception('Miss root object') - for objName in ruleSet: # 遍历全部对象 - if objName[-6:] != 'Object': # 对象名必须以Object结尾 - raise Exception('Illegal object name `' + objName + '`') - for key, option in ruleSet[objName].items(): - keyName = '`' + objName + '.' + key + '`' - if 'optional' not in option or not isinstance(option['optional'], bool): # optional检查 - raise Exception('Illegal optional in ' + keyName) - if not option['optional'] and 'default' not in option: # optional为False时应有default - raise Exception('Miss default value in ' + keyName) - - allowNone = False - if 'allowNone' in option and not isinstance(option['allowNone'], bool): - raise Exception('Illegal allowNone in ' + keyName) - if 'allowNone' in option and option['allowNone']: - allowNone = True - - if 'type' not in option: # type值缺失 - raise Exception('Miss type in ' + keyName) - if not isinstance(option['type'], (type, str, list)): # type为变量类型 / str / list - raise Exception('Illegal type in ' + keyName) - if isinstance(option['type'], str) and option['type'] not in ruleSet: # 子Object未定义 - raise Exception('Object `' + option['type'] + '` not found in ' + keyName) - if isinstance(option['type'], list): - for subObjName in option['type']: - if not isinstance(subObjName, str): - raise Exception('Type list must be str in ' + keyName) - if subObjName not in ruleSet: # 子Object未定义 - raise Exception('Object `' + subObjName + '` not found in ' + keyName) - - if 'default' in option: - if option['default'] is None: # default值检查 - if not allowNone: - raise Exception(keyName + ' can\'t be None') - else: - if isinstance(option['type'], type): # type - if not isinstance(option['default'], option['type']): - raise Exception('Error default type in ' + keyName) - else: # str / list - if not isinstance(option['default'], dict): - raise Exception('Default type should be dict in ' + keyName) - - if 'format' in option and not callable(option['format']): # format必须为函数 - raise Exception('Format option must be a function in ' + keyName) - if isinstance(option['type'], type) and 'format' not in option: # 指定变量类型时需有format函数 - raise Exception('Miss format in ' + keyName) - - if 'filter' in option: - if 'errMsg' not in option: # filter与errMsg同时存在 - raise Exception('Miss errMsg option in ' + keyName) - if not callable(option['filter']): # filter必须为函数 - raise Exception('Filter option must be a function in ' + keyName) - if not isinstance(option['type'], type): - raise Exception('Overage filter option in ' + keyName) - if 'errMsg' in option and not isinstance(option['errMsg'], str): # errMsg必须为str - raise Exception('Error message must be str in ' + keyName) - - if 'indexKey' in option and not isinstance(option['indexKey'], bool): # indexKey必为bool - raise Exception('Illegal indexKey in ' + keyName) - - -def ruleFilter(rawData: dict, ruleSet: dict, header: dict) -> tuple[bool, dict or str]: - """ - 使用规则集检查原始数据 - - 原始数据错误: - return False, {reason} - - 原始数据无误: - return True, {dist} - """ - try: - __ruleCheck(ruleSet) # 检查规则集 - except Exception as reason: - return False, 'Filter rules -> ' + str(reason) # 规则集有误 - - data = copy.deepcopy(rawData) - try: - data = __dictCheck(data, ruleSet, ruleSet['rootObject'], '') # 开始检查 - except filterException as reason: # 节点格式错误 - return False, str(reason) - except: - return False, 'Format error' - else: - return True, {**header, **data} diff --git a/ProxyFilter/filter.py b/ProxyFilter/filter.py deleted file mode 100644 index c4713b0..0000000 --- a/ProxyFilter/filter.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- - -from ProxyFilter import Shadowsocks -from ProxyFilter import ShadowsocksR -from ProxyFilter import VMess -from ProxyFilter import VLESS -from ProxyFilter import Trojan -from ProxyFilter import TrojanGo -from ProxyFilter import Brook -from ProxyFilter import Hysteria - -def filte(raw: dict, isExtra: bool = False) -> tuple[bool, str or dict]: - """ - 代理信息过滤并格式化 - - 参数无效: - return False, {reason} - - 参数有效: - return True, { - 'type': '...', - '...': '...', - ... - } - """ - try: - if 'type' not in raw: - return False, 'Missing `type` option' - if raw['type'] == 'ss': - status, raw['info'] = Shadowsocks.ssFilter(raw['info'], isExtra) - elif raw['type'] == 'ssr': - status, raw['info'] = ShadowsocksR.ssrFilter(raw['info'], isExtra) - elif raw['type'] == 'vmess': - status, raw['info'] = VMess.vmessFilter(raw['info'], isExtra) - elif raw['type'] == 'vless': - status, raw['info'] = VLESS.vlessFilter(raw['info'], isExtra) - elif raw['type'] == 'trojan': - status, raw['info'] = Trojan.trojanFilter(raw['info'], isExtra) - elif raw['type'] == 'trojan-go': - status, raw['info'] = TrojanGo.trojanGoFilter(raw['info'], isExtra) - elif raw['type'] == 'brook': - status, raw['info'] = Brook.filte(raw['info'], isExtra) - elif raw['type'] == 'hysteria': - status, raw['info'] = Hysteria.filte(raw['info'], isExtra) - else: - return False, 'Unknown proxy type' - return status, raw - except: - pass - return False, 'Unknown error' diff --git a/demo.py b/demo.py deleted file mode 100755 index 07d6fa3..0000000 --- a/demo.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/env python - -from pprint import pprint -from Filter import Filter - -ssProxy = { - 'server': '1.1.1.1', - 'port': '12345', - 'method': 'none', - 'passwd': 'dnomd343', - 'plugin': { - 'type': 'obfs' - } -} - -ssrProxy = { - 'server': '1.1.1.1', - 'port': 12345, - 'method': 'table', - 'passwd': 'dnomd343', - 'protocol': 'auth_chain-a', - 'protocolParam': '123', - 'obfs': 'plain', - 'obfsParam': 'ok', -} - -vmessProxy = { - 'server': '1.1.1.1', - 'port': b'12345', - 'id': 'c8783403-64d5-4b6d-8cf4-bd3988d01b6c', - 'aid': '64', - 'stream': { - 'type': 'GRPC', - 'service': 'no-gfw', - 'mode': ' multi ', - 'secure': { - 'sni': '', - 'alpn': 'h2, http/1.1', - 'verify': 'False ' - } - } -} - -vlessProxy = { - 'server': '1.1.1.1', - 'port': r'12345', - 'method': 'NONE', - 'id': ' 3f163adf-5bdd-40d0-b0ec-e47f9bebcac7', - 'stream': { - 'type': 'grpc', - 'service': 'dnomd343', - # 'secure': None, - # 'secure': { - # 'type': 'tls', - # 'sni': '23333', - # 'alpn': 'h2', - # 'verify': 0 - # } - # 'secure': { - # 'type': 'xtls', - # 'sni': '23333', - # 'alpn': 'h2', - # 'verify': True, - # 'flow': 'xtls-rprx-direct', - # 'udp443': 0.1 - # } - } -} - -trojanProxy = { - 'server': 'www.dnomd343.top', - 'port': 12345, - 'passwd': b'dnomd343', - 'stream': { - # 'type': 'grpc', - 'type': 'h2', - # 'host': '343.re', - 'service': 'dnomd343', - # 'secure': None, - 'secure': { - 'type': 'tls', - 'sni': '', - 'alpn': 'h2', - 'verify': 0 - } - # 'secure': { - # 'type': 'xtls', - # 'sni': '23333', - # 'alpn': 'h2', - # 'verify': True, - # 'flow': 'xtls-rprx-direct', - # 'udp443': 0.1 - # } - } -} - -trojanGoProxy = { - 'server': '343.re', - 'port': 12345, - 'passwd': 'dnomd343', - 'sni': '', - 'alpn': ' h2', - 'verify': 'FALSE', - 'ws': { - 'host': 'dnomd343.top', - 'path': '/test', - }, - 'ss': { - 'method': 'chacha20-ietf-poly1305', - 'passwd': 'dnomd343', - }, - 'plugin': { - 'type': 'go-quiet', - 'param': 123 - } -} - -brookProxy = { - 'server': '1.1.1.1', - 'port': 12345, - 'passwd': 'dnomd343', - 'stream': { - 'type': 'ws', - 'host': '343.re', - 'path': '/test', - 'raw': True, - 'secure': { - 'verify': ' 0' - } - }, -} - -hysteriaProxy = { - 'server': 'www.343.re', - 'port': 12345, - 'protocol': 'faketcp', - 'obfs': '1234', - 'passwd': 'dnomd343', - 'up': 100, - 'down': 500, - 'sni': '', - 'alpn': 'h3', - 'verify': 'FALSE', -} - -# ret = Filter('ss', ssProxy) -# ret = Filter('ssr', ssrProxy) -# ret = Filter('vmess', vmessProxy) -# ret = Filter('vless', vlessProxy) -# ret = Filter('trojan', trojanProxy) -# ret = Filter('trojan-go', trojanGoProxy) -# ret = Filter('brook', brookProxy) -ret = Filter('hysteria', hysteriaProxy) -pprint(ret, sort_dicts = False)