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']: if 'token' in envOptions['api']:
ApiToken = envOptions['api']['token'] 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 # Shadowsocks Info
mbedtlsMethods = [ mbedtlsMethods = [
'aes-128-cfb128', '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 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 def genFlag(length: int = 12) -> str: # generate random task flag
flag = '' flag = ''
for i in range(0, length): for i in range(0, length):

26
Builder/Brook.py

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

6
Builder/Hysteria.py

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

25
Builder/Shadowsocks.py

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import json import json
from Basis.Exception import buildException
from Basis.Constant import ssMethods, ssAllMethods, mbedtlsMethods from Basis.Constant import ssMethods, ssAllMethods, mbedtlsMethods
@ -20,25 +21,25 @@ def loadConfig(proxyInfo: dict, socksInfo: dict) -> dict: # load basic config o
return config 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']: if plugin in ['obfs-local', 'simple-tls', 'ck-client', 'gq-client', 'mtt-client', 'rabbit-plugin']:
return False # UDP is not used return False # UDP is not used
if plugin in ['v2ray-plugin', 'xray-plugin', 'gost-plugin']: 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 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]: def ssRust(proxyInfo: dict, socksInfo: dict, isUdp: bool) -> tuple[dict, list, dict]:
config = loadConfig(proxyInfo, socksInfo) config = loadConfig(proxyInfo, socksInfo)
if isUdp: # proxy UDP traffic if isUdp: # proxy udp traffic
config['mode'] = 'tcp_and_udp' 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]: def ssLibev(proxyInfo: dict, socksInfo: dict, isUdp: bool) -> tuple[dict, list, dict]:
config = loadConfig(proxyInfo, socksInfo) config = loadConfig(proxyInfo, socksInfo)
if isUdp: # proxy UDP traffic if isUdp: # proxy udp traffic
config['mode'] = 'tcp_and_udp' config['mode'] = 'tcp_and_udp'
return config, ['ss-libev-local', '-v'], {} 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 if config['method'] in ['idea-cfb', 'seed-cfb']: # only older versions of openssl are supported
config['extra_opts'] = '--libopenssl=libcrypto.so.1.0.0' config['extra_opts'] = '--libopenssl=libcrypto.so.1.0.0'
if not isUdp: 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' config['shadowsocks'] = 'ss-python-local'
return config, ['ss-bootstrap-local', '--debug', '-vv'], {} 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]: def ssPythonLegacy(proxyInfo: dict, socksInfo: dict, isUdp: bool) -> tuple[dict, list, dict]:
config = loadConfig(proxyInfo, socksInfo) config = loadConfig(proxyInfo, socksInfo)
if not isUdp: 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' config['shadowsocks'] = 'ss-python-legacy-local'
return config, ['ss-bootstrap-local', '--debug', '-vv'], {} return config, ['ss-bootstrap-local', '--debug', '-vv'], {}
def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]: 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 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 not pluginUdp(proxyInfo['plugin']['type'], proxyInfo['plugin']['param']) # udp conflict status of plugins
) )
if proxyInfo['method'] not in ssAllMethods: # unknown shadowsocks method 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 for client in ssMethods: # traverse all shadowsocks client
if proxyInfo['method'] not in ssMethods[client]: if proxyInfo['method'] not in ssMethods[client]:
continue continue
ssConfig, ssClient, ssEnv = { ssConfig, ssClient, ssEnv = { # found appropriate client
'ss-rust': ssRust, 'ss-rust': ssRust,
'ss-libev': ssLibev, 'ss-libev': ssLibev,
'ss-python': ssPython, 'ss-python': ssPython,

7
Builder/ShadowsocksR.py

@ -2,16 +2,17 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import json import json
from Basis.Exception import buildException
from Basis.Constant import ssrMethods, ssrProtocols, ssrObfuscations from Basis.Constant import ssrMethods, ssrProtocols, ssrObfuscations
def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]: def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]:
if proxyInfo['method'] not in ssrMethods: if proxyInfo['method'] not in ssrMethods:
raise RuntimeError('Unknown shadowsocksr method') raise buildException('Unknown shadowsocksr method')
if proxyInfo['protocol'] not in ssrProtocols: if proxyInfo['protocol'] not in ssrProtocols:
raise RuntimeError('Unknown shadowsocksr protocol') raise buildException('Unknown shadowsocksr protocol')
if proxyInfo['obfs'] not in ssrObfuscations: if proxyInfo['obfs'] not in ssrObfuscations:
raise RuntimeError('Unknown shadowsocksr obfuscation') raise buildException('Unknown shadowsocksr obfuscation')
ssrConfig = { ssrConfig = {
'server': proxyInfo['server'], 'server': proxyInfo['server'],
'server_port': proxyInfo['port'], # type -> int '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'], 'address': proxyInfo['server'],
'port': proxyInfo['port'], 'port': proxyInfo['port'],
'password': proxyInfo['passwd'], 'password': proxyInfo['passwd'],
**Xray.xtlsFlow(proxyInfo['stream']) **Xray.xtlsFlow(proxyInfo['stream']) # add xtls flow option
}] }]
}, },
'streamSettings': Xray.loadStream(proxyInfo['stream']) 'streamSettings': Xray.loadStream(proxyInfo['stream'])

7
Builder/V2ray.py

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

5
Builder/VLESS.py

