Browse Source

update: release Filter module

master
dnomd343 2 years ago
parent
commit
53451eebb5
  1. 12
      Filter/Brook.py
  2. 13
      Filter/Hysteria.py
  3. 8
      Filter/Shadowsocks.py
  4. 13
      Filter/ShadowsocksR.py
  5. 10
      Filter/Trojan.py
  6. 13
      Filter/TrojanGo.py
  7. 19
      Filter/V2ray.py
  8. 10
      Filter/VLESS.py
  9. 10
      Filter/VMess.py
  10. 2
      Filter/Xray.py
  11. 77
      Filter/__init__.py
  12. 61
      demo.py
  13. 4
      docs/ProxyObject/Trojan.md
  14. 4
      docs/ProxyObject/VLESS.md
  15. 2
      docs/ProxyObject/VMess.md

12
Filter/Brook.py

@ -1,8 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from Basis.Filter import rulesFilter import copy
from Basis.Functions import isHost, isPort from Basis.Functions import isHost, isPort
from Basis.Filter import Filter, rulesFilter
from Basis.Functions import toInt, toStr, toStrTidy, toBool from Basis.Functions import toInt, toStr, toStrTidy, toBool
secureObject = rulesFilter({ secureObject = rulesFilter({
@ -99,3 +100,12 @@ brookObject = rulesFilter({
'errMsg': 'Invalid Brook stream' 'errMsg': 'Invalid Brook stream'
} }
}) })
def brookFilter(proxyInfo: dict) -> dict:
proxyInfo = copy.deepcopy(proxyInfo)
proxyInfo = Filter(proxyInfo, brookObject) # run filter
stream = proxyInfo['stream']
if stream['type'] == 'ws' and stream['host'] == '':
stream['host'] = proxyInfo['server'] # fill host option in WebSocket stream
return proxyInfo

13
Filter/Hysteria.py

@ -1,10 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from Basis.Filter import rulesFilter import copy
from Basis.Functions import isHost, isPort from Basis.Functions import isHost, isPort
from Basis.Filter import Filter, rulesFilter
from Basis.Constant import hysteriaProtocols from Basis.Constant import hysteriaProtocols
from Basis.Functions import toInt, toStr, toStrTidy, toBool from Basis.Functions import isIpAddr, toInt, toStr, toStrTidy, toBool
hysteriaObject = rulesFilter({ hysteriaObject = rulesFilter({
'server': { 'server': {
@ -84,3 +85,11 @@ hysteriaObject = rulesFilter({
'errMsg': 'Invalid verify option' 'errMsg': 'Invalid verify option'
} }
}) })
def hysteriaFilter(proxyInfo: dict) -> dict:
proxyInfo = copy.deepcopy(proxyInfo)
proxyInfo = Filter(proxyInfo, hysteriaObject) # run filter
if proxyInfo['sni'] == '' and not isIpAddr(proxyInfo['server']):
proxyInfo['sni'] = proxyInfo['server']
return proxyInfo

8
Filter/Shadowsocks.py

@ -1,10 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from Basis.Filter import rulesFilter import copy
from Filter.Plugin import pluginObject from Filter.Plugin import pluginObject
from Basis.Constant import ssAllMethods from Basis.Constant import ssAllMethods
from Basis.Functions import isHost, isPort from Basis.Functions import isHost, isPort
from Basis.Filter import Filter, rulesFilter
from Basis.Functions import toInt, toStr, toStrTidy from Basis.Functions import toInt, toStr, toStrTidy
ssObject = rulesFilter({ ssObject = rulesFilter({
@ -39,3 +40,8 @@ ssObject = rulesFilter({
'errMsg': 'Invalid plugin options' 'errMsg': 'Invalid plugin options'
} }
}) })
def ssFilter(proxyInfo: dict) -> dict:
proxyInfo = copy.deepcopy(proxyInfo)
return Filter(proxyInfo, ssObject) # run filter

13
Filter/ShadowsocksR.py

@ -1,8 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from Basis.Filter import rulesFilter import copy
from Basis.Functions import isHost, isPort from Basis.Functions import isHost, isPort
from Basis.Filter import Filter, rulesFilter
from Basis.Functions import toInt, toStr, toStrTidy from Basis.Functions import toInt, toStr, toStrTidy
from Basis.Constant import ssrMethods, ssrProtocols, ssrObfuscations from Basis.Constant import ssrMethods, ssrProtocols, ssrObfuscations
@ -72,3 +73,13 @@ ssrObject = rulesFilter({
'errMsg': 'Invalid ShadowsocksR obfuscation param' 'errMsg': 'Invalid ShadowsocksR obfuscation param'
} }
}) })
def ssrFilter(proxyInfo: dict) -> dict:
proxyInfo = copy.deepcopy(proxyInfo)
proxyInfo = Filter(proxyInfo, ssrObject) # run filter
if proxyInfo['protocol'] == 'origin': # origin without param
proxyInfo['protocolParam'] = ''
if proxyInfo['obfs'] == 'plain': # plain without param
proxyInfo['obfsParam'] = ''
return proxyInfo

