Browse Source

feat: add build exception

master^2
dnomd343 2 years ago
parent
commit
a966c8cf5d
  1. 6
      Basis/Constant.py
  2. 6
      Basis/Exception.py
  3. 4
      Basis/Functions.py
  4. 26
      Builder/Brook.py
  5. 6
      Builder/Hysteria.py
  6. 25
      Builder/Shadowsocks.py
  7. 7
      Builder/ShadowsocksR.py
  8. 2
      Builder/Trojan.py
  9. 7
      Builder/V2ray.py
  10. 5
      Builder/VLESS.py
  11. 3
      Builder/VMess.py
  12. 7
      Builder/Xray.py
  13. 12
      Builder/__init__.py

6
Basis/Constant.py

@ -40,6 +40,12 @@ if 'api' in envOptions:
if 'token' in envOptions['api']:
ApiToken = envOptions['api']['token']
# WorkDir Create
try:
os.makedirs(WorkDir) # just like `mkdir -p ...`
except:
pass # folder exist or target is another thing
# Shadowsocks Info
mbedtlsMethods = [
'aes-128-cfb128',

6
Basis/Exception.py

@ -0,0 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class buildException(Exception): # for build error
def __init__(self, reason):
self.reason = reason

4
Basis/Functions.py

@ -55,6 +55,10 @@ def hostFormat(host: str, v6Bracket: bool = False) -> str:
return host
def v6AddBracket(host: str) -> str: # add bracket for ipv6
return hostFormat(host, v6Bracket = True)
def genFlag(length: int = 12) -> str: # generate random task flag
flag = ''
for i in range(0, length):

26
Builder/Brook.py

@ -1,30 +1,29 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from Basis.Functions import hostFormat
from Basis.Functions import v6AddBracket
def loadOrigin(proxyInfo: dict) -> list: # origin stream
return ['client'] + [
'--server', '%s:%i' % (hostFormat(proxyInfo['server'], v6Bracket = True), proxyInfo['port']),
'--server', '%s:%i' % (v6AddBracket(proxyInfo['server']), proxyInfo['port']),
'--password', proxyInfo['passwd'],
] + (['--udpovertcp'] if proxyInfo['stream']['uot'] else [])
] + (['--udpovertcp'] if proxyInfo['stream']['uot'] else []) # add uot option
def loadWebsocket(proxyInfo: dict) -> list:
isTls = proxyInfo['stream']['secure'] is not None
wsAddress = (('wss' if isTls else 'ws') + '://%s:%i%s') % (
hostFormat(proxyInfo['stream']['host'], v6Bracket = True), proxyInfo['port'], proxyInfo['stream']['path']
def loadWebsocket(proxyInfo: dict) -> list: # websocket stream
isTls = proxyInfo['stream']['secure'] is not None # ws or wss
wsAddress = (('wss' if isTls else 'ws') + '://%s:%i%s') % ( # websocket address
v6AddBracket(proxyInfo['stream']['host']), proxyInfo['port'], proxyInfo['stream']['path']
)
brookCommand = [
'wssclient' if isTls else 'wsclient',
'--address', '%s:%i' % (hostFormat(proxyInfo['server'], v6Bracket = True), proxyInfo['port']),
'--address', '%s:%i' % (v6AddBracket(proxyInfo['server']), proxyInfo['port']), # real address
'--password', proxyInfo['passwd'],
] + (['--withoutBrookProtocol'] if proxyInfo['stream']['raw'] else [])
] + (['--withoutBrookProtocol'] if proxyInfo['stream']['raw'] else []) # raw transmission on ws or wss
if not isTls:
return brookCommand + ['--wsserver', wsAddress]
return brookCommand + ['--wssserver', wsAddress] + (
[] if proxyInfo['stream']['secure']['verify'] else ['--insecure']
[] if proxyInfo['stream']['secure']['verify'] else ['--insecure'] # add tls options
)
@ -32,7 +31,6 @@ def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str,
brookCommand = ['brook', '--debug', '--listen', ':'] + { # debug module listen on random port
'origin': loadOrigin,
'ws': loadWebsocket,
}[proxyInfo['stream']['type']](proxyInfo) + [
'--socks5', '%s:%i' % (hostFormat(socksInfo['addr'], v6Bracket = True), socksInfo['port'])
]
}[proxyInfo['stream']['type']](proxyInfo) # choose origin or websocket stream
brookCommand += ['--socks5', '%s:%i' % (v6AddBracket(socksInfo['addr']), socksInfo['port'])]
return brookCommand, 'Config file %s no need' % configFile, {} # command, fileContent, envVar

