You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
6.6 KiB

#!/usr/bin/python
# -*- coding:utf-8 -*-
import json
ssMethodList = { # shadowsocks各版本支持的加密方式
"ss-python": [
"aes-128-gcm",
"aes-192-gcm",
"aes-256-gcm",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"aes-128-ocb",
"aes-192-ocb",
"aes-256-ocb",
"aes-128-ofb",
"aes-192-ofb",
"aes-256-ofb",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"aes-128-cfb1",
"aes-192-cfb1",
"aes-256-cfb1",
"aes-128-cfb8",
"aes-192-cfb8",
"aes-256-cfb8",
"aes-128-cfb128",
"aes-192-cfb128",
"aes-256-cfb128",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"camellia-128-cfb128",
"camellia-192-cfb128",
"camellia-256-cfb128",
"table",
"rc4",
"rc4-md5",
"rc2-cfb",
"bf-cfb",
"cast5-cfb",
"des-cfb",
"idea-cfb",
"seed-cfb",
"salsa20",
"xchacha20",
"chacha20",
"chacha20-ietf",
"chacha20-poly1305",
"chacha20-ietf-poly1305",
"xchacha20-ietf-poly1305",
],
"ss-python-legacy": [
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"aes-128-ofb",
"aes-192-ofb",
"aes-256-ofb",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"aes-128-cfb1",
"aes-192-cfb1",
"aes-256-cfb1",
"aes-128-cfb8",
"aes-192-cfb8",
"aes-256-cfb8",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"table",
"rc4",
"rc4-md5",
"rc2-cfb",
"bf-cfb",
"cast5-cfb",
"des-cfb",
"idea-cfb",
"seed-cfb",
"salsa20",
"salsa20-ctr",
"chacha20",
],
"ss-libev": [
"aes-128-gcm",
"aes-192-gcm",
"aes-256-gcm",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"rc4",
"rc4-md5",
"bf-cfb",
"salsa20",
"chacha20",
"chacha20-ietf",
"chacha20-ietf-poly1305",
"xchacha20-ietf-poly1305",
],
"ss-libev-legacy": [
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"table",
"rc4",
"rc4-md5",
"rc2-cfb",
"bf-cfb",
"cast5-cfb",
"des-cfb",
"idea-cfb",
"seed-cfb",
"salsa20",
"chacha20",
"chacha20-ietf",
],
"ss-rust": [
"aes-128-gcm",
"aes-256-gcm",
"plain",
"none",
"chacha20-ietf-poly1305",
]
}
def __baseJSON(proxyInfo, socksPort): # 生成JSON基本结构
jsonContent = {
'server': proxyInfo['server'],
'server_port': int(proxyInfo['port']),
'local_address': '127.0.0.1',
'local_port': int(socksPort),
'password': proxyInfo['password'],
'method': proxyInfo['method'],
}
if proxyInfo['plugin'] != '':
jsonContent['plugin'] = proxyInfo['plugin']
jsonContent['plugin_opts'] = proxyInfo['pluginArg']
return jsonContent
def __pluginUdpCheck(plugin, pluginArg): # 插件是否使用UDP通讯
if plugin == '': # 无插件
return False
noUdpPlugin = [ # 不使用UDP通讯的插件
'obfs-local',
'simple-tls',
'ck-client',
'gq-client',
'mtt-client',
'rabbit-plugin',
'gun-plugin',
]
onlyUdpPlugin = [ # 仅使用UDP通讯的插件
'kcptun-client',
'qtun-client',
]
if plugin in noUdpPlugin:
return False
if plugin in onlyUdpPlugin:
return True
if plugin == 'v2ray-plugin' or plugin == 'xray-plugin' or plugin == 'gost-plugin':
if not 'mode=quic' in pluginArg.split(';'):
return False
return True # 默认假定占用UDP
def __ssPython(proxyInfo, socksPort, isLegacy = False): # ss-python配置文件生成
jsonContent = __baseJSON(proxyInfo, socksPort)
specialMethods = [
'aes-128-cfb128',
'aes-192-cfb128',
'aes-256-cfb128',
'camellia-128-cfb128',
'camellia-192-cfb128',
'camellia-256-cfb128',
]
if isLegacy == False: # 仅新版本支持
if jsonContent['method'] in specialMethods:
jsonContent['method'] = 'mbedtls:' + jsonContent['method']
if jsonContent['method'] == 'idea-cfb' or jsonContent['method'] == 'seed-cfb':
jsonContent['extra_opts'] = '--libopenssl=libcrypto.so.1.0.0'
if proxyInfo['udp'] != True:
jsonContent['no_udp'] = True
if isLegacy == True:
jsonContent['shadowsocks'] = 'ss-python-legacy-local'
else:
jsonContent['shadowsocks'] = 'ss-python-local'
return jsonContent, 'ss-bootstrap-local'
def __ssLibev(proxyInfo, socksPort, isLegacy = False): # ss-libev配置文件生成
jsonContent = __baseJSON(proxyInfo, socksPort)
if proxyInfo['udp'] == True:
jsonContent['mode'] = 'tcp_and_udp'
if isLegacy == True:
return jsonContent, 'ss-libev-legacy-local'
else:
return jsonContent, 'ss-libev-local'
def __ssRust(proxyInfo, socksPort): # ss-rust配置文件生成
jsonContent = __baseJSON(proxyInfo, socksPort)
if proxyInfo['udp'] == True:
jsonContent['mode'] = 'tcp_and_udp'
return jsonContent, 'ss-rust-local'
def load(proxyInfo, socksPort, configFile): # Shadowsocks配置载入
proxyInfo['udp'] = not __pluginUdpCheck(proxyInfo['plugin'], proxyInfo['pluginArg'])
if proxyInfo['method'] in ssMethodList['ss-libev']:
jsonContent, ssFile = __ssLibev(proxyInfo, socksPort)
elif proxyInfo['method'] in ssMethodList['ss-libev-legacy']:
jsonContent, ssFile = __ssLibev(proxyInfo, socksPort, isLegacy = True)
elif proxyInfo['method'] in ssMethodList['ss-python']:
jsonContent, ssFile = __ssPython(proxyInfo, socksPort)
elif proxyInfo['method'] in ssMethodList['ss-python-legacy']:
jsonContent, ssFile = __ssPython(proxyInfo, socksPort, isLegacy = True)
elif proxyInfo['method'] in ssMethodList['ss-rust']:
jsonContent, ssFile = __ssRust(proxyInfo, socksPort)
else:
return None, None # 匹配不到加密方式
return [ ssFile, '-c', configFile ], json.dumps(jsonContent)