@ -3,9 +3,12 @@
import json import json
from Builder import Xray from Builder import Xray
from Basis.Exception import buildException
def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]: def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]:
if proxyInfo['method'] != 'none':
raise buildException('Unknown VLESS method')
outboundConfig = { outboundConfig = {
'protocol': 'vless', 'protocol': 'vless',
'settings': { 'settings': {
@ -15,7 +18,7 @@ def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str,
'users': [{ 'users': [{
'id': proxyInfo['id'], 'id': proxyInfo['id'],
'encryption': proxyInfo['method'], '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 import json
from Builder import V2ray from Builder import V2ray
from Basis.Constant import vmessMethods from Basis.Constant import vmessMethods
from Basis.Exception import buildException
def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]: def load(proxyInfo: dict, socksInfo: dict, configFile: str) -> tuple[list, str, dict]:
if proxyInfo['method'] not in vmessMethods: if proxyInfo['method'] not in vmessMethods:
raise RuntimeError('Unknown vmess method') raise buildException('Unknown VMess method')
outboundConfig = { outboundConfig = {
'protocol': 'vmess', 'protocol': 'vmess',
'settings': { 'settings': {

7
Builder/Xray.py

@ -3,6 +3,7 @@
from Builder import V2ray from Builder import V2ray
from Basis.Constant import xtlsFlows from Basis.Constant import xtlsFlows
from Basis.Exception import buildException
loadConfig = V2ray.loadConfig loadConfig = V2ray.loadConfig
@ -11,7 +12,7 @@ def loadSecure(secureInfo: dict or None) -> dict: # TLS / XTLS encrypt config
if secureInfo is None: if secureInfo is None:
return {'security': 'none'} # without TLS / XTLS options return {'security': 'none'} # without TLS / XTLS options
if secureInfo['type'] not in ['tls', 'xtls']: if secureInfo['type'] not in ['tls', 'xtls']:
raise RuntimeError('Unknown secure type') raise buildException('Unknown xray secure type')
secureObject = { secureObject = {
'allowInsecure': not secureInfo['verify'] # whether verify server's certificate 'allowInsecure': not secureInfo['verify'] # whether verify server's certificate
} }
@ -53,7 +54,7 @@ def loadStream(streamInfo: dict) -> dict:
'grpc': V2ray.grpcStream, 'grpc': V2ray.grpcStream,
} }
if streamInfo['type'] not in streamEntry: if streamInfo['type'] not in streamEntry:
raise RuntimeError('Unknown stream type') raise buildException('Unknown xray stream type')
streamObject = streamEntry[streamInfo['type']](streamInfo) streamObject = streamEntry[streamInfo['type']](streamInfo)
return { return {
**streamObject, **streamObject,
@ -67,7 +68,7 @@ def xtlsFlow(streamInfo: dict or None) -> dict:
if streamInfo['secure']['type'] != 'xtls': # not XTLS secure type if streamInfo['secure']['type'] != 'xtls': # not XTLS secure type
return {} return {}
if streamInfo['secure']['flow'] not in xtlsFlows: if streamInfo['secure']['flow'] not in xtlsFlows:
raise RuntimeError('Unknown xtls flow') raise buildException('Unknown xtls flow')
return { return {
'flow': xtlsFlows[streamInfo['secure']['flow']] + ( # xtls-rprx-xxx 'flow': xtlsFlows[streamInfo['secure']['flow']] + ( # xtls-rprx-xxx
'-udp443' if streamInfo['secure']['udp443'] else '' # whether block udp/443 (disable http/3) '-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 import copy
from Basis.Logger import logging from Basis.Logger import logging
from Basis.Process import Process from Basis.Process import Process
from Basis.Functions import v6AddBracket
from Basis.Exception import buildException
from Basis.Constant import WorkDir, PathEnv 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 Brook
from Builder import VMess from Builder import VMess
@ -44,19 +46,19 @@ class Builder(object):
Attributes: Attributes:
id, proxyType, proxyInfo, socksAddr, socksPort, output id, proxyType, proxyInfo, socksAddr, socksPort, output
""" """
output = None output = None # output capture of proxy client (after process exit)
def __loadClient(self): def __loadClient(self):
logging.info('[%s] Builder load %s client at %s -> %s' % ( logging.info('[%s] Builder load %s client at %s -> %s' % (
self.id, self.proxyType, 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 configFile = os.path.join( # config file path
WorkDir, self.id + clientEntry[self.proxyType][1] # workDir + taskId + file suffix WorkDir, self.id + clientEntry[self.proxyType][1] # workDir + taskId + file suffix
) )
logging.debug('[%s] Builder config file -> %s' % (self.id, configFile)) logging.debug('[%s] Builder config file -> %s' % (self.id, configFile))
command, fileContent, envVar = clientEntry[self.proxyType][0](self.proxyInfo, { # load client boot info 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, 'port': self.socksPort,
}, configFile) }, configFile)
envVar['PATH'] = PathEnv # add PATH env (some programs need it) 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 self.id = genFlag(length = 12) if taskId == '' else taskId # load task ID
if proxyType not in clientEntry: if proxyType not in clientEntry:
logging.error('[%s] Builder receive unknown proxy type %s' % (self.id, proxyType)) 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.proxyType = proxyType # proxy type -> ss / ssr / vmess ...
self.proxyInfo = copy.copy(proxyInfo) # connection info self.proxyInfo = copy.copy(proxyInfo) # connection info
self.socksAddr = bindAddr self.socksAddr = bindAddr

Loading…
Cancel
Save