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.
 
 

178 lines
5.7 KiB

#!/usr/bin/python
# -*- coding:utf-8 -*-
"""
# ShadowsocksR构建器
## 节点格式
```json
{
"server": "...",
"port": ...,
"method": "...",
"passwd": "...",
"protocol": "...",
"protocolParam": "...",
"obfs": "...",
"obfsParam": "..."
}
```
+ server (str) -> 必选, 服务器地址 (IPv4 / IPv6 / Domain)
+ port (int) -> 必选, 服务器端口 (1 ~ 65535)
+ method (str) -> 必选, ShadowsocksR加密方式 (`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`)
+ passwd (str) -> 必选, ShadowsocksR连接密码
+ protocol (str) -> 必选, ShadowsocksR连接协议 (`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`)
+ protocolParam (str) -> 必选, ShadowsocksR协议参数
+ obfs (str) -> 必选, ShadowsocksR混淆方式 (`plain`,`http_post`,`http_simple`,`tls_simple`,
`tls1.2_ticket_auth`,`tls1.2_ticket_fastauth`,`random_head`)
+ obfsParam (str) -> 必选, ShadowsocksR混淆参数
"""
import json
ssrMethodList = [ # ShadowsocksR加密方式
'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 = [ # ShadowsocksR协议列表
'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 = [ # ShadowsocksR混淆方式
'plain',
'http_post',
'http_simple',
'tls_simple',
'tls1.2_ticket_auth',
'tls1.2_ticket_fastauth',
'random_head',
]
def __ssrFormatCheck(proxyInfo: dict) -> bool: # ShadowsocksR参数检查
if 'server' not in proxyInfo or not isinstance(proxyInfo['server'], str): # server -> str
return False
if 'port' not in proxyInfo or not isinstance(proxyInfo['port'], int): # port -> int
return False
if 'method' not in proxyInfo or not isinstance(proxyInfo['method'], str): # method -> str
return False
if 'passwd' not in proxyInfo or not isinstance(proxyInfo['passwd'], str): # passwd -> str
return False
if 'protocol' not in proxyInfo or not isinstance(proxyInfo['protocol'], str): # protocol -> str
return False
if 'protocolParam' not in proxyInfo or not isinstance(proxyInfo['protocolParam'], str): # protocolParam -> str
return False
if 'obfs' not in proxyInfo or not isinstance(proxyInfo['obfs'], str): # obfs -> str
return False
if 'obfsParam' not in proxyInfo or not isinstance(proxyInfo['obfsParam'], str): # obfsParam -> str
return False
return True
def load(proxyInfo: dict, socksPort: int, configFile: str) -> tuple[list or None, str or None, dict or None]:
"""
ShadowsocksR配置载入
proxyInfo: 节点信息
socksPort: 本地通讯端口
configFile: 配置文件路径
节点有误:
return None, None, None
载入成功:
return startCommand, fileContent, envVar
"""
if not __ssrFormatCheck(proxyInfo): # 参数有误
return None, None, None
if not proxyInfo['method'] in ssrMethodList: # 匹配不到加密方法
return None, None, None
if not proxyInfo['protocol'] in ssrProtocolList: # 匹配不到协议
return None, None, None
if not proxyInfo['obfs'] in ssrObfsList: # 匹配不到混淆方式
return None, None, None
config = {
'server': proxyInfo['server'],
'server_port': proxyInfo['port'],
'local_address': '127.0.0.1',
'local_port': socksPort,
'password': proxyInfo['passwd'],
'method': proxyInfo['method'],
'protocol': proxyInfo['protocol'],
'protocol_param': proxyInfo['protocolParam'],
'obfs': proxyInfo['obfs'],
'obfs_param': proxyInfo['obfsParam']
}
return ['ssr-local', '-c', configFile], json.dumps(config), {}