Browse Source

feat: ssr build supported, struct adjustment

master
Dnomd343 3 years ago
parent
commit
79336f90de
  1. 14
      ProxyBuilder/Shadowsocks.py
  2. 94
      ProxyBuilder/ShadowsocksR.py
  3. 25
      ProxyBuilder/main.py
  4. 32
      demo.py

14
ProxyBuilder/Shadowsocks.py

@ -173,8 +173,7 @@ def __pluginUdpCheck(plugin, pluginArg): # 插件是否使用UDP通讯
if plugin in onlyUdpPlugin: if plugin in onlyUdpPlugin:
return True return True
if plugin == 'v2ray-plugin' or plugin == 'xray-plugin' or plugin == 'gost-plugin': if plugin == 'v2ray-plugin' or plugin == 'xray-plugin' or plugin == 'gost-plugin':
if 'mode=quic' in pluginArg.split(';'): if not 'mode=quic' in pluginArg.split(';'):
return True
return False return False
return True # 默认假定占用UDP return True # 默认假定占用UDP
@ -216,7 +215,7 @@ def __ssRust(proxyInfo, socksPort): # ss-rust配置文件生成
jsonContent['mode'] = 'tcp_and_udp' jsonContent['mode'] = 'tcp_and_udp'
return jsonContent, 'ss-rust-local' return jsonContent, 'ss-rust-local'
def load(proxyInfo, socksPort, configFile): # shadowsocks配置载入 def load(proxyInfo, socksPort, configFile): # Shadowsocks配置载入
proxyInfo['udp'] = not __pluginUdpCheck(proxyInfo['plugin'], proxyInfo['pluginArg']) proxyInfo['udp'] = not __pluginUdpCheck(proxyInfo['plugin'], proxyInfo['pluginArg'])
if proxyInfo['method'] in ssMethodList['ss-libev']: if proxyInfo['method'] in ssMethodList['ss-libev']:
jsonContent, ssFile = __ssLibev(proxyInfo, socksPort) jsonContent, ssFile = __ssLibev(proxyInfo, socksPort)
@ -229,10 +228,5 @@ def load(proxyInfo, socksPort, configFile): # shadowsocks配置载入
elif proxyInfo['method'] in ssMethodList['ss-rust']: elif proxyInfo['method'] in ssMethodList['ss-rust']:
jsonContent, ssFile = __ssRust(proxyInfo, socksPort) jsonContent, ssFile = __ssRust(proxyInfo, socksPort)
else: else:
return None # 匹配不到加密方式 return None, None # 匹配不到加密方式
try: return [ ssFile, '-c', configFile ], json.dumps(jsonContent)
with open(configFile, 'w') as fileObject:
fileObject.write(json.dumps(jsonContent)) # 保存配置文件
except:
return None # 配置文件写入失败
return [ ssFile, '-c', configFile ]

94
ProxyBuilder/ShadowsocksR.py

@ -0,0 +1,94 @@
#!/usr/bin/python
# -*- coding:utf-8 -*-
import json
ssrMethodList = [ # 加密方法
"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-ctr",
"aes-192-ctr",
"aes-256-ctr",
"aes-128-gcm",
"aes-192-gcm",
"aes-256-gcm",
"aes-128-ofb",
"aes-192-ofb",
"aes-256-ofb",
"camellia-128-cfb",
"camellia-192-cfb",
"camellia-256-cfb",
"none",
"table",
"rc4",
"rc4-md5",
"rc4-md5-6",
"bf-cfb",
"cast5-cfb",
"des-cfb",
"idea-cfb",
"seed-cfb",
"rc2-cfb",
"salsa20",
"xsalsa20",
"chacha20",
"xchacha20",
"chacha20-ietf",
]
ssrProtocolList = [ # 协议
"origin",
"verify_sha1",
"verify_simple",
"verify_deflate",
"auth_simple",
"auth_sha1",
"auth_sha1_v2",
"auth_sha1_v4",
"auth_aes128",
"auth_aes128_md5",
"auth_aes128_sha1",
"auth_chain_a",
"auth_chain_b",
"auth_chain_c",
"auth_chain_d",
"auth_chain_e",
"auth_chain_f",
]
ssrObfsList = [ # 混淆方式
"plain",
"http_post",
"http_simple",
"tls_simple",
"tls1.2_ticket_auth",
"tls1.2_ticket_fastauth",
"random_head",
]
def load(proxyInfo, socksPort, configFile): # ShadowsocksR配置载入
if not proxyInfo['method'] in ssrMethodList:
return None, None # 匹配不到加密方法
if not proxyInfo['protocol'] in ssrProtocolList:
return None, None # 匹配不到协议
if not proxyInfo['obfs'] in ssrObfsList:
return None, None # 匹配不到混淆方式
return [ 'ssr-local', '-c', configFile ], json.dumps({
'server': proxyInfo['server'],
'server_port': proxyInfo['port'],
'local_address': '127.0.0.1',
'local_port': socksPort,
'password': proxyInfo['password'],
'method': proxyInfo['method'],
'protocol': proxyInfo['protocol'],
'protocol_param': proxyInfo['protocolParam'],
'obfs': proxyInfo['obfs'],
'obfs_param': proxyInfo['obfsParam']
})

25
ProxyBuilder/main.py