6
Builder/Hysteria.py

@ -2,19 +2,19 @@
# -*- coding: utf-8 -*-
import json
from Basis.Functions import hostFormat
from Basis.Functions import v6AddBracket
def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]:
hysteriaConfig = {
'server': '%s:%i' % (hostFormat(proxyInfo['server'], v6Bracket = True), proxyInfo['port']),
'server': '%s:%i' % (v6AddBracket(proxyInfo['server']), proxyInfo['port']),
'protocol': proxyInfo['protocol'],
'up_mbps': proxyInfo['up'],
'down_mbps': proxyInfo['down'],
'retry_interval': 2,
'retry': 3,
'socks5': {
'listen': '%s:%i' % (hostFormat(socksInfo['addr'], v6Bracket = True), socksInfo['port'])
'listen': '%s:%i' % (v6AddBracket(socksInfo['addr']), socksInfo['port'])
},
**({} if proxyInfo['obfs'] is None else {
'obfs': proxyInfo['obfs']

25
Builder/Shadowsocks.py

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
import json
from Basis.Exception import buildException
from Basis.Constant import ssMethods, ssAllMethods, mbedtlsMethods
@ -20,25 +21,25 @@ def loadConfig(proxyInfo: dict, socksInfo: dict) -> dict: # load basic config o
return config
def pluginUdp(plugin: str, pluginParam: str) -> bool: # whether the plugin uses UDP
def pluginUdp(plugin: str, pluginParam: str) -> bool: # whether the plugin uses udp
if plugin in ['obfs-local', 'simple-tls', 'ck-client', 'gq-client', 'mtt-client', 'rabbit-plugin']:
return False # UDP is not used
if plugin in ['v2ray-plugin', 'xray-plugin', 'gost-plugin']:
if 'mode=quic' not in pluginParam.split(';'): # non-quic mode does not use UDP
if 'mode=quic' not in pluginParam.split(';'): # non-quic mode does not use udp
return False
return True # UDP is assumed by default
return True # udp is assumed by default
def ssRust(proxyInfo: dict, socksInfo: dict, isUdp: bool) -> tuple[dict, list, dict]:
config = loadConfig(proxyInfo, socksInfo)
if isUdp: # proxy UDP traffic
if isUdp: # proxy udp traffic
config['mode'] = 'tcp_and_udp'
return config, ['ss-rust-local', '-v'], {'RUST_BACKTRACE': 'full'}
return config, ['ss-rust-local', '-v'], {'RUST_BACKTRACE': 'full'} # enable rust trace
def ssLibev(proxyInfo: dict, socksInfo: dict, isUdp: bool) -> tuple[dict, list, dict]:
config = loadConfig(proxyInfo, socksInfo)
if isUdp: # proxy UDP traffic
if isUdp: # proxy udp traffic
config['mode'] = 'tcp_and_udp'
return config, ['ss-libev-local', '-v'], {}
@ -50,7 +51,7 @@ def ssPython(proxyInfo: dict, socksInfo: dict, isUdp: bool) -> tuple[dict, list,
if config['method'] in ['idea-cfb', 'seed-cfb']: # only older versions of openssl are supported
config['extra_opts'] = '--libopenssl=libcrypto.so.1.0.0'
if not isUdp:
config['no_udp'] = True # UDP traffic is not proxied
config['no_udp'] = True # udp traffic is not proxied
config['shadowsocks'] = 'ss-python-local'
return config, ['ss-bootstrap-local', '--debug', '-vv'], {}
@ -58,21 +59,21 @@ def ssPython(proxyInfo: dict, socksInfo: dict, isUdp: bool) -> tuple[dict, list,
def ssPythonLegacy(proxyInfo: dict, socksInfo: dict, isUdp: bool) -> tuple[dict, list, dict]:
config = loadConfig(proxyInfo, socksInfo)
if not isUdp:
config['no_udp'] = True # UDP traffic is not proxied
config['no_udp'] = True # udp traffic is not proxied
config['shadowsocks'] = 'ss-python-legacy-local'
return config, ['ss-bootstrap-local', '--debug', '-vv'], {}
def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]:
isUdp = True if proxyInfo['plugin'] is None else ( # UDP enabled when server without plugin
not pluginUdp(proxyInfo['plugin']['type'], proxyInfo['plugin']['param']) # UDP conflict status of plugins
isUdp = True if proxyInfo['plugin'] is None else ( # udp enabled when server without plugin
not pluginUdp(proxyInfo['plugin']['type'], proxyInfo['plugin']['param']) # udp conflict status of plugins
)
if proxyInfo['method'] not in ssAllMethods: # unknown shadowsocks method
raise RuntimeError('Unknown shadowsocks method')
raise buildException('Unknown shadowsocks method')
for client in ssMethods: # traverse all shadowsocks client
if proxyInfo['method'] not in ssMethods[client]:
continue
ssConfig, ssClient, ssEnv = {
ssConfig, ssClient, ssEnv = { # found appropriate client
'ss-rust': ssRust,
'ss-libev': ssLibev,
'ss-python': ssPython,

7
Builder/ShadowsocksR.py

@ -2,16 +2,17 @@
# -*- coding: utf-8 -*-
import json
from Basis.Exception import buildException
from Basis.Constant import ssrMethods, ssrProtocols, ssrObfuscations
def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]:
if proxyInfo['method'] not in ssrMethods:
raise RuntimeError('Unknown shadowsocksr method')
raise buildException('Unknown shadowsocksr method')
if proxyInfo['protocol'] not in ssrProtocols:
raise RuntimeError('Unknown shadowsocksr protocol')
raise buildException('Unknown shadowsocksr protocol')
if proxyInfo['obfs'] not in ssrObfuscations:
raise RuntimeError('Unknown shadowsocksr obfuscation')
raise buildException('Unknown shadowsocksr obfuscation')
ssrConfig = {
'server': proxyInfo['server'],
'server_port': proxyInfo['port'], # type -> int

2
Builder/Trojan.py

@ -13,7 +13,7 @@ def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str,
'address': proxyInfo['server'],
'port': proxyInfo['port'],
'password': proxyInfo['passwd'],
**Xray.xtlsFlow(proxyInfo['stream'])
**Xray.xtlsFlow(proxyInfo['stream']) # add xtls flow option
}]
},
'streamSettings': Xray.loadStream(proxyInfo['stream'])

7
Builder/V2ray.py

@ -2,8 +2,9 @@
# -*- coding: utf-8 -*-
import copy
from Basis.Exception import buildException
httpConfig = {
httpConfig = { # http obfs configure in default
'type': 'http',
'request': {
'version': '1.1',
@ -24,7 +25,7 @@ httpConfig = {
}
}
kcpConfig = {
kcpConfig = { # kcp options in default
'mtu': 1350,
'tti': 50,
'uplinkCapacity': 12,
@ -139,7 +140,7 @@ def loadStream(streamInfo: dict) -> dict:
'grpc': grpcStream,
}
if streamInfo['type'] not in streamEntry:
raise RuntimeError('Unknown stream type')
raise buildException('Unknown v2ray stream type')
streamObject = streamEntry[streamInfo['type']](streamInfo)
return {
**streamObject,

5
Builder/VLESS.py

@ -3,9 +3,12 @@
import json
from Builder import Xray
from Basis.Exception import buildException
def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]:
if proxyInfo['method'] != 'none':
raise buildException('Unknown VLESS method')
outboundConfig = {
'protocol': 'vless',
'settings': {
@ -15,7 +18,7 @@ def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str,
'users': [{
'id': proxyInfo['id'],
'encryption': proxyInfo['method'],
**Xray.xtlsFlow(proxyInfo['stream'])
**Xray.xtlsFlow(proxyInfo['stream']) # add xtls flow option
}]
}]
},

3
Builder/VMess.py

@ -4,11 +4,12 @@
import json
from Builder import V2ray
from Basis.Constant import vmessMethods
from Basis.Exception import buildException
def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]:
if proxyInfo['method'] not in vmessMethods:
raise RuntimeError('Unknown vmess method')
raise buildException('Unknown VMess method')
outboundConfig = {
'protocol': 'vmess',
'settings': {

7
Builder/Xray.py

@ -3,6 +3,7 @@
from Builder import V2ray
from Basis.Constant import xtlsFlows
from Basis.Exception import buildException
loadConfig = V2ray.loadConfig
@ -11,7 +12,7 @@ def loadSecure(secureInfo: dict or None) -> dict: # TLS / XTLS encrypt config
if secureInfo is None:
return {'security': 'none'} # without TLS / XTLS options
if secureInfo['type'] not in ['tls', 'xtls']:
raise RuntimeError('Unknown secure type')
raise buildException('Unknown xray secure type')
secureObject = {
'allowInsecure': not secureInfo['verify'] # whether verify server's certificate
}
@ -53,7 +54,7 @@ def loadStream(streamInfo: dict) -> dict:
'grpc': V2ray.grpcStream,
}
if streamInfo['type'] not in streamEntry:
raise RuntimeError('Unknown stream type')
raise buildException('Unknown xray stream type')
streamObject = streamEntry[streamInfo['type']](streamInfo)
return {
**streamObject,
@ -67,7 +68,7 @@ def xtlsFlow(streamInfo: dict or None) -> dict:
if streamInfo['secure']['type'] != 'xtls': # not XTLS secure type
return {}
if streamInfo['secure']['flow'] not in xtlsFlows:
raise RuntimeError('Unknown xtls flow')
raise buildException('Unknown xtls flow')
return {
'flow': xtlsFlows[streamInfo['secure']['flow']] + ( # xtls-rprx-xxx
'-udp443' if streamInfo['secure']['udp443'] else '' # whether block udp/443 (disable http/3)

12
Builder/__init__.py

@ -5,8 +5,10 @@ import os
import copy
from Basis.Logger import logging
from Basis.Process import Process
from Basis.Functions import v6AddBracket
from Basis.Exception import buildException
from Basis.Constant import WorkDir, PathEnv
from Basis.Functions import hostFormat, genFlag, getAvailablePort
from Basis.Functions import genFlag, getAvailablePort
from Builder import Brook
from Builder import VMess
@ -44,19 +46,19 @@ class Builder(object):
Attributes:
id, proxyType, proxyInfo, socksAddr, socksPort, output
"""
output = None
output = None # output capture of proxy client (after process exit)
def __loadClient(self):
logging.info('[%s] Builder load %s client at %s -> %s' % (
self.id, self.proxyType,
'socks5://%s:%i' % (hostFormat(self.socksAddr, v6Bracket = True), self.socksPort), self.proxyInfo
'socks5://%s:%i' % (v6AddBracket(self.socksAddr), self.socksPort), self.proxyInfo
))
configFile = os.path.join( # config file path
WorkDir, self.id + clientEntry[self.proxyType][1] # workDir + taskId + file suffix
)
logging.debug('[%s] Builder config file -> %s' % (self.id, configFile))
command, fileContent, envVar = clientEntry[self.proxyType][0](self.proxyInfo, { # load client boot info
'addr': self.socksAddr,
'addr': self.socksAddr, # specify socks5 info
'port': self.socksPort,
}, configFile)
envVar['PATH'] = PathEnv # add PATH env (some programs need it)
@ -69,7 +71,7 @@ class Builder(object):
self.id = genFlag(length = 12) if taskId == '' else taskId # load task ID
if proxyType not in clientEntry:
logging.error('[%s] Builder receive unknown proxy type %s' % (self.id, proxyType))
raise RuntimeError('Unknown proxy type')
raise buildException('Unknown proxy type')
self.proxyType = proxyType # proxy type -> ss / ssr / vmess ...
self.proxyInfo = copy.copy(proxyInfo) # connection info
self.socksAddr = bindAddr

Loading…
Cancel
Save