def __init__(self, loop, dns_resolver): super(HttpApiThread, self).__init__() self.loop = loop self.config = shell.get_config(False) self.dns_resolver = dns_resolver self.tcp_servers_pool = {} self.udp_servers_pool = {}
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 __init__(self): shell.check_python() self.config = shell.get_config(False) self.dns_resolver = asyncdns.DNSResolver() if not self.config.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False self.mgr = None # asyncmgr.ServerMgr() self.tcp_servers_pool = {} self.tcp_ipv6_servers_pool = {} self.udp_servers_pool = {} self.udp_ipv6_servers_pool = {} self.stat_counter = {} self.loop = eventloop.EventLoop() self.logger = logging.getLogger(__name__) if get_config().debug: self.logger.setLevel(logging.DEBUG) fh = logging.FileHandler('log.txt', mode='a', encoding=None, delay=False) formater = logging.Formatter( '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s' ) fh.setFormatter(formater) self.logger.addHandler(fh) self.thread = MainThread((self.loop, self.dns_resolver, self.mgr)) self.thread.start()
def __init__(self): shell.check_python() self.config = shell.get_config(False) self.dns_resolver = asyncdns.DNSResolver() if not self.config.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False self.mgr = None # asyncmgr.ServerMgr() self.eventloop_pool = {} self.thread_pool = {} self.dns_resolver_pool = {} self.dns_resolver = asyncdns.DNSResolver() self.loop = eventloop.EventLoop() self.thread = MainThread((self.loop, self.dns_resolver, self.mgr)) self.thread.start() self.tcp_servers_pool = {} self.tcp_ipv6_servers_pool = {} self.udp_servers_pool = {} self.udp_ipv6_servers_pool = {} self.stat_counter = {} self.uid_port_table = {}
def thread_db(): ''' :param obj: 就是DbTransfer 线程的入口函数 ''' logging.debug('thread_db') import socket global db_instance timeout = 60 socket.setdefaulttimeout(timeout) last_rows = [] db_instance = DbTransfer() ServerPool.get_instance() shell.log_shadowsocks_version() try: import resource logging.info( 'current process RLIMIT_NOFILE resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) except: pass rows = db_instance.pull_db_all_user() try: while True: load_config() try: db_instance.push_db_all_user() rows = db_instance.pull_db_all_user() if rows: db_instance.pull_ok = True config = shell.get_config(False) for port in config['additional_ports']: val = config['additional_ports'][port] val['port'] = int(port) val['enable'] = 1 val['transfer_enable'] = 1024**7 val['u'] = 0 val['d'] = 0 if "password" in val: val["passwd"] = val["password"] rows.append(val) db_instance.del_server_out_of_bound_safe(last_rows, rows) last_rows = rows except Exception as e: trace = traceback.format_exc() logging.error(trace) # self.logger.warn('db thread except:%s' % e) if db_instance.event.wait( get_config().UPDATE_TIME ) or not ServerPool.get_instance().thread.is_alive(): break except KeyboardInterrupt as e: pass db_instance.del_servers() ServerPool.get_instance().stop() db_instance = None
def main(): shell.check_python() config = shell.get_config(False) daemon.daemon_exec(config) daemon.set_user(config.get('user', None)) thread.start_new_thread(db_transfer.DbTransfer.thread_db, ()) while True: time.sleep(99999)
class cfgjson(): _config = shell.get_config(True) def __int__(self): self._config = shell.get_config(True) def printcfg(self): print(str(self._config))
def __init__(self): shell.check_python() self.config = shell.get_config(False) self.dns_resolver = asyncdns.DNSResolver() self.tcp_servers_pool = {} self.udp_servers_pool = {} self.loop = eventloop.EventLoop() self.thread = MainThread((self.loop, self.dns_resolver)) self.thread.start()
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(): 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) 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, stat_callback=stat_handler) a_config = config.copy() if a_config.get('port_password', None): a_config['server_port'] = random.choice( a_config['port_password'].keys()) a_config['password'] = a_config['port_password']\ [a_config['server_port']] udp_server = udprelay.UDPRelay(a_config, dns_resolver, True, stat_callback=stat_handler) 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)) t = threading.Thread(target=monitor, args=(), name='monitor') t.daemon = True t.start() loop.run() except Exception as e: shell.print_exception(e) sys.exit(1)
def push_all_port_and_connect(self): config = shell.get_config(False) keys = ['node_id', 'port', 'type', 'ip'] tcp_poll = None udp_poll = None if 'server_ipv6' in config: tcp_poll = ServerPool.get_instance().tcp_ipv6_servers_pool udp_poll = ServerPool.get_instance().udp_ipv6_servers_pool else: tcp_poll = ServerPool.get_instance().tcp_servers_pool udp_poll = ServerPool.get_instance().udp_servers_pool # 结果集 result = [] for (k, v) in tcp_poll.items(): if len(v['one_minute_ips']) > 0: result.append({ 'node': self.cfg['node_id'], 'port': k, 'type': 'tcp', 'ip': ','.join([ from_map_ipv6_get_ipv4(x) for x in v['one_minute_ips'] ]), 'created_at': time.time() }) for (k, v) in udp_poll.items(): if len(v['one_minute_ips']) > 0: result.append({ 'node': self.cfg['node_id'], 'port': k, 'type': 'udp', 'ip': ','.join([ from_map_ipv6_get_ipv4(x) for x in v['one_minute_ips'] ]), 'created_at': time.time() }) # 如果结果集不为空则更新数据库 if len(result) > 0: with database.atomic(): SsNodeIp.insert_many(result).execute() logging.info( "push all user one minute connections finished")
def __init__(self): shell.check_python() self.config = shell.get_config(False) shell.print_shadowsocks() self.dns_resolver = asyncdns.DNSResolver() self.mgr = asyncmgr.ServerMgr() self.tcp_servers_pool = {} self.tcp_ipv6_servers_pool = {} self.udp_servers_pool = {} self.udp_ipv6_servers_pool = {} self.loop = eventloop.EventLoop() thread.start_new_thread(ServerPool._loop, (self.loop, self.dns_resolver, self.mgr))
def thread_db(obj): import socket import time global db_instance timeout = 60 socket.setdefaulttimeout(timeout) last_rows = [] db_instance = obj() ServerPool.get_instance() shell.log_shadowsocks_version() try: import resource logging.info('current process RLIMIT_NOFILE resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) except: pass try: while True: load_config() db_instance.load_cfg() try: db_instance.push_db_all_user() rows = db_instance.pull_db_all_user() if rows: db_instance.pull_ok = True config = shell.get_config(False) for port in config['additional_ports']: val = config['additional_ports'][port] val['port'] = int(port) val['enable'] = 1 val['transfer_enable'] = 1024 ** 7 val['u'] = 0 val['d'] = 0 if "password" in val: val["passwd"] = val["password"] rows.append(val) db_instance.del_server_out_of_bound_safe(last_rows, rows) last_rows = rows except Exception as e: trace = traceback.format_exc() logging.error(trace) #logging.warn('db thread except:%s' % e) if db_instance.event.wait(get_config().UPDATE_TIME) or not ServerPool.get_instance().thread.is_alive(): break except KeyboardInterrupt as e: pass db_instance.del_servers() ServerPool.get_instance().stop() db_instance = None
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 main(): # 检查当前的运行环境 是否支持, 如果不支持, sys.exit(1) 退出 shell.check_python() config = shell.get_config(True) # deamon.deamon_exec(config) logging.info('start local at %s:%d' % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver) loop = eventloop.EventLoop() tcp_server.add_to_loop(loop) loop.run()
def main(): shadowsocks_shell.check_python() config = shadowsocks_shell.get_config(True) logging.info("starting dns at %s:%d" % (config['local_address'], 53)) config['dns'] = config.get('dns', '8.8.8.8') loop = eventloop.EventLoop() udprelay = UDPDNSRelay(config) udprelay.add_to_loop(loop) tcprelay = TCPDNSRelay(config) tcprelay.add_to_loop(loop) loop.run()
def main(): shell.check_python() config = shell.get_config(True) logging.info("starting dns at %s:%d" % (config['local_address'], config.get('local_port', 53))) config['dns'] = config.get('dns', '8.8.8.8') loop = eventloop.EventLoop() udprelay = UDPDNSRelay(config) udprelay.add_to_loop(loop) tcprelay = TCPDNSRelay(config) tcprelay.add_to_loop(loop) loop.run()
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) if not config.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False 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_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 __init__(self): shell.check_python() self.config = shell.get_config(False) self.dns_resolver = asyncdns.DNSResolver() if not self.config.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False self.mgr = None #asyncmgr.ServerMgr() self.tcp_servers_pool = {} self.tcp_ipv6_servers_pool = {} self.udp_servers_pool = {} self.udp_ipv6_servers_pool = {} self.stat_counter = {} self.loop = eventloop.EventLoop() self.thread = MainThread( (self.loop, self.dns_resolver, self.mgr) ) self.thread.start()
def main(): shell.check_python() config = shell.get_config() daemon.daemon_exec(config) tcp_servers = [] udp_servers = [] dns_resolver = asyncdns.DNSResolver() a_config = config.copy() logging.info("starting bridge at %s:%d" % (a_config['local'], int(a_config['local_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) #add tcp_servers into event loop,when a call is in,it will be invoked. 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(): # 检查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) 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) # 注册信号事件,用于结束 local 程序 signal.signal(getattr(signal, "SIGQUIT", signal.SIGTERM), handler) def int_handler(signum, _): sys.exit(1) # SIGINT external interrupt, usually initiated by the user 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(): # 检查 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_server(): config = shell.get_config(True) config = config.copy() a_config = { 'server': '127.0.0.1', 'local_port': 1081, 'port_password': { '8381': 'foobar1', '8382': 'foobar2' }, 'method': 'aes-256-cfb', 'manager_address': '127.0.0.1:6001', 'timeout': 60, 'fast_open': False, 'verbose': 2 } config.update(a_config) manager = Manager(config) enc.append(manager) manager.run()
def main(): shell.check_python() config = shell.get_config(False) if False: db_transfer.DbTransfer.thread_db() else: if config['API_INTERFACE'] == 'mudbjson': thread = MainThread(db_transfer.MuJsonTransfer) elif config['API_INTERFACE'] == 'sspanelv4': thread = MainThread(db_transfer.DbTransfer) else: thread = MainThread(db_transfer.Dbv3Transfer) thread.start() try: while thread.is_alive(): thread.join(10.0) except (KeyboardInterrupt, IOError, OSError) as e: import traceback traceback.print_exc() thread.stop()
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版本 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 __init__(self): super(MuJsonTransfer, self).__init__() config = shell.get_config(False)
def del_server_out_of_bound_safe(self, last_rows, rows): #停止超流量的服务 #启动没超流量的服务 try: switchrule = importloader.load('switchrule') except Exception as e: logging.error('load switchrule.py fail') cur_servers = {} new_servers = {} allow_users = {} mu_servers = {} config = shell.get_config(False) for row in rows: try: allow = switchrule.isTurnOn(row) and row['enable'] == 1 and row['u'] + row['d'] < row['transfer_enable'] except Exception as e: allow = False port = row['port'] passwd = common.to_bytes(row['passwd']) if hasattr(passwd, 'encode'): passwd = passwd.encode('utf-8') cfg = {'password': passwd} if 'id' in row: self.port_uid_table[row['port']] = row['id'] read_config_keys = ['method', 'obfs', 'obfs_param', 'protocol', 'protocol_param', 'forbidden_ip', 'forbidden_port', 'speed_limit_per_con', 'speed_limit_per_user'] for name in read_config_keys: if name in row and row[name]: cfg[name] = row[name] merge_config_keys = ['password'] + read_config_keys for name in cfg.keys(): if hasattr(cfg[name], 'encode'): try: cfg[name] = cfg[name].encode('utf-8') except Exception as e: logging.warning('encode cfg key "%s" fail, val "%s"' % (name, cfg[name])) if port not in cur_servers: cur_servers[port] = passwd else: logging.error('more than one user use the same port [%s]' % (port,)) continue if 'protocol' in cfg and 'protocol_param' in cfg and common.to_str(cfg['protocol']) in obfs.mu_protocol(): if '#' in common.to_str(cfg['protocol_param']): mu_servers[port] = passwd allow = True if allow: if port not in mu_servers: allow_users[port] = cfg cfgchange = False if port in ServerPool.get_instance().tcp_servers_pool: relay = ServerPool.get_instance().tcp_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp(cfg[name], relay._config[name]): cfgchange = True break if not cfgchange and port in ServerPool.get_instance().tcp_ipv6_servers_pool: relay = ServerPool.get_instance().tcp_ipv6_servers_pool[port] for name in merge_config_keys: if (name in cfg) and ((name not in relay._config) or not self.cmp(cfg[name], relay._config[name])): cfgchange = True break if port in mu_servers: if ServerPool.get_instance().server_is_run(port) > 0: if cfgchange: logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) new_servers[port] = (passwd, cfg) else: self.new_server(port, passwd, cfg) else: if ServerPool.get_instance().server_is_run(port) > 0: if config['additional_ports_only'] or not allow: logging.info('db stop server at port [%s]' % (port,)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) else: if cfgchange: logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) new_servers[port] = (passwd, cfg) elif not config['additional_ports_only'] and allow and port > 0 and port < 65536 and ServerPool.get_instance().server_run_status(port) is False: self.new_server(port, passwd, cfg) for row in last_rows: if row['port'] in cur_servers: pass else: logging.info('db stop server at port [%s] reason: port not exist' % (row['port'])) ServerPool.get_instance().cb_del_server(row['port']) self.clear_cache(row['port']) if row['port'] in self.port_uid_table: del self.port_uid_table[row['port']] if len(new_servers) > 0: from shadowsocks import eventloop self.event.wait(eventloop.TIMEOUT_PRECISION + eventloop.TIMEOUT_PRECISION / 2) for port in new_servers.keys(): passwd, cfg = new_servers[port] self.new_server(port, passwd, cfg) logging.debug('db allow users %s \nmu_servers %s' % (allow_users, mu_servers)) for port in mu_servers: ServerPool.get_instance().update_mu_users(port, allow_users) self.mu_ports = mu_servers
def del_server_out_of_bound_safe(self, last_rows, rows): #停止超流量的服务 #启动没超流量的服务 keymap = {} try: switchrule = importloader.load('switchrule') keymap = switchrule.getRowMap() except Exception as e: logging.error('load switchrule.py fail') cur_servers = {} new_servers = {} allow_users = {} mu_servers = {} config = shell.get_config(False) for row in rows: try: allow = switchrule.isTurnOn(row) and row['enable'] == 1 and row['u'] + row['d'] < row['transfer_enable'] except Exception as e: allow = False port = row['port'] passwd = common.to_bytes(row['passwd']) if hasattr(passwd, 'encode'): passwd = passwd.encode('utf-8') cfg = {'password': passwd} if 'id' in row: self.port_uid_table[row['port']] = row['id'] read_config_keys = ['method', 'obfs', 'obfs_param', 'protocol', 'protocol_param', 'forbidden_ip', 'forbidden_port', 'speed_limit_per_con', 'speed_limit_per_user'] for name in read_config_keys: if name in row and row[name]: if name in keymap: cfg[keymap[name]] = row[name] else: cfg[name] = row[name] merge_config_keys = ['password'] + read_config_keys for name in cfg.keys(): if hasattr(cfg[name], 'encode'): try: cfg[name] = cfg[name].encode('utf-8') except Exception as e: logging.warning('encode cfg key "%s" fail, val "%s"' % (name, cfg[name])) if port not in cur_servers: cur_servers[port] = passwd else: logging.error('more than one user use the same port [%s]' % (port,)) continue if 'protocol' in cfg and 'protocol_param' in cfg and common.to_str(cfg['protocol']) in obfs.mu_protocol(): if '#' in common.to_str(cfg['protocol_param']): mu_servers[port] = passwd allow = True if allow: if port not in mu_servers: allow_users[port] = cfg cfgchange = False if port in ServerPool.get_instance().tcp_servers_pool: relay = ServerPool.get_instance().tcp_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp(cfg[name], relay._config[name]): cfgchange = True break if not cfgchange and port in ServerPool.get_instance().tcp_ipv6_servers_pool: relay = ServerPool.get_instance().tcp_ipv6_servers_pool[port] for name in merge_config_keys: if (name in cfg) and ((name not in relay._config) or not self.cmp(cfg[name], relay._config[name])): cfgchange = True break if port in mu_servers: if ServerPool.get_instance().server_is_run(port) > 0: if cfgchange: logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) new_servers[port] = (passwd, cfg) else: self.new_server(port, passwd, cfg) else: if ServerPool.get_instance().server_is_run(port) > 0: if config['additional_ports_only'] or not allow: logging.info('db stop server at port [%s]' % (port,)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) else: if cfgchange: logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) ServerPool.get_instance().cb_del_server(port) self.force_update_transfer.add(port) new_servers[port] = (passwd, cfg) elif not config['additional_ports_only'] and allow and port > 0 and port < 65536 and ServerPool.get_instance().server_run_status(port) is False: self.new_server(port, passwd, cfg) for row in last_rows: if row['port'] in cur_servers: pass else: logging.info('db stop server at port [%s] reason: port not exist' % (row['port'])) ServerPool.get_instance().cb_del_server(row['port']) self.clear_cache(row['port']) if row['port'] in self.port_uid_table: del self.port_uid_table[row['port']] if len(new_servers) > 0: from shadowsocks import eventloop self.event.wait(eventloop.TIMEOUT_PRECISION + eventloop.TIMEOUT_PRECISION / 2) for port in new_servers.keys(): passwd, cfg = new_servers[port] self.new_server(port, passwd, cfg) logging.debug('db allow users %s \nmu_servers %s' % (allow_users, mu_servers)) for port in mu_servers: ServerPool.get_instance().update_mu_users(port, allow_users) self.mu_ports = mu_servers
def main(): shell.check_python() 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 = password_obfs[1] if len(password_obfs) > 2: protocol = password_obfs[2] elif type(password_obfs) == dict: password = password_obfs.get('password', config_password) method = password_obfs.get('method', method) protocol = password_obfs.get('protocol', protocol) protocol_param = password_obfs.get('protocol_param', protocol_param) obfs = password_obfs.get('obfs', obfs) obfs_param = password_obfs.get('obfs_param', obfs_param) bind = password_obfs.get('bind', bind) bindv6 = password_obfs.get('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, 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_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 __int__(self): self._config = shell.get_config(True)
def main(): shell.check_python() # 读取配置信息,False 表示这里是服务端运行 config = shell.get_config(False) # TODO 临时打印配置信息 print(config) """ 默认配置信息 { 'log-file': '/var/log/shadowsocks.log', 'verbose': False, 'local_port': 1080, 'workers': 1, 'fast_open': False, 'forbidden_ip': <shadowsocks.common.IPNetwork object at 0x10f4f8a10>, 'server': '0.0.0.0', 'port_password': None, 'server_port': None, 'timeout': 300, 'local_address': '127.0.0.1', 'pid-file': '/var/run/shadowsocks.pid', 'password': '', 必填 'method': 'aes-256-cfb' } """ # 根据配置对守护进程进行操作,不开启 daemon 时此处可忽略 daemon.daemon_exec(config) """ port_password 为一个字典,每个端口有不同的密码,用于多用户登录 "port_password": { "8381": "foobar1", "8382": "foobar2", } """ 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'] = {} # TODO 待确认 # 此处应为 server_port = config.get('server_port', 8388) 以允许默认端口启动 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'] print(config) # 如果获取到 manager_address,则启动管理进程 if config.get('manager_address', 0): logging.info('entering manager mode') manager.run(config) return tcp_servers = [] udp_servers = [] # 如果设置了 dns 服务器 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 时,也会退化到使用 port_password,此时 port_password 为单元素列表 port_password = config['port_password'] # 后面用 port_password 中每一项分别生成一份配置,所以 config['port_password'] 就用不着了 del config['port_password'] # 循环每一对端口和密码 for port, password in port_password.items(): # dict.copy() 创建了一个新的字典对象,内容一样 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 的 Relay 实例 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)) """ getattr(object, name[, default]) 如果 siganl.SIGQUIT 不存在,即注册 SIGTERM 事件 SIGTERM 终止进程,但终止前会允许 handler 被执行,SIGKILL 不会 SIGQUIT 在 SIGTERM 的基础上,还生成了一份 core dump 文件记录了进程信息 http://programmergamer.blogspot.jp/2013/05/clarification-on-sigint-sigterm-sigkill.html """ 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 解析器到事件循环中 dns_resolver.add_to_loop(loop) # 批量地将所有 tcp_server 和 udp_server 加入事件循环中 list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) # 使守护进程以设置中 user 的名义执行 daemon.set_user(config.get('user', None)) # 启动事件循环 loop.run() except Exception as e: shell.print_exception(e) sys.exit(1) # 如果 workers 为 1 则直接启动 server,否则进行 fork() if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(config['workers'])): r = os.fork() # 如果执行这段代码的进程为子进程,输出启动信息,然后运行 run_server() if r == 0: logging.info('worker started') is_child = True run_server() break else: # 如果为父进程,添加到 pid 到子进程列表中 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() # 当收到中断或者终止信号时,向每个子进程 pid 发出终止信号 signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGINT, handler) # master # 关闭所有 tcp_server,udp_server 和 dns 解析器 # close 方法从 eventloop 中移除了每个注册的事件 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: # TODO 待测试 # 等待子进程结束,当子进程结束时返回 os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()
from __future__ import absolute_import, division, print_function, \ with_statement import sys import os import time import logging import signal import json sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../')) from shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, \ asyncdns, manager, agent shell.check_python() config = shell.get_config(False) daemon.daemon_exec(config) agent_ = agent.Agent(config) worker_id = 0 workers = 1 tcp_servers = [] udp_servers = [] dns_resolver = 0 #load server config def init_config(): global tcp_servers, udp_servers, dns_resolver, workers, worker_id tcp_servers = [] udp_servers = []
def main(): """ 启动服务器主函数 :return: None """ 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: # 给每个port赋password for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: # 只有1个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 = [] 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(): """ 服务器运行 :return: None """ def child_handler(signum, _): """ 子程序要求关闭 :param signum: 信号值 :param _: 不明 :return: None """ 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, _): """ 强制退出程序,意义不明 :param signum: 信号值 :param _: 不明 :return: None """ sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() # 用addtoloop把dnsresolver添加到eventloop里,当DNSResolver对应的socket有dns解析结果可以读取的时候,eventloop会自动调用其handle_event方法将就绪的socket递给DNSResolver,DNSResolver就可以从其中读取dns应答数据了。 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) # workers<=1时开启服务器,>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, _): """ 关闭所有子进程 :param signum: 信号值 :param _: 不明 :return: None :raises OSError: 子进程已经退出 """ 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) # 关闭所有服务器 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 del_server_out_of_bound_safe(self, last_rows, rows): cur_servers = {} #记录每次读取配置的所有有效端口服务,port=>passwd new_servers = {} #记录每次读取配置后需要新启动的端口,port=>(passwd,cfg) config = shell.get_config(False) for row in rows: #超流判断 allow = row['u'] + row['d'] < row['quota'] port = row['port'] #转换密码编码为utf-8编码 passwd = common.to_bytes(row['passwd']) if hasattr(passwd, 'encode'): passwd = passwd.encode('utf-8') cfg = {'password': passwd} #把端口参数存入cfg read_config_keys = ['method', 'obfs', 'obfs_param', 'protocol', 'protocol_param', 'speed_limit_per_user'] for name in read_config_keys: if name in row and row[name]: cfg[name] = row[name] merge_config_keys = ['password'] + read_config_keys #转换端口参数值为utf-8编码 for name in cfg.keys(): if hasattr(cfg[name], 'encode'): try: cfg[name] = cfg[name].encode('utf-8') except Exception as e: logging.warning('encode cfg key "%s" fail, val "%s"' % (name, cfg[name])) #有多个用户使用相同的端口 if port not in cur_servers: cur_servers[port] = passwd else: logging.error('端口冲突: [%s]' %(port)) continue #如果当前端口允许运行 if allow: cfgchange = False #检查端口参数变更 if port in ServerPool.get_instance().tcp_servers_pool: relay = ServerPool.get_instance().tcp_servers_pool[port] for name in merge_config_keys: if name in cfg and not self.cmp(cfg[name], relay._config[name]): cfgchange = True break #停止需要重启的端口服务,并把端口参数放入new_servers if ServerPool.get_instance().server_is_run(port) > 0: if cfgchange: self.force_update_transfer[port] = ServerPool.get_instance().get_server_transfer(port) ServerPool.get_instance().cb_del_server(port) new_servers[port] = (passwd, cfg) #新增的端口服务放入new_server elif allow and port > 0 and port < 65536 and ServerPool.get_instance().server_run_status(port) is False: self.new_server(port, passwd, cfg) #关闭需要停止服务的端口 for row in last_rows: if row['port'] not in cur_servers: self.force_update_transfer[row['port']] = ServerPool.get_instance().get_server_transfer(row['port']) ServerPool.get_instance().cb_del_server(row['port']) #启动新增的端口服务和需要重启的端口服务 if len(new_servers) > 0: from shadowsocks import eventloop self.event.wait(eventloop.TIMEOUT_PRECISION + eventloop.TIMEOUT_PRECISION / 2) for port in new_servers.keys(): passwd, cfg = new_servers[port] self.new_server(port, passwd, cfg)
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()
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 load_muconfig(self): muconfig = shell.get_config(False) if muconfig: self.muconfig.update(muconfig)
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_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'] if config.get('manager_address', 0): logging.info('entering manager mode') manager.run(config) return tcp_servers = [] udp_servers = [] # 创建一个dns解析对象 if 'dns_server' in config: # allow override settings in resolv.conf dns_resolver = asyncdns.DNSResolver(config['dns_server'], config['prefer_ipv6']) else: dns_resolver = asyncdns.DNSResolver(prefer_ipv6=config['prefer_ipv6']) # 一个服务器端可以打开多个端口 # 对于每个端口,都要新建一个对应的处理器 # 同时从配置文件中删除对应的配置 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、udp列表 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..') # 关闭所有的socket,lambda表达式一句话搞定 # 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)) 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) # 把所有的监听端口添加到事件循环loop中,lambda表达式一句话搞定 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) # 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(): shell.check_python() # 读取 config = shell.get_config(False) # TODO 临时打印配置信息 print(config) # 根据配置对守护进程进行操作,不开启 daemon 时此处可忽略 daemon.daemon_exec(config) """ port_password 为一个字典,每个端口有不同的密码,用于多用户登录 "port_password": { "8381": "foobar1", "8382": "foobar2", } """ 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'] # TODO 如果获取到 manager_address,则启动管理进程,先跳过不看 if config.get('manager_address', 0): logging.info('entering manager mode') manager.run(config) return tcp_servers = [] udp_servers = [] # 如果设置了 dns 服务器 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 时,也会退化到使用 port_password,此时 port_password 为单元素列表 port_password = config['port_password'] # TODO 为什么要删除 del config['port_password'] # 循环每一对端口和密码 for port, password in port_password.items(): # dict.copy() 创建了一个新的字典对象,内容一样 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) # 如果 workers 为 1 则直接启动 server,否则进行 fork() 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 load_cfg(self): cfg = shell.get_config(False) if cfg: self.cfg.update(cfg)
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) logging.warn('!' * 30) if config.has_key('server_info'): if config['server_info'].has_key(config['server']): logging.info( "OK.. [ (ip: %s) (server_port: %s) (password: %s) (server_info: %s) (method: %s) ]" % (config['server'], config['server_port'], config['password'], config['server_info']["%s" % config['server']], config['method'])) else: logging.info( "OK.. [ (ip: %s) (server_port: %s) (password: %s) (method: %s) ]" % (config['server'], config['server_port'], config['password'], config['method'])) else: logging.info( "OK.. [ (ip: %s) (server_port: %s) (password: %s) (method: %s) ]" % (config['server'], config['server_port'], config['password'], config['method'])) logging.warn('!' * 30) time.sleep(1) daemon.daemon_exec(config) try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver(config) tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop(config) 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 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()