Browse Source

refactor: new ProxyFilter

master
Dnomd343 3 years ago
parent
commit
b462eb18bc
  1. 4
      ProxyFilter/Plugin.py
  2. 104
      ProxyFilter/Shadowsocks.py
  3. 222
      ProxyFilter/ShadowsocksR.py
  4. 2
      ProxyFilter/__init__.py
  5. 17
      ProxyFilter/baseFunc.py
  6. 9
      ProxyFilter/filter.py

4
ProxyFilter/Plugin.py

@ -114,8 +114,8 @@ pluginAlias = { # 插件别名
def pluginFormat(plugin): # 插件格式化 def pluginFormat(plugin): # 插件格式化
plugin = plugin.replace('_', '-').lower().strip() plugin = plugin.replace('_', '-').lower().strip()
if not plugin in pluginList: # 非标插件名 if plugin not in pluginList: # 非标插件名
for pluginName in pluginAlias: for pluginName in pluginAlias:
if plugin in pluginAlias[pluginName]: # 匹配别名列表 if plugin in pluginAlias[pluginName]: # 匹配别名列表
return pluginName return pluginName
return plugin return plugin # 匹配不到时返回原值

104
ProxyFilter/Shadowsocks.py

@ -1,10 +1,41 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
"""
{
'server': '...',
'port': ...,
'method': '...',
'passwd': '...',
'plugin': pluginObject
}
server (str) -> required
port (int or str) -> required
method (str) -> required
passwd (str) -> required
plugin (None or dict) -> optional
pluginObject: {
'type': '...',
'param': '...'
}
type (str) -> optional
param (str) -> optional
"""
from ProxyFilter import baseFunc from ProxyFilter import baseFunc
from ProxyFilter import Plugin as sip003 from ProxyFilter import Plugin as sip003
ssMethodList = [ ssMethodList = [ # Shadowsocks加密方式
'aes-128-gcm', 'aes-128-gcm',
'aes-192-gcm', 'aes-192-gcm',
'aes-256-gcm', 'aes-256-gcm',
@ -56,7 +87,7 @@ ssMethodList = [
'xchacha20-ietf-poly1305' 'xchacha20-ietf-poly1305'
] ]
pluginList = [ pluginList = [ # SIP003插件列表
'obfs-local', 'obfs-local',
'simple-tls', 'simple-tls',
'v2ray-plugin', 'v2ray-plugin',
@ -71,18 +102,32 @@ pluginList = [
'gun-plugin' 'gun-plugin'
] ]
def __ssFormat(raw): # 容错性格式化 def __ssFill(raw: dict) -> dict: # 补全可选值
try:
if 'plugin' not in raw:
raw['plugin'] = None
if raw['plugin'] is not None:
if 'type' not in raw['plugin']:
raw['plugin']['type'] = ''
if 'param' not in raw['plugin']:
raw['plugin']['param'] = ''
except:
pass
return raw
def __ssFormat(raw: dict) -> dict: # 容错性格式化
try: try:
raw['server'] = raw['server'].strip() raw['server'] = raw['server'].strip()
raw['port'] = int(raw['port']) raw['port'] = int(raw['port'])
raw['method'] = raw['method'].replace('_', '-').lower().strip() raw['method'] = raw['method'].replace('_', '-').lower().strip()
raw['plugin'] = sip003.pluginFormat(raw['plugin']) if raw['plugin'] is not None:
raw['plugin']['type'] = sip003.pluginFormat(raw['plugin']['type'])
except: except:
pass pass
return raw return raw
def ssFilter(raw): def ssFilter(raw: dict) -> tuple[bool, str or dict]:
''' """
Shadowsocks节点合法性检查 Shadowsocks节点合法性检查
不合法: 不合法:
@ -91,51 +136,46 @@ def ssFilter(raw):
合法: 合法:
return True, { return True, {
'type': 'ss', 'type': 'ss',
'server': '...', ...
'port': ...,
'password': '...',
'method": '...',
'plugin": '...',
'pluginParam": '...'
} }
''' """
try: try:
result = {} if 'server' not in raw: # 必选值检查
result['type'] = 'ss'
raw = __ssFormat(raw)
if not 'server' in raw:
return False, 'Missing `server` option' return False, 'Missing `server` option'
if not 'port' in raw: if 'port' not in raw:
return False, 'Missing `port` option' return False, 'Missing `port` option'
if not 'password' in raw: if 'method' not in raw:
return False, 'Missing `password` option'
if not 'method' in raw:
return False, 'Missing `method` option' return False, 'Missing `method` option'
if 'passwd' not in raw:
return False, 'Missing `passwd` option'
raw = __ssFormat(__ssFill(raw)) # 预处理
result = {'type': 'ss'}
if baseFunc.isHost(raw['server']): if baseFunc.isHost(raw['server']):
result['server'] = raw['server'] result['server'] = raw['server'] # server
else: else:
return False, 'Illegal `server` option' return False, 'Illegal `server` option'
if baseFunc.isPort(raw['port']): if baseFunc.isPort(raw['port']):
result['port'] = raw['port'] result['port'] = raw['port'] # port
else: else:
return False, 'Illegal `port` option' return False, 'Illegal `port` option'
result['password'] = raw['password']
if raw['method'] in ssMethodList: if raw['method'] in ssMethodList:
result['method'] = raw['method'] result['method'] = raw['method'] # method
else: else:
return False, 'Unknown Shadowsocks method' return False, 'Unknown Shadowsocks method'
result['passwd'] = raw['passwd'] # passwd
if (not 'plugin' in raw) or raw['plugin'] == '': if raw['plugin'] is None or raw['plugin']['type'] in [None, '']:
result['plugin'] = '' plugin = None
result['pluginParam'] = ''
else: else:
if raw['plugin'] in pluginList: if raw['plugin']['type'] in pluginList:
result['plugin'] = raw['plugin'] plugin = {
result['pluginParam'] = raw['pluginParam'] 'type': raw['plugin']['type'],
'param': raw['plugin']['param']
}
else: else:
return False, 'Unknown sip003 plugin' return False, 'Unknown sip003 plugin'
result['plugin'] = plugin
except: except:
return False, 'Unknown error' return False, 'Unknown error'
return True, result return True, result

222
ProxyFilter/ShadowsocksR.py

@ -1,94 +1,136 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
"""
{
'server': '...',
'port': ...,
'method': '...',
'passwd': '...',
'protocol': '...',
'protocolParam': '...',
'obfs': '...',
'obfsParam': '...'
}
server (str) -> required
port (int or str) -> required
method (str) -> required
passwd (str) -> required
protocol (str) -> optional
protocolParam (str) -> optional
obfs (str) -> optional
obfsParam (str) -> optional
"""
from ProxyFilter import baseFunc from ProxyFilter import baseFunc
ssrMethodList = [ ssrMethodList = [ # ShadowsocksR加密方式
"aes-128-cfb", 'aes-128-cfb',
"aes-192-cfb", 'aes-192-cfb',
"aes-256-cfb", 'aes-256-cfb',
"aes-128-cfb1", 'aes-128-cfb1',
"aes-192-cfb1", 'aes-192-cfb1',
"aes-256-cfb1", 'aes-256-cfb1',
"aes-128-cfb8", 'aes-128-cfb8',
"aes-192-cfb8", 'aes-192-cfb8',
"aes-256-cfb8", 'aes-256-cfb8',
"aes-128-ctr", 'aes-128-ctr',
"aes-192-ctr", 'aes-192-ctr',
"aes-256-ctr", 'aes-256-ctr',
"aes-128-gcm", 'aes-128-gcm',
"aes-192-gcm", 'aes-192-gcm',
"aes-256-gcm", 'aes-256-gcm',
"aes-128-ofb", 'aes-128-ofb',
"aes-192-ofb", 'aes-192-ofb',
"aes-256-ofb", 'aes-256-ofb',
"camellia-128-cfb", 'camellia-128-cfb',
"camellia-192-cfb", 'camellia-192-cfb',
"camellia-256-cfb", 'camellia-256-cfb',
"none", 'none',
"table", 'table',
"rc4", 'rc4',
"rc4-md5", 'rc4-md5',
"rc4-md5-6", 'rc4-md5-6',
"bf-cfb", 'bf-cfb',
"cast5-cfb", 'cast5-cfb',
"des-cfb", 'des-cfb',
"idea-cfb", 'idea-cfb',
"seed-cfb", 'seed-cfb',
"rc2-cfb", 'rc2-cfb',
"salsa20", 'salsa20',
"xsalsa20", 'xsalsa20',
"chacha20", 'chacha20',
"xchacha20", 'xchacha20',
"chacha20-ietf", 'chacha20-ietf',
] ]
ssrProtocolList = [ ssrProtocolList = [ # ShadowsocksR协议
"origin", 'origin',
"verify_sha1", 'verify_sha1',
"verify_simple", 'verify_simple',
"verify_deflate", 'verify_deflate',
"auth_simple", 'auth_simple',
"auth_sha1", 'auth_sha1',
"auth_sha1_v2", 'auth_sha1_v2',
"auth_sha1_v4", 'auth_sha1_v4',
"auth_aes128", 'auth_aes128',
"auth_aes128_md5", 'auth_aes128_md5',
"auth_aes128_sha1", 'auth_aes128_sha1',
"auth_chain_a", 'auth_chain_a',
"auth_chain_b", 'auth_chain_b',
"auth_chain_c", 'auth_chain_c',
"auth_chain_d", 'auth_chain_d',
"auth_chain_e", 'auth_chain_e',
"auth_chain_f", 'auth_chain_f',
] ]
ssrObfsList = [ ssrObfsList = [ # ShadowsocksR混淆方式
"plain", 'plain',
"http_post", 'http_post',
"http_simple", 'http_simple',
"tls_simple", 'tls_simple',
"tls1.2_ticket_auth", 'tls1.2_ticket_auth',
"tls1.2_ticket_fastauth", 'tls1.2_ticket_fastauth',
"random_head", 'random_head',
] ]
def __ssrFormat(raw): # 容错性格式化 def __ssrFill(raw: dict) -> dict: # 补全可选值
try:
if 'protocol' not in raw:
raw['protocol'] = ''
if 'protocolParam' not in raw:
raw['protocolParam'] = ''
if 'obfs' not in raw:
raw['obfs'] = ''
if 'obfsParam' not in raw:
raw['obfsParam'] = ''
except:
pass
return raw
def __ssrFormat(raw: dict) -> dict: # 容错性格式化
try: try:
raw['server'] = raw['server'].strip() raw['server'] = raw['server'].strip()
raw['port'] = int(raw['port']) raw['port'] = int(raw['port'])
raw['method'] = raw['method'].replace('_', '-').lower().strip() raw['method'] = raw['method'].replace('_', '-').lower().strip()
if 'protocol' in raw: raw['protocol'] = raw['protocol'].replace('-', '_').lower().strip()
raw['protocol'] = raw['protocol'].replace('-', '_').lower().strip() raw['obfs'] = raw['obfs'].replace('-', '_').lower().strip()
if 'obfs' in raw:
raw['obfs'] = raw['obfs'].replace('-', '_').lower().strip()
except: except:
pass pass
return raw return raw
def ssrFilter(raw): def ssrFilter(raw: dict) -> tuple[bool, str or dict]:
''' """
ShadowsocksR节点合法性检查 ShadowsocksR节点合法性检查
不合法: 不合法:
@ -97,45 +139,37 @@ def ssrFilter(raw):
合法: 合法:
return True, { return True, {
'type': 'ssr', 'type': 'ssr',
'server': '...', ...
'port': ...,
'password': '...',
'method": '...',
'protocol': '...',
'protocolParam': '...',
'obfs': '...',
'obfsParam': '...'
} }
''' """
try: try:
result = {}
result['type'] = 'ssr'
raw = __ssrFormat(raw)
if not 'server' in raw: if 'server' not in raw: # 必选值检查
return False, 'Missing `server` option' return False, 'Missing `server` option'
if not 'port' in raw: if 'port' not in raw:
return False, 'Missing `port` option' return False, 'Missing `port` option'
if not 'password' in raw: if 'method' not in raw:
return False, 'Missing `password` option'
if not 'method' in raw:
return False, 'Missing `method` option' return False, 'Missing `method` option'
if 'passwd' not in raw:
return False, 'Missing `password` option'
raw = __ssrFormat(__ssrFill(raw)) # 预处理
result = {'type': 'ssr'}
if baseFunc.isHost(raw['server']): if baseFunc.isHost(raw['server']):
result['server'] = raw['server'] result['server'] = raw['server'] # server
else: else:
return False, 'Illegal `server` option' return False, 'Illegal `server` option'
if baseFunc.isPort(raw['port']): if baseFunc.isPort(raw['port']):
result['port'] = raw['port'] result['port'] = raw['port'] # port
else: else:
return False, 'Illegal `port` option' return False, 'Illegal `port` option'
result['password'] = raw['password']
if raw['method'] in ssrMethodList: if raw['method'] in ssrMethodList:
result['method'] = raw['method'] result['method'] = raw['method'] # method
else: else:
return False, 'Unknown ShadowsocksR method' return False, 'Unknown ShadowsocksR method'
result['passwd'] = raw['passwd'] # passwd
if (not 'protocol' in raw) or raw['protocol'] == 'origin' or raw['protocol'] == '': if raw['protocol'] in [None, '', 'origin']: # 默认协议
result['protocol'] = 'origin' result['protocol'] = 'origin'
result['protocolParam'] = '' result['protocolParam'] = ''
else: else:
@ -145,7 +179,7 @@ def ssrFilter(raw):
else: else:
return False, 'Unknown ShadowsocksR protocol' return False, 'Unknown ShadowsocksR protocol'
if (not 'obfs' in raw) or raw['obfs'] == 'plain' or raw['obfs'] == '': if raw['obfs'] in [None, '', 'plain']: # 默认混淆
result['obfs'] = 'plain' result['obfs'] = 'plain'
result['obfsParam'] = '' result['obfsParam'] = ''
else: else:

2
ProxyFilter/__init__.py

@ -3,4 +3,4 @@
from ProxyFilter.filter import * from ProxyFilter.filter import *
__all__ = [ 'filter' ] __all__ = ['filte']

17
ProxyFilter/baseFunc.py

@ -5,7 +5,7 @@ import re
import IPy import IPy
def isHost(host: str) -> bool: def isHost(host: str) -> bool:
''' """
判断host是否合法 判断host是否合法
IPv4 / IPv6 / Domain IPv4 / IPv6 / Domain
@ -13,7 +13,7 @@ def isHost(host: str) -> bool:
合法: return True 合法: return True
不合法: return False 不合法: return False
''' """
try: try:
IPy.IP(host) IPy.IP(host)
if host.find('/') != -1: # filter CIDR if host.find('/') != -1: # filter CIDR
@ -21,10 +21,10 @@ def isHost(host: str) -> bool:
return True return True
except: # not IP address except: # not IP address
pass pass
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})+$', host) != None) 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})+$', host) is not None
def isPort(port) -> bool: def isPort(port: int) -> bool:
''' """
判断端口是否合法 判断端口是否合法
1 ~ 65535 1 ~ 65535
@ -32,11 +32,10 @@ def isPort(port) -> bool:
合法: return True 合法: return True
不合法: return False 不合法: return False
''' """
try: try:
if isinstance(port, (int, str)): if 1 <= port <= 65535:
if int(port) >= 1 and int(port) <= 65535: return True
return True
except: # illegal except: # illegal
pass pass
return False return False

9
ProxyFilter/filter.py

@ -4,8 +4,8 @@
from ProxyFilter import Shadowsocks from ProxyFilter import Shadowsocks
from ProxyFilter import ShadowsocksR from ProxyFilter import ShadowsocksR
def filter(raw): def filte(raw: dict) -> tuple[bool, str]:
''' """
代理信息过滤并格式化 代理信息过滤并格式化
参数无效: 参数无效:
@ -17,10 +17,9 @@ def filter(raw):
'...': '...', '...': '...',
... ...
} }
"""
'''
try: try:
if not 'type' in raw: if 'type' not in raw:
return False, 'Missing `type` option' return False, 'Missing `type` option'
if raw['type'] == 'ss': if raw['type'] == 'ss':
return Shadowsocks.ssFilter(raw) return Shadowsocks.ssFilter(raw)

Loading…
Cancel
Save