def new_server(self, port, user_config): ret = True port = int(port) ipv6_ok = False if 'server_ipv6' in self.config: if port in self.tcp_ipv6_servers_pool: logging.info("server already at %s:%d" % (self.config['server_ipv6'], port)) return 'this port server is already running' else: a_config = self.config.copy() a_config.update(user_config) if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == "[" and a_config['server_ipv6'][-1] == "]": a_config['server_ipv6'] = a_config['server_ipv6'][1:-1] a_config['server'] = a_config['server_ipv6'] a_config['server_port'] = port a_config['max_connect'] = 128 a_config['method'] = common.to_str(a_config['method']) try: logging.info("starting server at [%s]:%d" % (common.to_str(a_config['server']), port)) tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False, stat_counter=self.stat_counter) tcp_server.add_to_loop(self.loop) self.tcp_ipv6_servers_pool.update({port: tcp_server}) udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False, stat_counter=self.stat_counter) udp_server.add_to_loop(self.loop) self.udp_ipv6_servers_pool.update({port: udp_server}) if common.to_str(a_config['server_ipv6']) == "::": ipv6_ok = True except Exception as e: logging.warn("IPV6 %s " % (e,)) if 'server' in self.config: if port in self.tcp_servers_pool: logging.info("server already at %s:%d" % (common.to_str(self.config['server']), port)) return 'this port server is already running' else: a_config = self.config.copy() a_config.update(user_config) a_config['server_port'] = port a_config['max_connect'] = 128 a_config['method'] = common.to_str(a_config['method']) try: logging.info("starting server at %s:%d" % (common.to_str(a_config['server']), port)) tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) tcp_server.add_to_loop(self.loop) self.tcp_servers_pool.update({port: tcp_server}) udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) udp_server.add_to_loop(self.loop) self.udp_servers_pool.update({port: udp_server}) except Exception as e: if not ipv6_ok: logging.warn("IPV4 %s " % (e,)) return True
def new_server(self, port, user_config): port = int(port) if 'server' in self.config: if port in self.tcp_servers_pool: logging.info("server already at %s:%d" % (common.to_str(self.config['server']), port)) return 'this port server is already running' else: a_config = self.config.copy() a_config.update(user_config) a_config['server_port'] = port a_config['max_connect'] = 128 a_config['method'] = common.to_str(a_config['method']) try: logging.info("starting server at %s:%d" % (common.to_str(a_config['server']), port)) tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) tcp_server.add_to_loop(self.loop) self.tcp_servers_pool.update({port: tcp_server}) udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) udp_server.add_to_loop(self.loop) self.udp_servers_pool.update({port: udp_server}) except Exception as e: logging.warn("IPV4 %s " % (e, )) return True
def handler(): config = { "password": password, "method": crypt_name, "server_port": port, "timeout": 60, "server": "::", "fast_open": False } try: loop = eventloop.EventLoop() dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, False, stat_callback=call_back) udp_server = udprelay.UDPRelay(config, dns_resolver, False) dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) loop.run() except IOError as e: if e.errno == 98: sys.exit(1) except Exception as e: shell.print_exception(e) sys.exit(1)
def main(): shell.check_python() config = shell.get_config(False) daemon.daemon_exec(config) if config['port_password']: if config['password']: logging.warn('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: config['port_password'] = {} server_port = config['server_port'] if type(server_port) == list: for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: config['port_password'][str(server_port)] = config['password'] tcp_servers = [] udp_servers = [] dns_resolver = asyncdns.DNSResolver() for port, password in config['port_password'].items(): a_config = config.copy() a_config['server_port'] = int(port) a_config['password'] = password logging.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) def run_server(): def child_handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') list( map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1) run_server()
def main(): shell.check_python() # fix py2exe if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) config = shell.get_config(True) daemon.daemon_exec(config) logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) daemon.set_user(config.get('user', None)) loop.run()
def deployProxy(configs, index): config = configs[index] try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: raise
def __init__(self, ssconfig, thread_num=0, timeout=1.0): super(SSThread, self).__init__() self.ssconfig = ssconfig self.loop = eventloop.EventLoop() self.dns_resolver = asyncdns.DNSResolver() self.tcp_server = tcprelay.TCPRelay(self.ssconfig, self.dns_resolver, True) self.udp_server = udprelay.UDPRelay(self.ssconfig, self.dns_resolver, True)
def main(): # Python 2.6+ or Python3.3+ shell.check_python() # fix py2exe if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) config = shell.get_config(True) if not config.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False # only daemon.daemon_exec(config) logging.info( "local start with protocol[%s] password [%s] method [%s] obfs [%s] obfs_param [%s]" % (config['protocol'], config['password'], config['method'], config['obfs'], config['obfs_param'])) try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) # DNS分解器 dns_resolver = asyncdns.DNSResolver() # TCP服务 tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) # UDP服务 udp_server = udprelay.UDPRelay(config, dns_resolver, True) # 将DNS服务、TCP服务、UDP服务加入事件循环 loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) # 预设信号处理函数,接收到正常的退出信号 signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) def int_handler(signum, _): sys.exit(1) # SIGINT是键盘ctrl + c signal.signal(signal.SIGINT, int_handler) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1)
def main(): global loop utils.check_python() # fix py2exe if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) config = utils.get_config(True) daemon.daemon_exec(config) utils.print_shadowsocks() encrypt.try_cipher(config['password'], config['method']) try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) # signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) def int_handler(signum, _): sys.exit(1) # signal.signal(signal.SIGINT, int_handler) loop.run() try: tcp_server.close(next_tick=True) udp_server.close(next_tick=True) except: pass except (KeyboardInterrupt, IOError, OSError) as e: import traceback traceback.print_exc() logging.error(e) if config['verbose']: import traceback traceback.print_exc() os._exit(1)
def _start_ss(self): logging.info("starting local at %s:%d" % (self.config['local_address'], self.config['local_port'])) print("starting local at %s:%d" % (self.config['local_address'], self.config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(self.config, dns_resolver, True) udp_server = udprelay.UDPRelay(self.config, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) loop.run()
def add_port(self, config): port = int(config['server_port']) servers = self._relays.get(port, None) if servers: logging.error('server already exists at %s:%d' % (config['server'], port)) return logging.info('adding server at %s:%d' % (config['server'], port)) t = tcprelay.TCPRelay(config, self._dns_resolver, False, self.stat_callback) u = udprelay.UDPRelay(config, self._dns_resolver, False, self.stat_callback) t.add_to_loop(self._loop) u.add_to_loop(self._loop) self._relays[port] = (t, u)
def main(): shell.check_python() # 判断python版本 # fix py2exe # hasattr(object, name) 判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。 if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): # sys.executable python可执行文件的绝对路径 # os.path.abspath(path) 返回绝对路径 # os.path.dirname(path) 返回文件路径 # os.chdir() 用于改变当前工作目录到指定的路径 p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) # 获取配置字典,包含每个配置项的具体配置值 config = shell.get_config(True) # 根据配置文件当中的关键字daemon决定程序是启动/停止/重启 daemon.daemon_exec(config) try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1)
def add_port(self, config): port = int(config['server_port']) servers = self._relays.get(port, None) if servers: logging.error("Server Exists: P[%d], M[%s], E[%s]" % (port, config['method'], config['email'])) return logging.info("Server Added: P[%d], M[%s], E[%s]" % (port, config['method'], config['email'])) t = tcprelay.TCPRelay(config, self._dns_resolver, False, self.stat_callback) u = udprelay.UDPRelay(config, self._dns_resolver, False, self.stat_callback) t.add_to_loop(self._loop) u.add_to_loop(self._loop) self._relays[port] = (t, u)
def add_server(self, user_config): config = self._config.copy() config.update(user_config) port = int(config['server_port']) if port in self._relays: logging.error("server already at %s:%d" % (config['server'], port)) return False logging.info("add server at %s:%d" % (config['server'], port)) t = tcprelay.TCPRelay(config, self._dns_resolver, False, self.stat_callback) u = udprelay.UDPRelay(config, self._dns_resolver, False, self.stat_callback) t.add_to_loop(self._loop) u.add_to_loop(self._loop) self._relays[port] = (t, u) return True
def add_port(self, config): a_config = self._config.copy() a_config.update(config) port = int(a_config['server_port']) servers = self._relays.get(port, None) if servers: logging.error("server already exists at %s:%d" % (a_config['server'],port)) return False logging.info("adding server at %s:%d" % (a_config['server'], port)) t = tcprelay.TCPRelay(a_config, self._dns_resolver, False, self.stat_callback) u = udprelay.UDPRelay(a_config, self._dns_resolver, False, self.stat_callback) t.add_to_loop(self._loop) u.add_to_loop(self._loop) self._relays[port] = (t, u, a_config['username'], a_config['password'], a_config['method']) return True
def main(): # 检查 python 版本 shell.check_python() # fix py2exe if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) config = shell.get_config(True) # 加载配置文件 daemon.daemon_exec(config) # 读取配置文件是否开启进程守护, 仅在UNIX ,Linux 上有效 try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() # 创建dns 查询对象 tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) # 创建 TCP 代理转发对象 udp_server = udprelay.UDPRelay(config, dns_resolver, True) # 创建 UDP 代理转发对象 loop = eventloop.EventLoop() # 创建事件处理对象 # 将dns查询、tcp代理方式转发、udp代理方式转发绑定到事件循环 dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) # "Ctrl + C" 中断指令 def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) daemon.set_user(config.get('user', None)) loop.run() # 开启事件循环 except Exception as e: shell.print_exception(e) sys.exit(1)
def run(config): shell.check_python() # fix py2exe if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) loop.run()
def add_port(self, config): port = int(config['server_port']) servers = self._relays.get(port, None) if servers: logging.error("Server Exists: P[%d], M[%s], E[%s]" % ( port, config['method'], config['email'])) return # Check if AEAD cipher is enforced if config['aead_enforcement'] and config['method'] not in aead_ciphers: logging.warning("AEAD Cipher Enforced - Rejected Server: P[%d], M[%s], E[%s]" % ( port, config['method'], config['email'])) return t = tcprelay.TCPRelay(config, self._dns_resolver, False, self.stat_callback) u = udprelay.UDPRelay(config, self._dns_resolver, False, self.stat_callback) t.add_to_loop(self._loop) u.add_to_loop(self._loop) self._relays[port] = (t, u) logging.info("Server Added: P[%d], M[%s], E[%s]" % (port, config['method'], config['email']))
def stopOnUnix(self, ssrDict, *args): ssrDict['daemon'] = 'stop' ssrDict['local_address'] = args[0] ssrDict['local_port'] = args[1] ssrDict['timeout'] = args[2] ssrDict['workers'] = args[3] ssrDict['pid-file'] = args[4] ssrDict['log-file'] = args[5] if not ssrDict.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False try: daemon.daemon_exec(ssrDict) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(ssrDict, dns_resolver, True) udp_server = udprelay.UDPRelay(ssrDict, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logger.info('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) def int_handler(signum, _): logger.info("ShadowsocksR is stop") sys.exit(1) signal.signal(signal.SIGINT, int_handler) daemon.set_user(ssrDict.get('user', None)) logger.info('ShadowsocksR is start on {0}:{1}'.format(args[0], args[1])) loop.run() except Exception as e: logger.error(e) sys.exit(1)
def add_port(self, config): """ 添加服务端口,并保持只有一个服务端,同时监听tcp和udp的数据包 :param config: 配置信息 :return: 如果已存在服务端则返回 """ port = int(config['server_port']) servers = self._relays.get(port, None) if servers: logging.error("server already exists at %s:%d" % (config['server'], port)) return logging.info("adding server at %s:%d" % (config['server'], port)) t = tcprelay.TCPRelay(config, self._dns_resolver, False, self.stat_callback) u = udprelay.UDPRelay(config, self._dns_resolver, False, self.stat_callback) t.add_to_loop(self._loop) u.add_to_loop(self._loop) self._relays[port] = (t, u)
def daemon_embeded(config): if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) #config = shell.get_config(True) print(config) daemon.daemon_exec(config) logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) daemon.set_user(config.get('user', None)) loop.run()
def main(): shell.check_python() config = shell.get_config(False) daemon.daemon_exec(config) if config['port_password']: if config['password']: logging.warn('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: config['port_password'] = {} server_port = config.get('server_port', None) if server_port: if type(server_port) == list: for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: config['port_password'][str(server_port)] = config['password'] if config.get('manager_address', 0): logging.info('entering manager mode') manager.run(config) return tcp_servers = [] udp_servers = [] if 'dns_server' in config: # allow override settings in resolv.conf dns_resolver = asyncdns.DNSResolver(config['dns_server']) else: dns_resolver = asyncdns.DNSResolver() port_password = config['port_password'] del config['port_password'] for port, password in port_password.items(): a_config = config.copy() a_config['server_port'] = int(port) a_config['password'] = password logging.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) def run_server(): def child_handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') list(map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1) if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) os.waitpid(pid, 0) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGINT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()
def main(): shell.check_python3() config = shell.get_config(False) shell.log_shadowsocks_version() daemon.daemon_exec(config) try: import resource logging.info( 'current process RLIMIT_NOFILE resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) except ImportError: pass if config['port_password']: pass else: config['port_password'] = {} server_port = config['server_port'] if type(server_port) == list: for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: config['port_password'][str(server_port)] = config['password'] if not config.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False if config.get('manager_address', 0): logging.info('entering manager mode') manager.run(config) return tcp_servers = [] udp_servers = [] dns_resolver = asyncdns.DNSResolver() if int(config['workers']) > 1: stat_counter_dict = None else: stat_counter_dict = {} port_password = config['port_password'] config_password = config.get('password', 'm') del config['port_password'] for port, password_obfs in port_password.items(): method = config["method"] protocol = config.get("protocol", 'origin') protocol_param = config.get("protocol_param", '') obfs = config.get("obfs", 'plain') obfs_param = config.get("obfs_param", '') bind = config.get("out_bind", '') bindv6 = config.get("out_bindv6", '') if type(password_obfs) == list: password = password_obfs[0] obfs = common.to_str(password_obfs[1]) if len(password_obfs) > 2: protocol = common.to_str(password_obfs[2]) elif type(password_obfs) == dict: password = password_obfs.get('password', config_password) method = common.to_str(password_obfs.get('method', method)) protocol = common.to_str(password_obfs.get('protocol', protocol)) protocol_param = common.to_str( password_obfs.get('protocol_param', protocol_param)) obfs = common.to_str(password_obfs.get('obfs', obfs)) obfs_param = common.to_str( password_obfs.get('obfs_param', obfs_param)) bind = password_obfs.get('out_bind', bind) bindv6 = password_obfs.get('out_bindv6', bindv6) else: password = password_obfs a_config = config.copy() ipv6_ok = False logging.info( "server start with protocol[%s] password [%s] method [%s] obfs [%s] obfs_param [%s]" % (protocol, password, method, obfs, obfs_param)) if 'server_ipv6' in a_config: try: if len(a_config['server_ipv6'] ) > 2 and a_config['server_ipv6'][ 0] == "[" and a_config['server_ipv6'][-1] == "]": a_config['server_ipv6'] = a_config['server_ipv6'][1:-1] a_config['server_port'] = int(port) a_config['password'] = password a_config['method'] = method a_config['protocol'] = protocol a_config['protocol_param'] = protocol_param a_config['obfs'] = obfs a_config['obfs_param'] = obfs_param a_config['out_bind'] = bind a_config['out_bindv6'] = bindv6 a_config['server'] = a_config['server_ipv6'] logging.info("starting server at [%s]:%d" % (a_config['server'], int(port))) tcp_servers.append( tcprelay.TCPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) udp_servers.append( udprelay.UDPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) if a_config['server_ipv6'] == b"::": ipv6_ok = True except Exception as e: shell.print_exception(e) try: a_config = config.copy() a_config['server_port'] = int(port) a_config['password'] = password a_config['method'] = method a_config['protocol'] = protocol a_config['protocol_param'] = protocol_param a_config['obfs'] = obfs a_config['obfs_param'] = obfs_param a_config['out_bind'] = bind a_config['out_bindv6'] = bindv6 logging.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append( tcprelay.TCPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) udp_servers.append( udprelay.UDPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) except Exception as e: if not ipv6_ok: shell.print_exception(e) def run_server(): def child_handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') list( map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1) if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) os.waitpid(pid, 0) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGINT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()
def main(): shell.check_python() #检查python版本 config = shell.get_config(False) #从配置文件,命令行等获取参数 daemon.daemon_exec(config) #根据'daemon'参数来start,stop或restart ssserver if config['port_password']: if config['password']: logging.warn('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: config['port_password'] = {} server_port = config['server_port'] if type(server_port) == list: for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: config['port_password'][str(server_port)] = config['password'] if config.get('manager_address', 0): logging.info('entering manager mode') manager.run(config) return tcp_servers = [] udp_servers = [] # 类DNSResolver初始化时会从/etc/hosts和/etc/resolv.conf中获取hostname和dns dns_resolver = asyncdns.DNSResolver() port_password = config['port_password'] del config['port_password'] for port, password in port_password.items(): a_config = config.copy() a_config['server_port'] = int(port) a_config['password'] = password logging.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) def run_server(): def child_handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') # map(function, sequence[, sequence, ...]) -> list 将function函数作用到 # sequence中的每一个元素,也就是关掉上面打开的所有的socket list( map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) # 注册SIGQUIT或SIGTERM的信号处理函数,Windows不支持SIGQUIT而Linux支持,所以为了 # 跨平台兼容,此处使用了getattr函数 # 在调用exec前,子进程会继承父进程注册的信号处理action,这里在子进程中重新注册 # 了SIGTERM信号的处理action,不出意外,signal函数会返回上一次注册的action signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) # 为SIGINT注册信号处理函数 def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() # 将dns以及之前tcp, udp的socket都注册到epoll事件表中 dns_resolver.add_to_loop(loop) list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1) if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) os.waitpid(pid, 0) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGINT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()
def main(): # 检查python版本 utils.check_python() # fix py2exe # 应该是专门为py2exe检查当前执行路径用的 if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) # 形参是is_local=True config = utils.get_config(True) # linux系统:执行守护进程 daemon.daemon_exec(config) # 显示当前的ss版本号 utils.print_shadowsocks() # 创建加密器类的实例 encrypt.try_cipher(config['password'], config['method']) try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) # dns只是tcp上面的一个应用,所以没有自己的bind # 新建dns_resolver dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) # 创建时间循环的类实例 loop = eventloop.EventLoop() # dns请求报文发出去了之后要监测响应报文 dns_resolver.add_to_loop(loop) # client发远程网站地址给proxy,proxy去查找DNS tcp_server.add_to_loop(loop) # 递送tcp数据 udp_server.add_to_loop(loop) # 递送udp数据 # 定义退出信号捕获处理函数 def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') # 连带关闭socket(因为next = true) tcp_server.close(next_tick=True) udp_server.close(next_tick=True) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) # 进程终止 def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) # 运行事件循环,思想还是挺高端的 loop.run() # 按下 Ctrl+c 退出 except (KeyboardInterrupt, IOError, OSError) as e: logging.error(e) if config['verbose']: import traceback traceback.print_exc() os._exit(1)
def main(): # 检查python版本 shell.check_python() config = shell.get_config(False) # 获取配置文件,其中参数False 是标识符is_local的假值,表示要获取非local配置 daemon.daemon_exec(config) # 检查配置是否要开启进程守护,仅在UNIX, Linux 上有效 # 多用户分配设置处理 if config['port_password']: if config['password']: logging.warning('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: config['port_password'] = {} server_port = config['server_port'] if type(server_port) == list: for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: config['port_password'][str(server_port)] = config['password'] if config.get('manager_address', 0): logging.info('entering manager mode') manager.run(config) return tcp_servers = [] udp_servers = [] dns_resolver = asyncdns.DNSResolver() # 创建DNS查询对象 port_password = config['port_password'] # 获取 del config['port_password'] # 删除config 字典中的"port_password"键 # 将多用户配置转换为单用户配置 for port, password in port_password.items(): a_config = config.copy() a_config['server_port'] = int(port) # 创建"server_port"键 a_config['password'] = password # 创建"password"键 logging.info("starting server at %s:%d" % (a_config['server'], int(port))) # 记录服务开启 tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) # 添加TCP查询对象,TCP代理实现 udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) # 添加UDP查询对象 # 开启服务 def run_server(): def child_handler(signum, _): logging.warning('received SIGQUIT, doing graceful shutting down..') list(map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() # 创建事件循环处理对象 dns_resolver.add_to_loop(loop) # 将DNS绑定到事件循环 list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) daemon.set_user(config.get('user', None)) # 开启角色进程守护 loop.run() # 开启事件处理死循环 except Exception as e: shell.print_exception(e) # 异常处理 sys.exit(1) # 退出 if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) os.waitpid(pid, 0) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGINT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()
def main(): shell.check_python() # 获取配置文件,如果没有配置文件将给与默认的配置,配置如下 """ { "server": "0.0.0.0", "server_ipv6": "::", "server_port": 8388, "local_address": "127.0.0.1", "local_port": 1080, "password": "******", "timeout": 120, "udp_timeout": 60, "method": "aes-256-cfb", "protocol": "origin", "protocol_param": "", "obfs": "http_simple_compatible", "obfs_param": "", "dns_ipv6": false, "connect_verbose_info": 0, "redirect": "", "fast_open": false } """ config = shell.get_config(False) daemon.daemon_exec(config) # 写了port_password的配置 if config['port_password']: # 用了password就不用port_password if config['password']: logging.warn('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: # 没有写入port_password配置的情况 config['port_password'] = {} server_port = config['server_port'] # 判断服务器端口是否为一个数组是的话就,使用password作为密码的放在port_password中 if type(server_port) == list: for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: config['port_password'][str(server_port)] = config['password'] # 组装完如下 # """ # port_password:{ # port:password # } # """ # 是否启动了dns_ipv6 if not config.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False # 使用启用了管理者 # if config.get('manager', 0): # logging.info('entering manager mode') # # 判断是否使用管理者????这里我也还没有看源码 # manager.run(config) # return tcp_servers = [] udp_servers = [] dns_resolver = asyncdns.DNSResolver() port_password = config['port_password'] # 删除port_password这个数据 del config['port_password'] for port, password_obfs in port_password.items(): # 默认参数 # 加密方式 method = config.get("method", 'aes-256-cfb') # 用户密码 password = config.get("password", 'password') # 协议加密 protocol = config.get("protocol", 'origin') # 混淆方式 obfs = config.get("obfs","plain") # 获取混淆参数 obfs_param = config.get("obfs_param", '') # 判断是否是一个数组,格式如下 """ port_password:{ port:['password','obfs'], port:['password','obfs'], .... } """ if type(password_obfs) == list: password = password_obfs[0] obfs = password_obfs[1] elif type(password_obfs) == dict: # 字典的情况下,格式如下 """ port_password:{ port:{ password:password, protocol:protocol, obfs:obfs, obfs_param:obfs_param }, .... } """ # 如果是1的话表示无效的状态0表示正常 if password_obfs.get("flowMark",0) == 1 or password_obfs.get("dateMark",0) == 1: continue # 密码 password = password_obfs.get('password', 'm') # 协议 protocol = password_obfs.get('protocol', 'origin') # 协议参数 protocol_param = password_obfs.get('protocol_param', '') # 混淆方式 obfs = password_obfs.get('obfs', 'plain') # 混淆参数 obfs_param = password_obfs.get('obfs_param', '') # 获取加密方式 method = password_obfs.get("method", 'aes-256-cfb') else: password = password_obfs obfs = config["obfs"] a_config = config.copy() ipv6_ok = False logging.info("server start with protocol[%s] password [%s] method [%s] obfs [%s] obfs_param [%s]" % (protocol, password, a_config['method'], obfs, obfs_param)) if 'server_ipv6' in a_config: try: if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == "[" and a_config['server_ipv6'][-1] == "]": a_config['server_ipv6'] = a_config['server_ipv6'][1:-1] a_config['server'] = a_config['server_ipv6'] a_config['server_port'] = port a_config['password'] = password a_config['protocol'] = protocol a_config['protocol_param'] = protocol_param a_config['obfs'] = obfs a_config['obfs_param'] = obfs_param a_config['method'] = method logging.info("starting server at [%s]:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) if a_config['server_ipv6'] == b"::": ipv6_ok = True except Exception as e: shell.print_exception(e) try: a_config = config.copy() a_config['server_port'] = port a_config['password'] = password a_config['protocol'] = protocol a_config['protocol_param'] = protocol_param a_config['obfs'] = obfs a_config['obfs_param'] = obfs_param a_config['method'] = method logging.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) except Exception as e: if not ipv6_ok: shell.print_exception(e) def run_server(): def child_handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') list(map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1) if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) os.waitpid(pid, 0) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGINT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()
def main(): utils.check_python() config = utils.get_config(False) utils.print_shadowsocks() if config['port_password']: if config['password']: logging.warn('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: config['port_password'] = {} server_port = config['server_port'] if type(server_port) == list: for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: config['port_password'][str(server_port)] = config['password'] encrypt.try_cipher(config['password'], config['method']) tcp_servers = [] udp_servers = [] dns_resolver = asyncdns.DNSResolver() for port, password in config['port_password'].items(): a_config = config.copy() a_config['server_port'] = int(port) a_config['password'] = password logging.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) def run_server(): def child_handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') list( map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) try: loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) loop.run() except (KeyboardInterrupt, IOError, OSError) as e: logging.error(e) if config['verbose']: import traceback traceback.print_exc() os._exit(1) if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()
def main(): utils.check_python() # is_local=false config = utils.get_config(False) daemon.daemon_exec(config) utils.print_shadowsocks() # 支持多客户端 if config['port_password']: if config['password']: logging.warn('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: config['port_password'] = {} server_port = config['server_port'] # 若发现有多用户配置:采用‘端口->密码’的映射方式。 if type(server_port) == list: for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: config['port_password'][str(server_port)] = config['password'] # Create an instance of the cipher class encrypt.try_cipher(config['password'], config['method']) tcp_servers = [] udp_servers = [] dns_resolver = asyncdns.DNSResolver() # 一个服务器端可以打开多个端口 # 对于每个端口,都要新建一个对应的处理器 for port, password in config['port_password'].items(): a_config = config.copy() a_config['server_port'] = int(port) a_config['password'] = password logging.info("starting server at %s:%d" % (a_config['server'], int(port))) # 逐一加到tcp、udp列表 tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) def run_server(): # 收到退出信号的处理函数,关闭所有socket释放资源。 def child_handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') # 关闭所有的socket,一句话搞定,好厉害,跪拜ing # map(function, sequence[, sequence, ...]) -> list # Return a list of the results of applying the function to the items of the argument sequence(s). list( map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) # 收到退出信号,调用child_handler进行自杀。 signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) # 收到退出信号,调用int_handler进行自杀。 def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) # 把所有的监听端口添加到时间循环中,一句话搞定,好厉害,跪拜ing list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) loop.run() except (KeyboardInterrupt, IOError, OSError) as e: logging.error(e) if config['verbose']: import traceback traceback.print_exc() os._exit(1) # Shadowsocks supports spawning child processes like nginx. # You can use --workers to specify how many workers to use. # This argument is only supported on Unix and ssserver. # Currently UDP relay does not work well on multiple workers. # 支持像nginx多进程,可以在config中指定worker的数量。仅在linux下生效。 # 目前的bug:worker设为大于1时,udp转发有可能工作不正常 if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) os.waitpid(pid, 0) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGINT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()
def main(): logging.basicConfig( level=logging.DEBUG, format= '%(levelname)-4s:%(filename)s %(lineno)d %(funcName)s %(message)s') logging.info("main exec...") # a = "123456" # b = [] # b.append(a) # # logging.info("a:%s" % a[2:]) # logging.info("b:%s" % type(b)) # # s = utils.encode(b[0]) # logging.info(s) # b = utils.decode(s) # logging.info(b) shell.check_python() config = shell.get_config(False) daemon.daemon_exec(config) if config['port_password']: if config['password']: logging.warn('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: config['port_password'] = {} server_port = config['server_port'] if type(server_port) == list: for a_server_port in server_port: logging.info('a_server_port:%s' % str(a_server_port)) config['port_password'][a_server_port] = config['password'] else: logging.info('server_port:%s' % str(server_port)) config['port_password'][str(server_port)] = config['password'] if config.get('manager_address', 0): logging.info('entering manager mode') manager.run(config) return tcp_servers = [] udp_servers = [] if 'dns_server' in config: # allow override settings in resolv.conf logging.info("dns_server in config") dns_resolver = asyncdns.DNSResolver(config['dns_server'], config['prefer_ipv6']) else: logging.info("dns_server not in config") dns_resolver = asyncdns.DNSResolver(prefer_ipv6=config['prefer_ipv6']) port_password = config['port_password'] logging.info("port_password:%s" % str(port_password)) del config['port_password'] for port, password in port_password.items(): a_config = config.copy() a_config['server_port'] = int(port) a_config['password'] = password logging.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) logging.info('config type:' + str(type(config))) def run_server(): logging.info("run_server enters") def child_handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') list( map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1) if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True logging.info("run_server enters - 3") run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) os.waitpid(pid, 0) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGINT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') logging.info("call run_server - 1") run_server() else: logging.info("call run_server enters - 2") run_server()