Browse Source

update: complete filter module

master
dnomd343 2 years ago
parent
commit
ae84011188
  1. 22
      Basis/Filter.py
  2. 61
      Basis/Functions.py
  3. 55
      Filter/Plugin.py
  4. 29
      Filter/Shadowsocks.py
  5. 21
      demo.py

22
Basis/Filter.py

@ -54,7 +54,7 @@ filterObject = {
'errMsg': {
'type': str,
'optional': True, # `errMsg` is not force require
'default': 'filter error',
'default': 'Filter error',
'allowNone': False, # `errMsg` couldn't be None
}
}
@ -75,7 +75,7 @@ def Filter(raw: dict, rules: dict) -> dict:
# pretreatment process (raw --[copy / default value]--> data)
if key not in raw: # key not exist
if not rule['optional']: # force require key not exist
raise RuntimeError('Miss `%s` field' % key)
raise RuntimeError('Missing `%s` field' % key)
data[key] = rule['default'] # set default value
else: # key exist
data[key] = raw[key]
@ -97,11 +97,21 @@ def Filter(raw: dict, rules: dict) -> dict:
elif type(data[key]) not in rule['type']: # type not in allow list
raise RuntimeError('Invalid `%s` field' % key)
elif type(rule['type']) == dict: # check subObject
if type(data[key]) != dict:
raise RuntimeError('Invalid sub object in `%s`' % key) # subObject content should be dict
if not rule['multiSub']: # single subObject
data[key] = Filter(data[key], rule['type'])
subRules = rule['type']
else: # multi subObject
# TODO: multi sub filter
pass
if rule['indexKey'] not in data[key]: # confirm index key exist
raise RuntimeError('Index key not found in `%s`' % key)
subType = data[key][rule['indexKey']]
if subType not in rule['type']: # confirm subObject rule exist
raise RuntimeError('Unknown index `%s` in key `%s`' % (subType, key))
subRules = rule['type'][subType]
try:
data[key] = Filter(data[key], subRules)
except RuntimeError as exp:
raise RuntimeError('%s (in `%s`)' % (exp, key)) # add located info
continue
elif rule['type'] != any: # type == any -> skip type filter
raise RuntimeError('Unknown `type` in rules')
@ -117,4 +127,4 @@ def rulesFilter(rules: dict) -> dict:
return result
filterObject = rulesFilter(filterObject) # format itself
filterObject = rulesFilter(filterObject) # self-format

61
Basis/Functions.py

@ -10,6 +10,17 @@ from IPy import IP
from Basis.Logger import logging
def isHost(raw) -> bool:
# TODO: isHost function
return True
def isPort(port: int) -> bool:
if type(port) != int:
return False
return 1 <= port <= 65535 # 1 ~ 65535
def md5Sum(data: str, encode: str = 'utf-8') -> str:
return hashlib.md5(data.encode(encoding = encode)).hexdigest()
@ -42,6 +53,36 @@ def genUUID() -> str: # generate uuid v5
))
def toInt(raw) -> int:
try:
return int(raw)
except:
raise RuntimeError('Unable convert to int')
def toStr(raw, acceptNone: bool = True) -> str:
if raw is None and acceptNone: # None -> ''
return ''
if isinstance(raw, bytes): # bytes -> str
return str(raw, encoding = 'utf-8')
try:
return str(raw)
except:
raise RuntimeError('Unable convert to str')
def toBool(raw) -> bool:
if isinstance(raw, (bool, int, float)):
return bool(raw)
try:
raw = toStr(raw).strip().lower()
if raw in ['true', 'false']:
return True if raw == 'true' else False
return int(raw) != 0
except:
raise RuntimeError('Unable convert to bool')
def getAvailablePort(rangeStart: int = 1024, rangeEnd: int = 65535, waitTime: int = 10) -> int: # get available port
if rangeStart > rangeEnd or rangeStart < 1 or rangeEnd > 65535:
raise RuntimeError('Invalid port range')
@ -86,23 +127,3 @@ def networkStatus() -> list: # get all network connections
})
logging.debug('Network status -> found %i connections' % len(result))
return result
def toInt(raw) -> int:
pass
def toStr(raw) -> str:
pass
def toBool(raw) -> bool:
pass
def isHost(raw) -> bool:
pass
def isPort(raw) -> bool:
pass

