You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
6.0 KiB

#!/usr/bin/python
# -*- coding:utf-8 -*-
from ProxyFilter import baseFunc
from ProxyFilter import Plugin as sip003
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'
]
pluginList = [ # SIP003插件列表
'obfs-local',
'simple-tls',
'v2ray-plugin',
'xray-plugin',
'kcptun-client',
'gost-plugin',
'ck-client',
'gq-client',
'mtt-client',
'rabbit-plugin',
'qtun-client',
'gun-plugin'
]
def __ssFill(raw: dict) -> dict: # 补全可选值
try:
if 'plugin' not in raw:
raw['plugin'] = None
if raw['plugin'] is not None:
if 'param' not in raw['plugin']:
raw['plugin']['param'] = ''
except:
pass
return raw
def __ssFormat(raw: dict) -> dict: # 容错性格式化
try:
raw['server'] = raw['server'].strip()
raw['port'] = int(raw['port'])
raw['method'] = raw['method'].replace('_', '-').lower().strip()
if isinstance(raw['plugin'], str):
raw['plugin'] = raw['plugin'].strip()
if raw['plugin'] == '':
raw['plugin'] = None
else:
raw['plugin'] = {
'type': raw['plugin'],
'param': ''
}
if raw['plugin'] is not None:
if isinstance(raw['plugin']['type'], str):
raw['plugin']['type'] = raw['plugin']['type'].strip()
if raw['plugin']['type'] in [None, '']:
raw['plugin'] = None
else:
raw['plugin']['type'] = sip003.pluginFormat(raw['plugin']['type'])
except:
pass
return raw
def __ssParamCheck(raw: dict) -> tuple[bool, str or None]: # 参数检查
try:
if 'server' not in raw:
return False, 'Missing `server` option'
if 'port' not in raw:
return False, 'Missing `port` option'
if 'method' not in raw:
return False, 'Missing `method` option'
if 'passwd' not in raw:
return False, 'Missing `passwd` option'
if 'plugin' not in raw:
return False, 'Missing `plugin` option'
if raw['plugin'] is not None:
if 'type' not in raw['plugin']:
return False, 'Missing `plugin.type` option'
if 'param' not in raw['plugin']:
return False, 'Missing `plugin.param` option'
if not isinstance(raw['server'], str):
return False, 'Illegal `server` option'
if not isinstance(raw['port'], int):
return False, 'Illegal `int` option'
if not isinstance(raw['method'], str):
return False, 'Illegal `method` option'
if not isinstance(raw['passwd'], str):
return False, 'Illegal `passwd` option'
if (raw['plugin'] is not None) and (not isinstance(raw['plugin'], dict)):
return False, 'Illegal `plugin` option'
if raw['plugin'] is not None:
if not isinstance(raw['plugin']['type'], str):
return False, 'Illegal `plugin.type` option'
if not isinstance(raw['plugin']['param'], str):
return False, 'Illegal `plugin.param` option'
except:
return False, 'Unknown error'
return True, None
def ssFilter(rawInfo: dict, isExtra: bool) -> tuple[bool, str or dict]:
"""
Shadowsocks节点合法性检查
不合法:
return False, {reason}
合法:
return True, {
'type': 'ss',
...
}
"""
try:
raw = rawInfo
raw = __ssFormat(__ssFill(raw)) # 预处理
status, reason = __ssParamCheck(raw) # 参数检查
if not status: # 参数有误
return False, reason
result = {'type': 'ss'}
if isExtra: # 携带额外参数
if 'remark' not in raw: # 补全默认值
raw['remark'] = ''
if raw['remark'] is None: # 容错格式化
raw['remark'] = ''
if not isinstance(raw['remark'], str): # 参数检查
return False, 'Illegal `remark` option'
result['remark'] = raw['remark']
if baseFunc.isHost(raw['server']):
result['server'] = raw['server'] # server
else:
return False, 'Illegal `server` option'
if baseFunc.isPort(raw['port']):
result['port'] = raw['port'] # port
else:
return False, 'Illegal `port` option'
if raw['method'] in ssMethodList:
result['method'] = raw['method'] # method
else:
return False, 'Unknown Shadowsocks method'
result['passwd'] = raw['passwd'] # passwd
if raw['plugin'] is None:
plugin = None
else:
if raw['plugin']['type'] in pluginList:
plugin = {
'type': raw['plugin']['type'],
'param': raw['plugin']['param']
}
else:
return False, 'Unknown sip003 plugin'
result['plugin'] = plugin
except:
return False, 'Unknown error'
return True, result