10
Filter/Trojan.py

@ -1,9 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import copy
from Filter import Xray from Filter import Xray
from Basis.Filter import rulesFilter
from Basis.Functions import isHost, isPort from Basis.Functions import isHost, isPort
from Basis.Filter import Filter, rulesFilter
from Basis.Functions import toInt, toStr, toStrTidy from Basis.Functions import toInt, toStr, toStrTidy
trojanObject = rulesFilter({ trojanObject = rulesFilter({
@ -41,3 +42,10 @@ trojanObject = rulesFilter({
'errMsg': 'Invalid Trojan stream' 'errMsg': 'Invalid Trojan stream'
} }
}) })
def trojanFilter(proxyInfo: dict) -> dict:
proxyInfo = copy.deepcopy(proxyInfo)
proxyInfo = Filter(proxyInfo, trojanObject) # run filter
Xray.addSni(proxyInfo) # add SNI option
return proxyInfo

13
Filter/TrojanGo.py

@ -1,11 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from Basis.Filter import rulesFilter import copy
from Filter.Plugin import pluginObject from Filter.Plugin import pluginObject
from Basis.Constant import trojanGoMethods from Basis.Constant import trojanGoMethods
from Basis.Functions import isHost, isPort from Basis.Functions import isHost, isPort
from Basis.Functions import toInt, toStr, toStrTidy, toBool from Basis.Filter import Filter, rulesFilter
from Basis.Functions import isIpAddr, toInt, toStr, toStrTidy, toBool
ssObject = rulesFilter({ ssObject = rulesFilter({
'method': { 'method': {
@ -105,3 +106,11 @@ trojanGoObject = rulesFilter({
'errMsg': 'Invalid plugin options' 'errMsg': 'Invalid plugin options'
} }
}) })
def trojanGoFilter(proxyInfo: dict) -> dict:
proxyInfo = copy.deepcopy(proxyInfo)
proxyInfo = Filter(proxyInfo, trojanGoObject) # run filter
if proxyInfo['sni'] == '' and not isIpAddr(proxyInfo['server']):
proxyInfo['sni'] = proxyInfo['server']
return proxyInfo

19
Filter/V2ray.py

@ -3,7 +3,7 @@
from Basis.Filter import rulesFilter from Basis.Filter import rulesFilter
from Basis.Constant import quicMethods, udpObfuscations from Basis.Constant import quicMethods, udpObfuscations
from Basis.Functions import toInt, toStr, toStrTidy, toBool from Basis.Functions import isIpAddr, toInt, toStr, toStrTidy, toBool
tlsObject = rulesFilter({ tlsObject = rulesFilter({
'sni': { 'sni': {
@ -237,3 +237,20 @@ grpcObject = rulesFilter({
'errMsg': 'Invalid secure options' 'errMsg': 'Invalid secure options'
} }
}) })
def addSni(proxyInfo: dict) -> None:
stream = proxyInfo['stream']
if stream['secure'] is None or stream['secure']['sni'] != '': # don't need to set SNI
return
if not isIpAddr(proxyInfo['server']):
stream['secure']['sni'] = proxyInfo['server'] # set SNI as server address (domain case)
sniContent = ''
if stream['type'] == 'tcp' and stream['obfs'] is not None: # obfs host in TCP stream
sniContent = stream['obfs']['host'].split(',')[0]
elif stream['type'] == 'ws': # WebSocket host
sniContent = stream['host']
elif stream['type'] == 'h2': # HTTP/2 host
sniContent = stream['host'].split(',')[0]
if sniContent != '':
stream['secure']['sni'] = sniContent # overwrite SNI content

10
Filter/VLESS.py

@ -1,9 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import copy
from Filter import Xray from Filter import Xray
from Basis.Filter import rulesFilter
from Basis.Functions import isHost, isPort from Basis.Functions import isHost, isPort
from Basis.Filter import Filter, rulesFilter
from Basis.Functions import toInt, toStrTidy from Basis.Functions import toInt, toStrTidy
vlessObject = rulesFilter({ vlessObject = rulesFilter({
@ -49,3 +50,10 @@ vlessObject = rulesFilter({
'errMsg': 'Invalid VLESS stream' 'errMsg': 'Invalid VLESS stream'
} }
}) })
def vlessFilter(proxyInfo: dict) -> dict:
proxyInfo = copy.deepcopy(proxyInfo)
proxyInfo = Filter(proxyInfo, vlessObject) # run filter
Xray.addSni(proxyInfo) # add SNI option
return proxyInfo

10
Filter/VMess.py

@ -1,10 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import copy
from Filter import V2ray from Filter import V2ray
from Basis.Filter import rulesFilter
from Basis.Constant import vmessMethods from Basis.Constant import vmessMethods
from Basis.Functions import isHost, isPort from Basis.Functions import isHost, isPort
from Basis.Filter import Filter, rulesFilter
from Basis.Functions import toInt, toStrTidy from Basis.Functions import toInt, toStrTidy
vmessObject = rulesFilter({ vmessObject = rulesFilter({
@ -59,4 +60,9 @@ vmessObject = rulesFilter({
} }
}) })
# TODO: add SNI / ws host / h2 host
def vmessFilter(proxyInfo: dict) -> dict:
proxyInfo = copy.deepcopy(proxyInfo)
proxyInfo = Filter(proxyInfo, vmessObject) # run filter
V2ray.addSni(proxyInfo) # add SNI option
return proxyInfo

2
Filter/Xray.py

@ -162,3 +162,5 @@ grpcObject = rulesFilter({
**copy.deepcopy(V2ray.grpcObject), **copy.deepcopy(V2ray.grpcObject),
'secure': secureRule_2 # None / tlsObject 'secure': secureRule_2 # None / tlsObject
}) })
addSni = V2ray.addSni

77
Filter/__init__.py

@ -1,60 +1,27 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" from Filter.Brook import brookFilter
xxObject = { # a dict that describe multi-field from Filter.VMess import vmessFilter
'field_1': { from Filter.VLESS import vlessFilter
'optional': ..., # field force require or not from Filter.Trojan import trojanFilter
'default': ..., # default value when field is not exist (optional == True) from Filter.Shadowsocks import ssFilter
'allowNone': ..., # whether the value can be None (override the format and filter process) from Filter.ShadowsocksR import ssrFilter
'type': ..., # type of field content (in filter process) (any / type / list / dict) from Filter.TrojanGo import trojanGoFilter
'multiSub': ..., # whether there are multi subObject (type is dict) from Filter.Hysteria import hysteriaFilter
'indexKey': ..., # index key of subObject (type is dict and multiSub == True)
'format': ..., # format function (before filter process) (invalid content -> throw error) filterEntry = {
'filter': ..., # filter function -> bool (throw error when return False) 'ss': ssFilter,
'errMsg': ..., # raise message if there is something error 'ssr': ssrFilter,
}, 'vmess': vmessFilter,
'field_2': { 'vless': vlessFilter,
... 'trojan': trojanFilter,
}, 'trojan-go': trojanGoFilter,
... 'brook': brookFilter,
'hysteria': hysteriaFilter,
} }
def Filter(proxyType: str, proxyInfo: dict) -> dict:
default value if proxyType not in filterEntry:
+ optional: False raise RuntimeError('Unknown proxy type')
+ default: None return filterEntry[proxyType](proxyInfo)
+ allowNone: False
+ format: lambda -> return same thing
+ type: force require
+ multiSub: False
+ indexKey: 'type'
+ filter: lambda -> return True
+ errMsg: 'filter error'
pre process
=> field not exist
=> optional == False -> throw errMsg
=> optional == True -> set as default value -> continue
=> field exist
=> filed is None
=> allowNone is False -> throw errMsg
=> allowNone is True -> break
=> field is not None -> continue
format process -> set as field value (maybe throw error -> catch and throw errMsg)
filter process
=> type is `any` -> filter function check (skip type compare)
=> type is `type` -> compare with field type -> filter function check
=> type is `list` -> compare every type in list with field -> filter function check
=> type is `dict`
=> multiSub == False -> recursive check
=> multiSub == True
=> field content is not dict or not include indexKey -> throw error
=> others
=> indexKey's content not in type (dict) -> throw error
=> others -> recursive check
"""

61
demo.py

@ -1,26 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from pprint import pprint from pprint import pprint
from Basis.Filter import Filter from Filter import Filter
from Basis.Filter import filterObject
from Filter.Shadowsocks import ssObject
from Filter.ShadowsocksR import ssrObject
from Filter.VMess import vmessObject
from Filter.VLESS import vlessObject
from Filter.Trojan import trojanObject
from Filter.TrojanGo import trojanGoObject
from Filter.Brook import brookObject
from Filter.Hysteria import hysteriaObject
# pprint(ssObject, sort_dicts = False)
# pprint(ssrObject, sort_dicts = False)
# pprint(vmessObject, sort_dicts = False)
# pprint(vlessObject, sort_dicts = False)
# pprint(trojanObject, sort_dicts = False)
# pprint(trojanGoObject, sort_dicts = False)
# pprint(brookObject, sort_dicts = False)
# pprint(hysteriaObject, sort_dicts = False)
# pprint(filterObject, sort_dicts = False)
ssProxy = { ssProxy = {
'server': '1.1.1.1', 'server': '1.1.1.1',
@ -38,7 +19,9 @@ ssrProxy = {
'method': 'table', 'method': 'table',
'passwd': 'dnomd343', 'passwd': 'dnomd343',
'protocol': 'auth_chain-a', 'protocol': 'auth_chain-a',
'obfs': 'http_post' 'protocolParam': '123',
'obfs': 'plain',
'obfsParam': 'ok',
} }
vmessProxy = { vmessProxy = {
@ -51,7 +34,7 @@ vmessProxy = {
'service': 'no-gfw', 'service': 'no-gfw',
'mode': ' multi ', 'mode': ' multi ',
'secure': { 'secure': {
'sni': ' DNOMD343.top', 'sni': '',
'alpn': 'h2, http/1.1', 'alpn': 'h2, http/1.1',
'verify': 'False ' 'verify': 'False '
} }
@ -66,7 +49,7 @@ vlessProxy = {
'stream': { 'stream': {
'type': 'grpc', 'type': 'grpc',
'service': 'dnomd343', 'service': 'dnomd343',
'secure': None, # 'secure': None,
# 'secure': { # 'secure': {
# 'type': 'tls', # 'type': 'tls',
# 'sni': '23333', # 'sni': '23333',
@ -85,16 +68,18 @@ vlessProxy = {
} }
trojanProxy = { trojanProxy = {
'server': '1.1.1.1', 'server': 'www.dnomd343.top',
'port': 12345, 'port': 12345,
'passwd': b'dnomd343', 'passwd': b'dnomd343',
'stream': { 'stream': {
'type': 'grpc', # 'type': 'grpc',
'type': 'h2',
# 'host': '343.re',
'service': 'dnomd343', 'service': 'dnomd343',
# 'secure': None, # 'secure': None,
'secure': { 'secure': {
'type': 'tls', 'type': 'tls',
'sni': '23333', 'sni': '',
'alpn': 'h2', 'alpn': 'h2',
'verify': 0 'verify': 0
} }
@ -110,10 +95,10 @@ trojanProxy = {
} }
trojanGoProxy = { trojanGoProxy = {
'server': '1.1.1.1', 'server': '343.re',
'port': 12345, 'port': 12345,
'passwd': 'dnomd343', 'passwd': 'dnomd343',
'sni': '343.re', 'sni': '',
'alpn': ' h2', 'alpn': ' h2',
'verify': 'FALSE', 'verify': 'FALSE',
'ws': { 'ws': {
@ -146,24 +131,24 @@ brookProxy = {
} }
hysteriaProxy = { hysteriaProxy = {
'server': '1.1.1.1', 'server': 'www.343.re',
'port': 12345, 'port': 12345,
'protocol': 'faketcp', 'protocol': 'faketcp',
'obfs': '1234', 'obfs': '1234',
'passwd': 'dnomd343', 'passwd': 'dnomd343',
'up': 100, 'up': 100,
'down': 500, 'down': 500,
'sni': '343.re', 'sni': '',
'alpn': 'h3', 'alpn': 'h3',
'verify': 'FALSE', 'verify': 'FALSE',
} }
# ret = Filter(ssProxy, ssObject) # ret = Filter('ss', ssProxy)
# ret = Filter(ssrProxy, ssrObject) # ret = Filter('ssr', ssrProxy)
# ret = Filter(vmessProxy, vmessObject) # ret = Filter('vmess', vmessProxy)
# ret = Filter(vlessProxy, vlessObject) # ret = Filter('vless', vlessProxy)
# ret = Filter(trojanProxy, trojanObject) # ret = Filter('trojan', trojanProxy)
# ret = Filter(trojanGoProxy, trojanGoObject) # ret = Filter('trojan-go', trojanGoProxy)
# ret = Filter(brookProxy, brookObject) # ret = Filter('brook', brookProxy)
ret = Filter(hysteriaProxy, hysteriaObject) ret = Filter('hysteria', hysteriaProxy)
pprint(ret, sort_dicts = False) pprint(ret, sort_dicts = False)

4
docs/ProxyObject/Trojan.md

@ -275,7 +275,7 @@
+ 类型:*str* + 类型:*str*
+ 说明:TLS握手SNI字段 + 说明:TLS握手SNI字段
+ 缺省:`obfsObject.host[0]` / `wsObject.host` / `h2Object.host[0]` / `空` + 缺省:`空`
+ 限制:无 + 限制:无
### alpn ### alpn
@ -309,7 +309,7 @@
+ 类型:*str* + 类型:*str*
+ 说明:TLS握手SNI字段 + 说明:TLS握手SNI字段
+ 缺省:`obfsObject.host[0]` / `wsObject.host` / `h2Object.host[0]` / `空` + 缺省:`空`
+ 限制:无 + 限制:无
### alpn ### alpn

4
docs/ProxyObject/VLESS.md

@ -283,7 +283,7 @@
+ 类型:*str* + 类型:*str*
+ 说明:TLS握手SNI字段 + 说明:TLS握手SNI字段
+ 缺省:`obfsObject.host[0]` / `wsObject.host` / `h2Object.host[0]` / `空` + 缺省:`空`
+ 限制:无 + 限制:无
### alpn ### alpn
@ -317,7 +317,7 @@
+ 类型:*str* + 类型:*str*
+ 说明:TLS握手SNI字段 + 说明:TLS握手SNI字段
+ 缺省:`obfsObject.host[0]` / `wsObject.host` / `h2Object.host[0]` / `空` + 缺省:`空`
+ 限制:无 + 限制:无
### alpn ### alpn

2
docs/ProxyObject/VMess.md

@ -290,7 +290,7 @@
+ 类型:*str* + 类型:*str*
+ 说明:TLS握手SNI字段 + 说明:TLS握手SNI字段
+ 缺省:`obfsObject.host[0]` / `wsObject.host` / `h2Object.host[0]` / `空` + 缺省:`空`
+ 限制:无 + 限制:无
### alpn ### alpn

Loading…
Cancel
Save