55
Filter/Plugin.py

@ -1,5 +1,58 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import copy
from Basis.Functions import toStr
from Basis.Filter import rulesFilter
from Basis.Constant import pluginClients
pluginAlias = {
'obfs-local': {'obfs', 'simple-obfs'},
'simple-tls': {'tls', 'simple-tls'},
'v2ray-plugin': {'v2ray'},
'xray-plugin': {'xray'},
'kcptun-client': {'kcptun'},
'gost-plugin': {'gost'},
'ck-client': {'ck', 'cloak'},
'gq-client': {'gq', 'goquiet', 'go-quiet'},
'mtt-client': {'mtt', 'mos-tls-tunnel'},
'rabbit-plugin': {'rabbit', 'rabbit-tcp'},
'qtun-client': {'qtun'},
'gun-plugin': {'gun'},
}
pluginObject = rulesFilter({
'type': {
'type': str,
'format': lambda s: pluginFormat(toStr(s)),
'filter': lambda s: s in pluginClients,
'errMsg': 'Unknown SIP003 plugin'
},
'param': {
'optional': True,
'default': '',
'type': str,
'format': toStr,
'errMsg': 'Invalid SIP003 param'
}
})
def loadAlias() -> None:
for plugin in pluginAlias:
for alias in copy.copy(pluginAlias[plugin]):
pluginAlias[plugin].update({ # better compatibility
alias + '-local', alias + '-plugin',
alias + '-client', alias + '-server',
})
def pluginFormat(pluginName: str) -> str:
return pluginName
pluginName = pluginName.strip().lower().replace('_', '-')
for plugin, alias in pluginAlias.items():
if pluginName in alias:
return plugin
return pluginName # alias not found
loadAlias()

29
Filter/Shadowsocks.py

@ -1,27 +1,11 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from Filter.Plugin import pluginFormat
from Basis.Filter import rulesFilter
from Filter.Plugin import pluginObject
from Basis.Constant import ssAllMethods
from Basis.Functions import toInt, toStr
from Basis.Functions import isHost, isPort
from Basis.Filter import Filter, rulesFilter
from Basis.Constant import ssMethods, pluginClients
pluginObject = rulesFilter({
'type': {
'type': str,
'format': lambda s: pluginFormat(toStr(s).strip().lower()),
'filter': lambda s: s in pluginClients,
'errMsg': 'Unknown SIP003 plugin'
},
'param': {
'optional': False,
'default': '',
'type': str,
'format': toStr,
'errMsg': 'Invalid SIP003 param'
}
})
ssObject = rulesFilter({
'server': {
@ -39,7 +23,7 @@ ssObject = rulesFilter({
'method': {
'type': str,
'format': lambda s: toStr(s).strip().lower().replace('_', '-'),
'filter': lambda s: s in ssMethods,
'filter': lambda s: s in ssAllMethods,
'errMsg': 'Unknown Shadowsocks method'
},
'passwd': {
@ -48,13 +32,10 @@ ssObject = rulesFilter({
'errMsg': 'Invalid password content'
},
'plugin': {
'optional': False,
'optional': True,
'default': None,
'allowNone': True,
'type': pluginObject,
'errMsg': 'Invalid pluginObject'
}
})
from pprint import pprint
pprint(ssObject, sort_dicts = False)

21
demo.py

@ -1,7 +1,22 @@
#!/usr/bin/env python
import Filter.Shadowsocks
from pprint import pprint
from Basis.Filter import Filter
from Basis.Filter import filterObject
from Filter.Shadowsocks import ssObject
# from pprint import pprint
# from Basis.Filter import filterObject
# pprint(ssObject, sort_dicts = False)
# pprint(filterObject, sort_dicts = False)
ssProxy = {
'server': '1.1.1.1',
'port': '12345',
'method': 'none',
'passwd': 'dnomd343',
'plugin': {
'type': 'obfs',
}
}
ret = Filter(ssProxy, ssObject)
pprint(ret, sort_dicts = False)

Loading…
Cancel
Save