#!/usr/bin/python # -*- coding:utf-8 -*- from ProxyFilter import baseFunc 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 __ssrFill(raw: dict) -> dict: # 补全可选值 try: if 'protocol' not in raw: raw['protocol'] = '' if 'protocolParam' not in raw: raw['protocolParam'] = '' if 'obfs' not in raw: raw['obfs'] = '' if 'obfsParam' not in raw: raw['obfsParam'] = '' except: pass return raw def __ssrFormat(raw: dict) -> dict: # 容错性格式化 try: raw['server'] = raw['server'].strip() raw['port'] = int(raw['port']) raw['method'] = raw['method'].replace('_', '-').lower().strip() if raw['protocol'] is None: raw['protocol'] = '' if raw['protocolParam'] is None: raw['protocolParam'] = '' if raw['obfs'] is None: raw['obfs'] = '' if raw['obfsParam'] is None: raw['obfsParam'] = '' raw['protocol'] = raw['protocol'].replace('-', '_').lower().strip() raw['obfs'] = raw['obfs'].replace('-', '_').lower().strip() except: pass return raw def __ssrParamCheck(raw: dict) -> tuple[bool, str or None]: # 参数检查 try: if 'server' not in raw: return False, 'Missing `server` option' if 'port' not in raw: return False, 'Missing `port` option' if 'method' not in raw: return False, 'Missing `method` option' if 'passwd' not in raw: return False, 'Missing `passwd` option' if 'protocol' not in raw: return False, 'Missing `protocol` option' if 'protocolParam' not in raw: return False, 'Missing `protocolParam` option' if 'obfs' not in raw: return False, 'Missing `obfs` option' if 'obfsParam' not in raw: return False, 'Missing `obfsParam` option' if not isinstance(raw['server'], str): return False, 'Illegal `server` option' if not isinstance(raw['port'], int): return False, 'Illegal `int` option' if not isinstance(raw['method'], str): return False, 'Illegal `method` option' if not isinstance(raw['passwd'], str): return False, 'Illegal `passwd` option' if not isinstance(raw['protocol'], str): return False, 'Illegal `protocol` option' if not isinstance(raw['protocolParam'], str): return False, 'Illegal `protocolParam` option' if not isinstance(raw['obfs'], str): return False, 'Illegal `obfs` option' if not isinstance(raw['obfsParam'], str): return False, 'Illegal `obfsParam` option' except: return False, 'Unknown error' return True, None def ssrFilter(rawInfo: dict, isExtra: bool) -> tuple[bool, str or dict]: """ ShadowsocksR节点合法性检查 不合法: return False, {reason} 合法: return True, { 'type': 'ssr', ... } """ try: raw = rawInfo raw = __ssrFormat(__ssrFill(raw)) # 预处理 status, reason = __ssrParamCheck(raw) # 参数检查 if not status: # 参数有误 return False, reason result = {'type': 'ssr'} if isExtra: # 携带额外参数 if 'remark' not in raw: # 补全默认值 raw['remark'] = '' if 'group' not in raw: raw['group'] = '' if raw['remark'] is None: # 容错格式化 raw['remark'] = '' if raw['group'] is None: raw['group'] = '' if not isinstance(raw['remark'], str): # 参数检查 return False, 'Illegal `remark` option' if not isinstance(raw['group'], str): return False, 'Illegal `group` option' result['remark'] = raw['remark'] result['group'] = raw['group'] if baseFunc.isHost(raw['server']): result['server'] = raw['server'] # server else: return False, 'Illegal `server` option' if baseFunc.isPort(raw['port']): result['port'] = raw['port'] # port else: return False, 'Illegal `port` option' if raw['method'] in ssrMethodList: result['method'] = raw['method'] # method else: return False, 'Unknown ShadowsocksR method' result['passwd'] = raw['passwd'] # passwd if raw['protocol'] in ['', 'origin']: # 默认协议 result['protocol'] = 'origin' result['protocolParam'] = '' else: if raw['protocol'] in ssrProtocolList: result['protocol'] = raw['protocol'] result['protocolParam'] = raw['protocolParam'] else: return False, 'Unknown ShadowsocksR protocol' if raw['obfs'] in ['', 'plain']: # 默认混淆 result['obfs'] = 'plain' result['obfsParam'] = '' else: if raw['obfs'] in ssrObfsList: result['obfs'] = raw['obfs'] result['obfsParam'] = raw['obfsParam'] else: return False, 'Unknown ShadowsocksR obfs' except: return False, 'Unknown error' return True, result