def modify_multi_user_table(self, new_table): self.multi_user_table = new_table.copy() self.multi_user_host_table = {} self._protocol.obfs.server_info.users = self.multi_user_table for id in self.multi_user_table: self.multi_user_host_table[common.get_mu_host( id, self.multi_user_table[id]['md5'])] = id if self.multi_user_table[id]['forbidden_ip'] is not None: self.multi_user_table[id]['_forbidden_iplist'] = IPNetwork( str(self.multi_user_table[id]['forbidden_ip'])) else: self.multi_user_table[id][ '_forbidden_iplist'] = IPNetwork(str("")) if self.multi_user_table[id]['disconnect_ip'] is not None: self.multi_user_table[id]['_disconnect_ipset'] = IPNetwork( str(self.multi_user_table[id]['disconnect_ip'])) else: self.multi_user_table[id]['_disconnect_ipset'] = None if self.multi_user_table[id]['forbidden_port'] is not None: self.multi_user_table[id]['_forbidden_portset'] = PortRange( str(self.multi_user_table[id]['forbidden_port'])) else: self.multi_user_table[id][ '_forbidden_portset'] = PortRange(str(""))
def get_config(is_local): global verbose config = {} config_path = None logging.basicConfig(level=logging.INFO, format='%(levelname)-s: %(message)s') if is_local: # 客户端模式 shortopts = 'hd:s:b:p:k:l:m:O:o:G:g:c:t:vq' longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'user='******'version'] else: # 服务器模式 shortopts = 'hd:s:p:k:m:O:o:G:g:c:t:vq' longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'workers=', 'forbidden-ip=', 'user='******'manager-address=', 'version'] try: optlist, args = getopt.getopt(sys.argv[1:], shortopts, longopts) # 返回筛选后的命令行的(选项,值)序列 for key, value in optlist: if key == '-c': config_path = value elif key in ('-h', '--help'): print_help(is_local) sys.exit(0) elif key == '--version': print_shadowsocks() sys.exit(0) else: continue if config_path is None: config_path = find_config() if config_path: logging.debug('loading config from %s' % config_path) print(config_path) with open(config_path, 'rb') as f: try: config = parse_json_in_str(remove_comment(f.read().decode('utf8'))) except ValueError as e: logging.error('found an error in config.json: %s', str(e)) sys.exit(1) v_count = 0 for key, value in optlist: if key == '-p': config['server_port'] = int(value) elif key == '-k': config['password'] = to_bytes(value) elif key == '-l': config['local_port'] = int(value) elif key == '-s': config['server'] = to_str(value) elif key == '-m': config['method'] = to_str(value) elif key == '-O': config['protocol'] = to_str(value) elif key == '-o': config['obfs'] = to_str(value) elif key == '-G': config['protocol_param'] = to_str(value) elif key == '-g': config['obfs_param'] = to_str(value) elif key == '-b': config['local_address'] = to_str(value) elif key == '-v': v_count += 1 # '-vv' turns on more verbose mode config['verbose'] = v_count elif key == '-t': config['timeout'] = int(value) elif key == '--fast-open': config['fast_open'] = True elif key == '--workers': config['workers'] = int(value) elif key == '--manager-address': config['manager_address'] = value elif key == '--user': config['user'] = to_str(value) elif key == '--forbidden-ip': config['forbidden_ip'] = to_str(value) elif key == '-d': config['daemon'] = to_str(value) elif key == '--pid-file': config['pid-file'] = to_str(value) elif key == '--log-file': config['log-file'] = to_str(value) elif key == '-q': v_count -= 1 config['verbose'] = v_count else: continue except getopt.GetoptError as e: print(e, file=sys.stderr) print_help(is_local) sys.exit(2) if not config: logging.error('config not specified') print_help(is_local) sys.exit(2) config['password'] = to_bytes(config.get('password', b'')) config['method'] = to_str(config.get('method', 'aes-256-cfb')) config['protocol'] = to_str(config.get('protocol', 'origin')) config['protocol_param'] = to_str(config.get('protocol_param', '')) config['obfs'] = to_str(config.get('obfs', 'plain')) config['obfs_param'] = to_str(config.get('obfs_param', '')) config['port_password'] = config.get('port_password', None) config['additional_ports'] = config.get('additional_ports', {}) config['additional_ports_only'] = config.get('additional_ports_only', False) config['timeout'] = int(config.get('timeout', 300)) config['udp_timeout'] = int(config.get('udp_timeout', 120)) config['udp_cache'] = int(config.get('udp_cache', 64)) config['fast_open'] = config.get('fast_open', False) config['workers'] = config.get('workers', 1) config['pid-file'] = config.get('pid-file', '/var/run/shadowsocksr.pid') # 进程标识符文件 config['log-file'] = config.get('log-file', '/var/log/shadowsocksr.log') # 日志 config['verbose'] = config.get('verbose', False) config['connect_verbose_info'] = config.get('connect_verbose_info', 0) config['local_address'] = to_str(config.get('local_address', '127.0.0.1')) config['local_port'] = config.get('local_port', 1080) if is_local: if config.get('server', None) is None: logging.error('server addr not specified') print_local_help() sys.exit(2) else: config['server'] = to_str(config['server']) else: config['server'] = to_str(config.get('server', '0.0.0.0')) try: config['forbidden_ip'] = \ IPNetwork(config.get('forbidden_ip', '127.0.0.0/8,::1/128')) except Exception as e: logging.error(e) sys.exit(2) try: config['forbidden_port'] = PortRange(config.get('forbidden_port', '')) except Exception as e: logging.error(e) sys.exit(2) try: config['ignore_bind'] = \ IPNetwork(config.get('ignore_bind', '127.0.0.0/8,::1/128,10.0.0.0/8,192.168.0.0/16')) except Exception as e: logging.error(e) sys.exit(2) config['server_port'] = config.get('server_port', 8388) logging.getLogger('').handlers = [] logging.addLevelName(VERBOSE_LEVEL, 'VERBOSE') if config['verbose'] >= 2: level = VERBOSE_LEVEL elif config['verbose'] == 1: level = logging.DEBUG elif config['verbose'] == -1: level = logging.WARN elif config['verbose'] <= -2: level = logging.ERROR else: level = logging.INFO verbose = config['verbose'] logging.basicConfig(level=level, format='%(asctime)s %(levelname)-8s %(filename)s:%(lineno)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S') check_config(config, is_local) return config
def __init__( self, config, dns_resolver, is_local, stat_callback=None, stat_counter=None): self._config = config if config.get('connect_verbose_info', 0) > 0: common.connect_log = logging.info if config.get('connect_hex_data', 0) > 0: self._connect_hex_data = True else: self._connect_hex_data = False if is_local: self._listen_addr = config['local_address'] self._listen_port = config['local_port'] self._remote_addr = config['server'] self._remote_port = config['server_port'] else: self._listen_addr = config['server'] self._listen_port = config['server_port'] self._remote_addr = None self._remote_port = None self._dns_resolver = dns_resolver self._password = common.to_bytes(config['password']) self._method = config['method'] self._timeout = config['timeout'] self._is_local = is_local self._udp_cache_size = config['udp_cache'] self._cache = lru_cache.LRUCache( timeout=config['udp_timeout'], close_callback=self._close_client_pair) self._cache_dns_client = lru_cache.LRUCache( timeout=10, close_callback=self._close_client_pair) self._client_fd_to_server_addr = {} #self._dns_cache = lru_cache.LRUCache(timeout=1800) self._eventloop = None self._closed = False self.server_transfer_ul = 0 self.server_transfer_dl = 0 self.connected_iplist = [] self.wrong_iplist = {} self.detect_log_list = [] self.is_cleaning_connected_iplist = False self.is_cleaning_wrong_iplist = False self.is_cleaning_detect_log = False self.is_cleaning_mu_detect_log_list = False self.is_cleaning_mu_connected_iplist = False if 'users_table' in self._config: self.multi_user_table = self._config['users_table'] self.mu_server_transfer_ul = {} self.mu_server_transfer_dl = {} self.mu_connected_iplist = {} self.mu_detect_log_list = {} self.is_pushing_detect_hex_list = False self.is_pushing_detect_text_list = False self.detect_hex_list = self._config['detect_hex_list'].copy() self.detect_text_list = self._config['detect_text_list'].copy() self.protocol_data = obfs.obfs(config['protocol']).init_data() self._protocol = obfs.obfs(config['protocol']) server_info = obfs.server_info(self.protocol_data) server_info.host = self._listen_addr server_info.port = self._listen_port if 'users_table' in self._config: server_info.users = self.multi_user_table else: server_info.users = {} server_info.is_multi_user = config["is_multi_user"] server_info.protocol_param = config['protocol_param'] server_info.obfs_param = '' server_info.iv = b'' server_info.recv_iv = b'' server_info.key_str = common.to_bytes(config['password']) try: server_info.key = encrypt.encrypt_key(self._password, self._method) except Exception: logging.error("UDP: method not support") server_info.key = b'' server_info.head_len = 30 server_info.tcp_mss = 1452 server_info.buffer_size = BUF_SIZE server_info.overhead = 0 self._protocol.set_server_info(server_info) self._sockets = set() self._fd_to_handlers = {} self._reqid_to_hd = {} self._data_to_write_to_server_socket = [] self._timeouts = [] # a list for all the handlers # we trim the timeouts once a while self._timeout_offset = 0 # last checked position for timeout self._handler_to_timeouts = {} # key: handler value: index in timeouts self._bind = config.get('out_bind', '') self._bindv6 = config.get('out_bindv6', '') self._ignore_bind_list = config.get('ignore_bind', []) if 'forbidden_ip' in config: self._forbidden_iplist = IPNetwork(config['forbidden_ip']) else: self._forbidden_iplist = None if 'forbidden_port' in config: self._forbidden_portset = PortRange(config['forbidden_port']) else: self._forbidden_portset = None if 'disconnect_ip' in config: self._disconnect_ipset = IPNetwork(config['disconnect_ip']) else: self._disconnect_ipset = None self._relay_rules = self._config['relay_rules'].copy() self._is_pushing_relay_rules = False addrs = socket.getaddrinfo(self._listen_addr, self._listen_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP) if len(addrs) == 0: raise Exception("can't get addrinfo for %s:%d" % (self._listen_addr, self._listen_port)) af, socktype, proto, canonname, sa = addrs[0] server_socket = socket.socket(af, socktype, proto) server_socket.bind((self._listen_addr, self._listen_port)) server_socket.setblocking(False) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024 * 1024) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024 * 1024) self._server_socket = server_socket self._stat_callback = stat_callback