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