diff --git a/ProxyFilter/Shadowsocks.py b/ProxyFilter/Shadowsocks.py index 3c36420..a258dc7 100644 --- a/ProxyFilter/Shadowsocks.py +++ b/ProxyFilter/Shadowsocks.py @@ -125,8 +125,8 @@ def ssFilter(raw): if raw['method'] in ssMethodList: result['method'] = raw['method'] else: - return False, 'Unknown shadowsocks method' - + return False, 'Unknown Shadowsocks method' + if (not 'plugin' in raw) or raw['plugin'] == '': result['plugin'] = '' result['pluginParam'] = '' diff --git a/ProxyFilter/ShadowsocksR.py b/ProxyFilter/ShadowsocksR.py new file mode 100644 index 0000000..15ab780 --- /dev/null +++ b/ProxyFilter/ShadowsocksR.py @@ -0,0 +1,159 @@ +#!/usr/bin/python +# -*- coding:utf-8 -*- + +from ProxyFilter import baseFunc + +ssrMethodList = [ + "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 = [ + "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 = [ + "plain", + "http_post", + "http_simple", + "tls_simple", + "tls1.2_ticket_auth", + "tls1.2_ticket_fastauth", + "random_head", +] + +def __ssrFormat(raw): # 容错性格式化 + try: + raw['server'] = raw['server'].strip() + raw['port'] = int(raw['port']) + raw['method'] = raw['method'].replace('_', '-').lower().strip() + if 'protocol' in raw: + raw['protocol'] = raw['protocol'].replace('-', '_').lower().strip() + if 'obfs' in raw: + raw['obfs'] = raw['obfs'].replace('-', '_').lower().strip() + except: + pass + return raw + + +def ssrFilter(raw): + ''' + ShadowsocksR节点合法性检查 + + 不合法: + return False, {reason} + + 合法: + return True, { + 'type': 'ssr', + 'server': '...', + 'port': ..., + 'password': '...', + 'method": '...', + 'protocol': '...', + 'protocolParam': '...', + 'obfs': '...', + 'obfsParam': '...' + } + ''' + try: + result = {} + result['type'] = 'ssr' + raw = __ssrFormat(raw) + + if not 'server' in raw: + return False, 'Missing `server` option' + if not 'port' in raw: + return False, 'Missing `port` option' + if not 'password' in raw: + return False, 'Missing `password` option' + if not 'method' in raw: + return False, 'Missing `method` option' + + if baseFunc.isHost(raw['server']): + result['server'] = raw['server'] + else: + return False, 'Illegal `server` option' + if baseFunc.isPort(raw['port']): + result['port'] = raw['port'] + else: + return False, 'Illegal `port` option' + result['password'] = raw['password'] + if raw['method'] in ssrMethodList: + result['method'] = raw['method'] + else: + return False, 'Unknown ShadowsocksR method' + + if (not 'protocol' in raw) or raw['protocol'] == 'origin' or raw['protocol'] == '': + result['protocol'] = 'origin' + result['protocolParam'] = '' + else: + if raw['protocol'] in ssrProtocolList: + result['protocol'] = raw['protocol'] + result['protocolParam'] = raw['protocolParam'] + else: + return False, 'Unknown ShadowsocksR protocol' + + if (not 'obfs' in raw) or raw['obfs'] == 'plain' or raw['obfs'] == '': + result['obfs'] = 'plain' + result['obfsParam'] = '' + else: + if raw['obfs'] in ssrObfsList: + result['obfs'] = raw['obfs'] + result['obfsParam'] = raw['obfsParam'] + else: + return False, 'Unknown ShadowsocksR obfs' + except: + return False, 'Unknown error' + return True, result diff --git a/ProxyFilter/baseFunc.py b/ProxyFilter/baseFunc.py index dc397ad..c337552 100644 --- a/ProxyFilter/baseFunc.py +++ b/ProxyFilter/baseFunc.py @@ -1,3 +1,6 @@ +#!/usr/bin/python +# -*- coding:utf-8 -*- + import re import IPy diff --git a/ProxyFilter/filter.py b/ProxyFilter/filter.py index de5a443..54f4817 100644 --- a/ProxyFilter/filter.py +++ b/ProxyFilter/filter.py @@ -2,6 +2,7 @@ # -*- coding:utf-8 -*- from ProxyFilter import Shadowsocks +from ProxyFilter import ShadowsocksR def filter(raw): ''' @@ -23,6 +24,8 @@ def filter(raw): return False, 'Missing `type` option' if raw['type'] == 'ss': return Shadowsocks.ssFilter(raw) + elif raw['type'] == 'ssr': + return ShadowsocksR.ssrFilter(raw) else: return False, 'Unknown proxy type' except: diff --git a/demo.py b/demo.py index 8232825..9d942d0 100644 --- a/demo.py +++ b/demo.py @@ -3,7 +3,7 @@ import ProxyFilter as Filter -info = { +ssInfo = { "type": "ss", "server": "127.0.0.1 ", "port": 12345, @@ -13,4 +13,16 @@ info = { "pluginParam": "obfs=http;host=www.bing.com" } -print(Filter.filter(info)) +ssrInfo = { + "type": "ssr", + "server": " 127.0.0.1", + "port": 23456, + "password": "dnomd343", + "method": "table", + "protocol": "auth-aes128_md5", + "protocolParam": "", + "obfs": "", + "obfsParam": "fafadfaf" +} + +print(Filter.filter(ssrInfo))