@ -8,6 +8,7 @@ import random
import socket import socket
import subprocess import subprocess
from ProxyBuilder import Shadowsocks from ProxyBuilder import Shadowsocks
from ProxyBuilder import ShadowsocksR
libcPaths = [ libcPaths = [
'/usr/lib64/libc.so.6', # CentOS '/usr/lib64/libc.so.6', # CentOS
@ -31,11 +32,11 @@ def __checkPortAvailable(port): # 检测端口可用性
ipv6_udp.bind(('::', port)) ipv6_udp.bind(('::', port))
ipv6_tcp.close() ipv6_tcp.close()
ipv6_udp.close() ipv6_udp.close()
return True return True # IPv4 TCP / IPv4 UDP / IPv6 TCP / IPv6 UDP 均无占用
except: except:
return False return False
finally: finally:
try: try: # 关闭socket
if ipv4_tcp: ipv4_tcp.close() if ipv4_tcp: ipv4_tcp.close()
if ipv4_udp: ipv4_udp.close() if ipv4_udp: ipv4_udp.close()
if ipv6_tcp: ipv6_tcp.close() if ipv6_tcp: ipv6_tcp.close()
@ -70,10 +71,20 @@ def build(proxyInfo, configDir): # 构建代理节点连接
proxyInfo.pop('type') proxyInfo.pop('type')
configFile = configDir + '/' + taskFlag + '.json' # 配置文件路径 configFile = configDir + '/' + taskFlag + '.json' # 配置文件路径
if (proxyType == 'shadowsocks'): # Shadowsocks节点 if proxyType == 'ss': # Shadowsocks节点
startCommand = Shadowsocks.load(proxyInfo, socksPort, configFile) startCommand, fileContent = Shadowsocks.load(proxyInfo, socksPort, configFile)
elif proxyType == 'ssr': # ShadowsocksR节点
startCommand, fileContent = ShadowsocksR.load(proxyInfo, socksPort, configFile)
else: # 未知类型 else: # 未知类型
return None return None
if startCommand == None: # 格式出错
return None
try:
with open(configFile, 'w') as fileObject:
fileObject.write(fileContent) # 保存配置文件
except:
print("Unable write to file " + configFile)
return None # 配置文件写入失败
try: try:
for libcPath in libcPaths: for libcPath in libcPaths:
@ -98,6 +109,8 @@ def build(proxyInfo, configDir): # 构建代理节点连接
} }
def check(taskInfo): # 检查客户端是否正常 def check(taskInfo): # 检查客户端是否正常
if taskInfo == None:
return False
process = taskInfo['process'] process = taskInfo['process']
if process.poll() != None: if process.poll() != None:
return False # 死亡 return False # 死亡
@ -105,6 +118,8 @@ def check(taskInfo): # 检查客户端是否正常
return True # 正常 return True # 正常
def destroy(taskInfo): # 结束客户端并清理 def destroy(taskInfo): # 结束客户端并清理
if taskInfo == None:
return
process = taskInfo['process'] process = taskInfo['process']
if process.poll() == None: # 未死亡 if process.poll() == None: # 未死亡
process.terminate() # SIGTERM process.terminate() # SIGTERM
@ -112,5 +127,5 @@ def destroy(taskInfo): # 结束客户端并清理
time.sleep(1) time.sleep(1)
process.terminate() process.terminate()
try: try:
os.remove(taskInfo.file) # 删除配置文件 os.remove(taskInfo['file']) # 删除配置文件
except: pass except: pass

32
demo.py

@ -5,23 +5,38 @@ import ProxyBuilder
def checkSocksPort(port): def checkSocksPort(port):
try: try:
startTime = time.time_ns()
r = requests.get('http://gstatic.com/generate_204', proxies = { r = requests.get('http://gstatic.com/generate_204', proxies = {
'http': 'socks5://127.0.0.1:' + str(port), 'http': 'socks5://127.0.0.1:' + str(port),
'https': 'socks5://127.0.0.1:' + str(port), 'https': 'socks5://127.0.0.1:' + str(port),
}) })
if r.status_code == 204: if r.status_code == 204:
delay = (time.time_ns() - startTime) / (10 ** 6)
print(format(delay, '.2f') + 'ms')
return True return True
except: pass except: pass
return False return False
# testInfo = {
# 'type': 'ss',
# 'server': '127.0.0.1',
# 'port': 12345,
# 'password': 'dnomd343',
# 'method': 'aes-256-ctr',
# 'plugin': '',
# 'pluginArg': '',
# }
testInfo = { testInfo = {
'type': 'shadowsocks', 'type': 'ssr',
'server': '127.0.0.1', "server": "127.0.0.1",
'port': 12345, "port": 23456,
'password': 'dnomd343', "password": "dnomd343",
'method': 'aes-256-ctr', "method": "table",
'plugin': '', "protocol": "auth_aes128_md5",
'pluginArg': '', "protocolParam": "",
"obfs": "tls1.2_ticket_auth",
"obfsParam": ""
} }
print("start") print("start")
@ -33,6 +48,9 @@ if ProxyBuilder.check(task) == False:
print("error exit") print("error exit")
else: else:
print("test with gstatic") print("test with gstatic")
checkSocksPort(task['port'])
checkSocksPort(task['port'])
checkSocksPort(task['port'])
if checkSocksPort(task['port']): if checkSocksPort(task['port']):
print("ok") print("ok")
else: else:

Loading…
Cancel
Save