mirror of https://github.com/dnomd343/ProxyC
dnomd343
2 years ago
7 changed files with 374 additions and 34 deletions
@ -0,0 +1,311 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
import os |
||||
|
import re |
||||
|
import json |
||||
|
from Basis.Logger import logging |
||||
|
from Basis.Methods import plugin |
||||
|
from Basis.Process import Process |
||||
|
from Basis.Functions import genFlag, getAvailablePort |
||||
|
|
||||
|
settings = { |
||||
|
'serverBind': '127.0.0.1', |
||||
|
'workDir': '/tmp/ProxyC' |
||||
|
} |
||||
|
|
||||
|
pluginParams = { |
||||
|
'SITE': 'www.bing.com', |
||||
|
'PATH': '/test', |
||||
|
'HOST': '343.re', |
||||
|
'CERT': '/etc/ssl/certs/343.re/fullchain.pem', |
||||
|
'KEY': '/etc/ssl/certs/343.re/privkey.pem', |
||||
|
'PASSWD': 'dnomd343', |
||||
|
} |
||||
|
|
||||
|
pluginConfig = { |
||||
|
'simple-obfs': { |
||||
|
'http mode': [ |
||||
|
'obfs=http', |
||||
|
'obfs=http;obfs-host=${SITE}', |
||||
|
], |
||||
|
'tls mode': [ |
||||
|
'obfs=tls', |
||||
|
'obfs=tls;obfs-host=${SITE}', |
||||
|
], |
||||
|
'http mode (with uri)': [ |
||||
|
'obfs=http', |
||||
|
'obfs=http;obfs-host=${SITE};obfs-uri=${PATH}', |
||||
|
], |
||||
|
'http mode (POST method)': [ |
||||
|
'obfs=http', |
||||
|
'obfs=http;http-method=POST;obfs-host=${SITE}', |
||||
|
], |
||||
|
}, |
||||
|
'simple-tls': { |
||||
|
'http mode': [ |
||||
|
's;n=${HOST};cert=${CERT};key=${KEY}', |
||||
|
'n=${HOST}', |
||||
|
], |
||||
|
'websocket mode': [ |
||||
|
's;n=${HOST};cert=${CERT};key=${KEY};ws;ws-path=${PATH}', |
||||
|
'n=${HOST};ws;ws-path=${PATH}', |
||||
|
], |
||||
|
'http mode (with mux)': [ |
||||
|
's;cert=${CERT};key=${KEY};n=${HOST}', |
||||
|
'n=${HOST};mux=8', |
||||
|
], |
||||
|
'http mode (with auth key)': [ |
||||
|
's;n=${HOST};cert=${CERT};key=${KEY};auth=${PASSWD}', |
||||
|
'n=${HOST};auth=${PASSWD}', |
||||
|
], |
||||
|
}, |
||||
|
'v2ray': { |
||||
|
'websocket mode': [ |
||||
|
'server', |
||||
|
'', |
||||
|
], |
||||
|
'websocket mode (with tls)': [ |
||||
|
'server;tls;host=${HOST};cert=${CERT};key=${KEY}', |
||||
|
'tls;host=${HOST}', |
||||
|
], |
||||
|
'websocket mode (with path)': [ |
||||
|
'server;path=${PATH}', |
||||
|
'path=${PATH}', |
||||
|
], |
||||
|
'quic mode': [ |
||||
|
'server;mode=quic;host=${HOST};cert=${CERT};key=${KEY}', |
||||
|
'mode=quic;host=${HOST}', |
||||
|
], |
||||
|
}, |
||||
|
'xray': { |
||||
|
'websocket mode': [ |
||||
|
'server', |
||||
|
'', |
||||
|
], |
||||
|
'websocket mode (with tls)': [ |
||||
|
'server;tls;host=${HOST};cert=${CERT};key=${KEY}', |
||||
|
'tls;host=${HOST}', |
||||
|
], |
||||
|
'websocket mode (with path)': [ |
||||
|
'server;path=${PATH}', |
||||
|
'path=${PATH}', |
||||
|
], |
||||
|
'quic mode': [ |
||||
|
'server;mode=quic;host=${HOST};cert=${CERT};key=${KEY}', |
||||
|
'mode=quic;host=${HOST}', |
||||
|
], |
||||
|
'grpc mode': [ |
||||
|
'server;mode=grpc', |
||||
|
'mode=grpc', |
||||
|
], |
||||
|
'grpc mode (with tls)': [ |
||||
|
'server;tls;mode=grpc;host=${HOST};cert=${CERT};key=${KEY}', |
||||
|
'tls;mode=grpc;host=${HOST}', |
||||
|
], |
||||
|
}, |
||||
|
'kcptun': { |
||||
|
'basic mode': [ |
||||
|
'', '' # aka fast mode |
||||
|
], |
||||
|
'with nocomp': [ |
||||
|
'nocomp', 'nocomp' |
||||
|
], |
||||
|
'with key': [ |
||||
|
'key=${PASSWD}', 'key=${PASSWD}' |
||||
|
], |
||||
|
'with multi conn': [ |
||||
|
'conn=8', 'conn=8' |
||||
|
], |
||||
|
}, |
||||
|
'gost': { |
||||
|
'ws mode': [ |
||||
|
'server;mode=ws', |
||||
|
'mode=ws', |
||||
|
], |
||||
|
'mws mode': [ |
||||
|
'server;mode=mws', |
||||
|
'mode=mws;mux=1', |
||||
|
], |
||||
|
'tls mode': [ |
||||
|
'server;cert=${CERT};key=${KEY};mode=tls', |
||||
|
'serverName=${HOST};mode=tls', |
||||
|
], |
||||
|
'mtls mode': [ |
||||
|
'server;cert=${CERT};key=${KEY};mode=mtls', |
||||
|
'serverName=${HOST};mode=mtls;mux=1', |
||||
|
], |
||||
|
'xtls mode': [ |
||||
|
'server;cert=${CERT};key=${KEY};mode=xtls', |
||||
|
'serverName=${HOST};mode=xtls', |
||||
|
], |
||||
|
'h2 mode': [ |
||||
|
'server;cert=${CERT};key=${KEY};mode=h2', |
||||
|
'serverName=${HOST};mode=h2', |
||||
|
], |
||||
|
'wss mode': [ |
||||
|
'server;cert=${CERT};key=${KEY};mode=wss', |
||||
|
'serverName=${HOST};mode=wss', |
||||
|
], |
||||
|
'mwss mode': [ |
||||
|
'server;cert=${CERT};key=${KEY};mode=mwss', |
||||
|
'serverName=${HOST};mode=mwss;mux=1', |
||||
|
], |
||||
|
'quic mode': [ |
||||
|
'server;cert=${CERT};key=${KEY};mode=quic', |
||||
|
'serverName=${HOST};mode=quic', |
||||
|
], |
||||
|
'grpc mode': [ |
||||
|
'server;cert=${CERT};key=${KEY};mode=grpc', |
||||
|
'serverName=${HOST};mode=grpc', |
||||
|
], |
||||
|
}, |
||||
|
'cloak': {}, |
||||
|
'go-quiet': { |
||||
|
'chrome fingerprint': [ |
||||
|
os.path.join(settings['workDir'], 'go-quiet_config_${RANDOM}.json'), |
||||
|
'ServerName=${SITE};key=${PASSWD};TicketTimeHint=300;Browser=chrome', |
||||
|
], |
||||
|
'firefox fingerprint': [ |
||||
|
os.path.join(settings['workDir'], 'go-quiet_config_${RANDOM}.json'), |
||||
|
'ServerName=${SITE};key=${PASSWD};TicketTimeHint=300;Browser=firefox', |
||||
|
], |
||||
|
}, |
||||
|
'mos-tls-tunnel': { |
||||
|
'basic mode': [ |
||||
|
'cert=${CERT};key=${KEY}', |
||||
|
'n=${HOST}', |
||||
|
], |
||||
|
'basic mode (with mux)': [ |
||||
|
'cert=${CERT};key=${KEY};mux', |
||||
|
'n=${HOST};mux', |
||||
|
], |
||||
|
'wss mode': [ |
||||
|
'wss;cert=${CERT};key=${KEY}', |
||||
|
'wss;n=${HOST}', |
||||
|
], |
||||
|
'wss mode (with path)': [ |
||||
|
'wss;cert=${CERT};key=${KEY};wss-path=${PATH}', |
||||
|
'wss;n=${HOST};wss-path=${PATH}', |
||||
|
], |
||||
|
'wss mode (with mux)': [ |
||||
|
'wss;cert=${CERT};key=${KEY};mux', |
||||
|
'wss;n=${HOST};mux', |
||||
|
], |
||||
|
}, |
||||
|
'rabbit': { |
||||
|
'basic mode': [ |
||||
|
'${RABBIT_PORT}', |
||||
|
'serviceAddr=127.0.0.1:${RABBIT_PORT};password=${PASSWD};tunnelN=6' # emulate SIP003 (ipv4 localhost) |
||||
|
], |
||||
|
}, |
||||
|
'qtun': { |
||||
|
'basic mode': [ |
||||
|
'cert=${CERT};key=${KEY}', |
||||
|
'host=${HOST}', |
||||
|
], |
||||
|
}, |
||||
|
'gun': { |
||||
|
'basic mode': [ |
||||
|
'server:cleartext', |
||||
|
'client:cleartext', |
||||
|
], |
||||
|
'basic mode (with tls)': [ |
||||
|
'server:${CERT}:${KEY}', |
||||
|
'client:${HOST}', |
||||
|
], |
||||
|
}, |
||||
|
} |
||||
|
|
||||
|
|
||||
|
def kcptunLoad() -> None: |
||||
|
for kcptunMode in ['fast', 'fast2', 'fast3', 'normal', 'manual']: # traverse kcptun modes |
||||
|
pluginConfig['kcptun'][kcptunMode + ' mode'] = ['mode=' + kcptunMode, 'mode=' + kcptunMode] |
||||
|
for kcptunCrypt in ['aes', 'aes-128', 'aes-192', 'salsa20', 'blowfish', |
||||
|
'twofish', 'cast5', '3des', 'tea', 'xtea', 'xor', 'none']: # traverse kcptun crypt |
||||
|
pluginConfig['kcptun']['with %s crypt' % kcptunCrypt] = ['crypt=' + kcptunCrypt, 'crypt=' + kcptunCrypt] |
||||
|
|
||||
|
|
||||
|
def cloakLoad() -> None: |
||||
|
ckKey = os.popen('ck-server -key').read() # generate public and private key for cloak |
||||
|
pluginParams['CK_PUBLIC'] = re.search(r'\s+(\S+)$', ckKey.split('\n')[0])[1] |
||||
|
pluginParams['CK_PRIVATE'] = re.search(r'\s+(\S+)$', ckKey.split('\n')[1])[1] |
||||
|
pluginParams['CK_UID'] = re.search(r'\s+(\S+)\n', os.popen('ck-server -uid').read())[1] # generate uid for clock |
||||
|
logging.info('generate clock uid -> %s' % pluginParams['CK_UID']) |
||||
|
logging.info('generate clock key -> %s (Public) | %s (Private)' % ( |
||||
|
pluginParams['CK_PUBLIC'], pluginParams['CK_PRIVATE'] |
||||
|
)) |
||||
|
ckPrefix = 'UID=${CK_UID};PublicKey=${CK_PUBLIC};ServerName=${SITE};' # cloak plugin's basic command |
||||
|
ckConfigPath = os.path.join(settings['workDir'], 'cloak_config_${RANDOM}.json') # clock server's config |
||||
|
for ckMethod in ['plain', 'aes-128-gcm', 'aes-256-gcm', 'chacha20-poly1305']: # traverse cloak encrypt methods |
||||
|
pluginConfig['cloak']['%s method' % ckMethod] = [ |
||||
|
ckConfigPath, ckPrefix + 'EncryptionMethod=' + ckMethod |
||||
|
] |
||||
|
for ckBrowser in ['chrome', 'firefox']: # traverse cloak browser fingerprints |
||||
|
pluginConfig['cloak']['%s fingerprint' % ckBrowser] = [ |
||||
|
ckConfigPath, ckPrefix + 'EncryptionMethod=plain;BrowserSig=' + ckBrowser |
||||
|
] |
||||
|
pluginConfig['cloak']['single connection'] = [ # disable connection multiplexing |
||||
|
ckConfigPath, ckPrefix + 'EncryptionMethod=plain;NumConn=0' |
||||
|
] |
||||
|
|
||||
|
|
||||
|
def ssInject(server: Process, pluginInfo: dict) -> Process: |
||||
|
if pluginInfo['type'] == 'cloak': |
||||
|
ckConfig = paramFill(json.dumps({ |
||||
|
'BypassUID': ['${CK_UID}'], |
||||
|
'RedirAddr': '${SITE}', |
||||
|
'PrivateKey': '${CK_PRIVATE}' |
||||
|
})) |
||||
|
server.setFile(server.file + [{ # add cloak config file |
||||
|
'path': pluginInfo['server']['param'], |
||||
|
'content': ckConfig |
||||
|
}]) |
||||
|
elif pluginInfo['type'] == 'go-quiet': |
||||
|
server.setFile(server.file + [{ # add gq-quiet config file |
||||
|
'path': pluginInfo['server']['param'], |
||||
|
'content': paramFill(json.dumps({'key': '${PASSWD}'})) |
||||
|
}]) |
||||
|
elif pluginInfo['type'] == 'rabbit': # hijack rabbit plugin config |
||||
|
ssConfig = json.loads(server.file[0]['content']) # modify origin config |
||||
|
ssConfig.pop('plugin') # remove plugin option |
||||
|
ssConfig.pop('plugin_opts') |
||||
|
rabbitBind = ('[%s]' if ':' in ssConfig['server'] else '%s') % ssConfig['server'] # ipv4 / [ipv6] |
||||
|
rabbitPort = ssConfig['server_port'] |
||||
|
ssConfig['server'] = '127.0.0.1' # SIP003 use ipv4 localhost for communication |
||||
|
ssConfig['server_port'] = int(pluginInfo['server']['param']) # aka ${RABBIT_PORT} |
||||
|
server.file[0]['content'] = json.dumps(ssConfig) |
||||
|
server.setCmd(['sh', '-c', paramFill( |
||||
|
'rabbit -mode s -password ${PASSWD} -rabbit-addr %s:%s' % (rabbitBind, rabbitPort) # start rabbit-tcp |
||||
|
) + ' &\nexec ' + ' '.join(server.cmd)]) # shadowsocks as main process (rabbit as sub process) |
||||
|
return server |
||||
|
|
||||
|
|
||||
|
def paramFill(param: str) -> str: |
||||
|
if '${RANDOM}' in param: # refresh RANDOM field |
||||
|
pluginParams['RANDOM'] = genFlag(length = 8) |
||||
|
for field in pluginParams: |
||||
|
param = param.replace('${%s}' % field, pluginParams[field]) # fill ${XXX} field |
||||
|
return param |
||||
|
|
||||
|
|
||||
|
def load(): |
||||
|
cloakLoad() # init cloak config |
||||
|
kcptunLoad() # init kcptun config |
||||
|
for pluginType in pluginConfig: |
||||
|
for pluginTest, pluginTestInfo in pluginConfig[pluginType].items(): # traverse all plugin test item |
||||
|
if pluginType == 'rabbit': |
||||
|
pluginParams['RABBIT_PORT'] = str(getAvailablePort()) # allocate port before rabbit plugin start |
||||
|
yield { |
||||
|
'type': pluginType, |
||||
|
'caption': pluginTest, |
||||
|
'server': { # plugin info for server |
||||
|
'type': plugin[pluginType]['server'], |
||||
|
'param': paramFill(pluginTestInfo[0]), |
||||
|
}, |
||||
|
'client': { # plugin info for client |
||||
|
'type': plugin[pluginType]['client'], |
||||
|
'param': paramFill(pluginTestInfo[1]), |
||||
|
}, |
||||
|
'inject': ssInject # for some special plugins (only server part) |
||||
|
} |
Loading…
Reference in new issue