def get_host_from_http_header(self, buf): ret_buf = b'' lines = buf.split(b'\r\n') if lines and len(lines) > 1: for line in lines: if match_begin(line, b"Host: "): return common.to_str(line[6:])
def write_pid_file(pid_file, pid): import fcntl import stat try: fd = os.open(pid_file, os.O_RDWR | os.O_CREAT, stat.S_IRUSR | stat.S_IWUSR) except OSError as e: shell.print_exception(e) return -1 flags = fcntl.fcntl(fd, fcntl.F_GETFD) assert flags != -1 flags |= fcntl.FD_CLOEXEC r = fcntl.fcntl(fd, fcntl.F_SETFD, flags) assert r != -1 # TODO: use kill(0) for the pid in pid_file if the file exists # There is no platform independent way to implement fcntl(fd, F_SETLK, &fl) # via fcntl.fcntl. So use lockf instead try: fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB, 0, 0, os.SEEK_SET) except IOError: r = os.read(fd, 32) if r: logging.error('already started at pid %s' % common.to_str(r)) else: logging.error('already started') os.close(fd) return -1 os.ftruncate(fd, 0) os.write(fd, common.to_bytes(str(pid))) return 0
def __init__(self, method): method = common.to_str(method) self.method = method self._method_info = self.get_method_info(method) if self._method_info: self.obfs = self.get_obfs(method) else: raise Exception('obfs plugin [%s] not supported' % method)
def push(self, ch): ch = ord(ch) if self.state == 0: if ch == ord('"'): self.state = 1 return to_str(chr(ch)) elif ch == ord('/'): self.state = 3 else: return to_str(chr(ch)) elif self.state == 1: if ch == ord('"'): self.state = 0 return to_str(chr(ch)) elif ch == ord('\\'): self.state = 2 return to_str(chr(ch)) elif self.state == 2: self.state = 1 if ch == ord('"'): return to_str(chr(ch)) return "\\" + to_str(chr(ch)) elif self.state == 3: if ch == ord('/'): self.state = 4 else: return "/" + to_str(chr(ch)) elif self.state == 4: if ch == ord('\n'): self.state = 0 return "\n" return ""
def base64_decode(string): def adjust_padding(string): """Adjust to base64 format, i.e. len(string) % 4 == 0.""" missing_padding = len(string) % 4 if missing_padding: string += '=' * (4 - missing_padding) return string string = adjust_padding(string.strip()) return common.to_str(base64.urlsafe_b64decode(common.to_bytes(string)))
def _parse_command(self, data): # commands: # add: {"server_port": 8000, "password": "******"} # remove: {"server_port": 8000"} data = common.to_str(data) parts = data.split(':', 1) if len(parts) < 2: return data, None command, config_json = parts try: config = shell.parse_json_in_str(config_json) return command, config except Exception as e: logger.error(e) return None
def check_config(config, is_local): if config.get('daemon', None) == 'stop': # no need to specify configuration for daemon stop return if is_local and not config.get('password', None): logger.error('password not specified') print_help(is_local) sys.exit(2) if not is_local and not config.get('password', None) \ and not config.get('port_password', None): logger.error('password or port_password not specified') print_help(is_local) sys.exit(2) if 'local_port' in config: config['local_port'] = int(config['local_port']) if 'server_port' in config and type(config['server_port']) != list: config['server_port'] = int(config['server_port']) if config.get('local_address', '') in [b'0.0.0.0']: logger.warning( 'warning: local set to listen on 0.0.0.0, it\'s not safe') if config.get('server', '') in ['127.0.0.1', 'localhost']: logger.warning( 'warning: server set to listen on %s:%s, are you sure?' % (to_str(config['server']), config['server_port'])) if config.get('timeout', 300) < 100: logger.warning('warning: your timeout %d seems too short' % int(config.get('timeout'))) if config.get('timeout', 300) > 600: logger.warning('warning: your timeout %d seems too long' % int(config.get('timeout'))) if config.get('password') in [b'mypassword']: logger.error('DON\'T USE DEFAULT PASSWORD! Please change it in your ' 'config.json!') sys.exit(1) if config.get('user', None) is not None: if os.name != 'posix': logger.error('user can be used only on Unix') sys.exit(1) encrypt.try_cipher(config['password'], config['method'])
def daemon_stop(pid_file=_default_pid_file): try: with open(pid_file) as f: buf = f.read() pid = common.to_str(buf) if not buf: logging.error('not running') except IOError as e: shell.print_exception(e) if e.errno == errno.ENOENT: # always exit 0 if we are sure daemon is not running logging.error('not running') return sys.exit(1) pid = int(pid) if pid > 0: try: os.kill(pid, signal.SIGTERM) except OSError as e: if e.errno == errno.ESRCH: logging.error('not running') # always exit 0 if we are sure daemon is not running return shell.print_exception(e) sys.exit(1) else: logging.error('pid is not positive: %d', pid) # sleep for maximum 10s for i in range(0, 200): try: # query for the pid os.kill(pid, 0) except OSError as e: if e.errno == errno.ESRCH: break time.sleep(0.05) else: logging.error('timed out when stopping pid %d', pid) sys.exit(1) print('stopped') os.unlink(pid_file)
def __init__(self, config): self._config = config self._relays = {} # (tcprelay, udprelay) self._loop = eventloop.EventLoop() self._dns_resolver = asyncdns.DNSResolver() self._dns_resolver.add_to_loop(self._loop) self._statistics = collections.defaultdict(int) self._control_client_addr = None try: manager_address = common.to_str(config['manager_address']) if ':' in manager_address: addr = manager_address.rsplit(':', 1) addr = addr[0], int(addr[1]) addrs = socket.getaddrinfo(addr[0], addr[1]) if addrs: family = addrs[0][0] else: logger.error('invalid address: %s', manager_address) exit(1) else: addr = manager_address family = socket.AF_UNIX self._control_socket = socket.socket(family, socket.SOCK_DGRAM) self._control_socket.bind(addr) self._control_socket.setblocking(False) except (OSError, IOError) as e: logger.error(e) logger.error('can not bind to manager address') exit(1) self._loop.add(self._control_socket, eventloop.POLL_IN, self) self._loop.add_periodic(self.handle_periodic) 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 self.add_port(a_config)
def main(): shell.check_python() shell.parse_args() config = shell.parse_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 test(): import time import threading import struct from shadowsocks.core import encrypt logging.basicConfig(level=5, format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S') enc = [] eventloop.TIMEOUT_PRECISION = 1 def run_server(): shell.parse_args() config = shell.parse_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() t = threading.Thread(target=run_server) t.start() time.sleep(1) manager = enc[0] cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) cli.connect(('127.0.0.1', 6001)) # test add and remove time.sleep(1) cli.send(b'add: {"server_port":7001, "password":"******"}') time.sleep(1) assert 7001 in manager._relays data, addr = cli.recvfrom(1506) assert b'ok' in data cli.send(b'remove: {"server_port":8381}') time.sleep(1) assert 8381 not in manager._relays data, addr = cli.recvfrom(1506) assert b'ok' in data logger.info('add and remove test passed') # test statistics for TCP header = common.pack_addr(b'google.com') + struct.pack('>H', 80) data = encrypt.encrypt_all(b'asdfadsfasdf', 'aes-256-cfb', 1, header + b'GET /\r\n\r\n') tcp_cli = socket.socket() tcp_cli.connect(('127.0.0.1', 7001)) tcp_cli.send(data) tcp_cli.recv(4096) tcp_cli.close() data, addr = cli.recvfrom(1506) data = common.to_str(data) assert data.startswith('stat: ') data = data.split('stat:')[1] stats = shell.parse_json_in_str(data) assert '7001' in stats logger.info('TCP statistics test passed') # test statistics for UDP header = common.pack_addr(b'127.0.0.1') + struct.pack('>H', 80) data = encrypt.encrypt_all(b'foobar2', 'aes-256-cfb', 1, header + b'test') udp_cli = socket.socket(type=socket.SOCK_DGRAM) udp_cli.sendto(data, ('127.0.0.1', 8382)) tcp_cli.close() data, addr = cli.recvfrom(1506) data = common.to_str(data) assert data.startswith('stat: ') data = data.split('stat:')[1] stats = json.loads(data) assert '8382' in stats logger.info('UDP statistics test passed') manager._loop.stop() t.join()
def _handle_server_dns_resolved(self, error, remote_addr, server_addr, params): if error: return data, r_addr, uid, header_length = params user_id = self._listen_port try: server_port = remote_addr[1] addrs = socket.getaddrinfo(server_addr, server_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP) if not addrs: # drop return af, socktype, proto, canonname, sa = addrs[0] server_addr = sa[0] key = client_key(r_addr, af) client_pair = self._cache.get(key, None) if client_pair is None: client_pair = self._cache_dns_client.get(key, None) if client_pair is None: if self._forbidden_iplist: if common.to_str(sa[0]) in self._forbidden_iplist: logging.debug('IP %s is in forbidden list, drop' % common.to_str(sa[0])) # drop return if self._forbidden_portset: if sa[1] in self._forbidden_portset: logging.debug('Port %d is in forbidden list, reject' % sa[1]) # drop return client = socket.socket(af, socktype, proto) client_uid = uid client.setblocking(False) self._socket_bind_addr(client, af) is_dns = False if len(data) > header_length + 13 and data[ header_length + 4:header_length + 12] == b"\x00\x01\x00\x00\x00\x00\x00\x00": is_dns = True else: pass if sa[1] == 53 and is_dns: #DNS logging.debug("DNS query %s from %s:%d" % (common.to_str(sa[0]), r_addr[0], r_addr[1])) self._cache_dns_client[key] = (client, uid) else: self._cache[key] = (client, uid) self._client_fd_to_server_addr[client.fileno()] = (r_addr, af) self._sockets.add(client.fileno()) self._eventloop.add(client, eventloop.POLL_IN, self) logging.debug('UDP port %5d sockets %d' % (self._listen_port, len(self._sockets))) if uid is not None: user_id = struct.unpack('<I', client_uid)[0] else: client, client_uid = client_pair self._cache.clear(self._udp_cache_size) self._cache_dns_client.clear(16) if self._is_local: ref_iv = [encrypt.encrypt_new_iv(self._method)] self._protocol.obfs.server_info.iv = ref_iv[0] data = self._protocol.client_udp_pre_encrypt(data) #logging.debug("%s" % (binascii.hexlify(data),)) data = encrypt.encrypt_all_iv( self._protocol.obfs.server_info.key, self._method, 1, data, ref_iv) if not data: return else: data = data[header_length:] if not data: return except Exception as e: shell.print_exception(e) logging.error("exception from user %d" % (user_id, )) try: client.sendto(data, (server_addr, server_port)) self.add_transfer_u(client_uid, len(data)) if client_pair is None: # new request addr, port = client.getsockname()[:2] common.connect_log( 'UDP data to %s(%s):%d from %s:%d by user %d' % (common.to_str(remote_addr[0]), common.to_str(server_addr), server_port, addr, port, user_id)) except IOError as e: err = eventloop.errno_from_exception(e) logging.warning('IOError sendto %s:%d by user %d' % (server_addr, server_port, user_id)) if err in (errno.EINPROGRESS, errno.EAGAIN): pass else: shell.print_exception(e)
def base64_encode(string): return common.to_str(base64.urlsafe_b64encode( common.to_bytes(string))).replace('=', '')
def parse_args(args_=None): # FIXME: called twice, service, parse_config def args_error( message): # TODO: print help information when invalid arguments nonlocal parser sys.stderr.write('error: %s\n'.format(message)) print('something wrong') parser.print_help() parser = argparse.ArgumentParser( description='A fast tunnel proxy that helps you bypass firewalls.', usage='ssclient <command> [OPTION]', epilog='Online help: <https://github.com/shadowsocks/shadowsocks>') # TODO: add conflicts of -L with others. # default to old version config path, if args.command is set, change it to new version config path parser.add_argument('-s', metavar='SERVER_ADDR', help='server address') parser.add_argument('-p', metavar='SERVER_PORT', help='server port', default='8388') parser.add_argument('-k', metavar='PASSWORD', help='password') parser.add_argument('-m', metavar='METHOD', help='encryption method', default='aes-256-cfb') parser.add_argument('-O', metavar='PROTOCOL', help='protocol', default='http_simple') parser.add_argument('-G', metavar='PROTOCOL_PARAM', help='protocol param', default='') parser.add_argument('-o', metavar='OBFS', help='obfsplugin', default='http_simple') parser.add_argument('-g', metavar='OBFS_PARAM', help='obfs param', default='') subparsers = parser.add_subparsers(title='command title', dest='command', help='sub-commands', metavar='<command>') server_parser = subparsers.add_parser('server', help='xxx') feed_parser = subparsers.add_parser('feed', help='yyy') status_parser = subparsers.add_parser('status', help='show current status') service_parser = subparsers.add_parser('service', help='service operations') config_parser = subparsers.add_parser('config', help='yyy') server_parser.add_argument('subcmd', help='server command') feed_parser.add_argument('--link', help='ssr link') # TODO: if no link, ask later. feed_parser.add_argument('subcmd', help='subscription command') feed_parser.add_argument('--source', help='souurce address') # status_parser.add_argument('subcmd', help='show current status') service_parser.add_argument('subcmd', help='show current status') config_parser.add_argument('subcmd', help='show current status') # config_parser.add_argument('-c', help='path to the import config file') config_parser.add_argument('-o', help='path to the :xport config file') for p in (parser, server_parser, feed_parser, status_parser, config_parser, service_parser): p.add_argument('-b', metavar='LOCAL_ADDR', help='local address', default='127.0.0.1') p.add_argument('-l', metavar='LOCAL_PORT', help='local port', default='1080') p.add_argument('-i', action='store_true', help='start in interactive mode') p.add_argument('-c', metavar='CONFIG', help='path to config file') p.add_argument('-L', metavar='SSR_LINK', help='connect using ssr link') p.add_argument('-t', metavar='TIMEOUT', help='timeout in seconds', default=300) p.add_argument('--fast-open', action='store_true', help='use TCP_FAST_OPEN, requires Linux 3.7+') # p.add_argument('-d', metavar='', help='daemon mode (start/stop/restart)', choices=['start', 'stop', 'restart']) # TODO: change help message about daemon, we don't need stop/restart option now p.add_argument('-d', action='store_true', help='daemon mode (start/stop/restart)') p.add_argument('--version', help='show version information', action='store_true') p.add_argument('--pid-file', metavar='PID_FILE', help='pid file for daemon mode') p.add_argument('--log-file', metavar='LOG_FILE', help='log file daemon mode') p.add_argument('--user', metavar='USER', help='run as user') p.add_argument('--workers', metavar='WORKERS', default=1) p.add_argument('-v', '-vv', action='count', help='verbose mode', default=0) # TODO: remove quiet mode p.add_argument('-q', '-qq', action='count', help='quiet mode') try: if args_: args, extra_args = parser.parse_known_args(args_) else: args, extra_args = parser.parse_known_args() # except argparse.ArgumentParser as e: # we cannot catch argparse.ArgumentParser since it does not inherit from BaseException, # when errors in args is founded, argparse just raise SystemExit, this is horrible, # we really need to handle the exception to stop daemon from exit. except SystemExit as e: # TODO: add subcommand `help`, and `help` message # args = parser.parse_known_args(['-h'])[0] args = parser.parse_known_args(['feed', 'list'])[0] pass global verbose global config config = {} global config_path config_path = None logging.basicConfig(level=logging.INFO, format='%(levelname)-s: %(message)s') if args.version: print_shadowsocks() # sys.exit(0) if args.c: # FIXME: enable default config_path if args.command: # if args.c == 'default': # config_path = find_config(True) # else: config_path = args.c else: # if args.c == 'default': # config_path = find_config(False) # else: config_path = args.c logger.debug('loading config from %s' % config_path) with open(config_path, 'rb') as f: try: config = parse_json_in_str( remove_comment(f.read().decode('utf8'))) except ValueError as e: logger.error('found an error in config.json: %s', str(e)) sys.exit(1) if config_path: config['config_path'] = config_path else: config['config_path'] = find_config(args.command) if args.p: config['server_port'] = int(args.p) if args.k: config['password'] = to_bytes(args.k) if args.l: config['local_port'] = int(args.l) if args.s: config['server'] = to_str(args.s) if args.m: config['method'] = to_str(args.m) if args.O: config['protocol'] = to_str(args.O) if args.o: config['obfs'] = to_str(args.o) if args.G: config['protocol_param'] = to_str(args.G) if args.g: config['obfs_param'] = to_str(args.g) if args.b: config['local_address'] = to_str(args.b) if args.t: config['timeout'] = int(args.t) # FIXME: # if key == '--fast-open': # config['fast_open'] = True if args.workers: config['workers'] = int(args.workers) # FIXME: # if key == '--manager-address': # config['manager_address'] = value if args.user: config['user'] = to_str(args.user) # FIXME: # if key == '--forbidden-ip': # config['forbidden_ip'] = to_str(value) if args.d: config['daemon'] = to_str(args.d) # FIXME: # if key == '--pid-file': # config['pid-file'] = to_str(value) # FIXME: # if key == '--log-file': # config['log-file'] = to_str(value) config['verbose'] = args.v if args.q: config['verbose'] -= 1 if args.L: config_from_ssrlink = decode_ssrlink(args.L) # config.update(config_from_ssrlink) config_from_ssrlink.update(config) config = config_from_ssrlink return (args, extra_args)
def parse_config(is_local, config_=None): global verbose global config global config_path # config = {} # config_path = None logging.basicConfig(level=logging.INFO, format='%(levelname)-s: %(message)s') if is_local: # check this is a client or a server. shortopts = 'hd:s:b:p:k:l:m:O:o:G:g:c:t:L:vq' longopts = [ 'help', 'fast-open', 'link', 'pid-file=', 'log-file=', 'user='******'version' ] else: shortopts = 'hd:s:p:k:m:O:o:G:g:c:t:vq' longopts = [ 'help', 'fast-open', 'pid-file=', 'log-file=', 'workers=', 'forbidden-ip=', 'user='******'manager-address=', 'version' ] if config_: config.update(config_) else: args = parse_args()[0] config['password'] = to_bytes(config.get('password', b'')) config['method'] = to_str(config.get('method', 'aes-256-cfb')) config['protocol'] = to_str(config.get('protocol', 'origin')) config['protocol_param'] = to_str(config.get('protocol_param', '')) config['obfs'] = to_str(config.get('obfs', 'plain')) config['obfs_param'] = to_str(config.get('obfs_param', '')) config['port_password'] = config.get('port_password', None) config['additional_ports'] = config.get('additional_ports', {}) config['additional_ports_only'] = config.get('additional_ports_only', False) config['timeout'] = int(config.get('timeout', 300)) config['udp_timeout'] = int(config.get('udp_timeout', 120)) config['udp_cache'] = int(config.get('udp_cache', 64)) config['fast_open'] = config.get('fast_open', False) config['workers'] = config.get('workers', 1) # config['pid-file'] = config.get('pid-file', '/var/run/shadowsocksr.pid') # config['log-file'] = config.get('log-file', '/var/log/shadowsocksr.log') config['pid-file'] = config.get('pid-file', '/tmp/shadowsocksr.pid') config['log-file'] = config.get('log-file', '/tmp/shadowsocksr.log') config['verbose'] = config.get('verbose', False) config['connect_verbose_info'] = config.get('connect_verbose_info', 0) config['local_address'] = to_str(config.get('local_address', '127.0.0.1')) config['local_port'] = config.get('local_port', 1080) if is_local: # FIXME: enable not provide server addr if daemon stop or restart # if config.get('server', None) is None and not args.command and (not args.d or args.d == 'start'): # if config.get('server', None) is None: # logging.error('server addr not specified') # print_local_help() # sys.exit(2) # else: # config['server'] = to_str(config['server']) if 'server' in config: config['server'] = to_str(config['server']) else: config['server'] = to_str(config.get('server', '0.0.0.0')) try: config['forbidden_ip'] = \ IPNetwork(config.get('forbidden_ip', '127.0.0.0/8,::1/128')) except Exception as e: logger.error(e) sys.exit(2) try: config['forbidden_port'] = PortRange( config.get('forbidden_port', '')) except Exception as e: logger.error(e) sys.exit(2) try: config['ignore_bind'] = \ IPNetwork(config.get('ignore_bind', '127.0.0.0/8,::1/128,10.0.0.0/8,192.168.0.0/16')) except Exception as e: logger.error(e) sys.exit(2) config['server_port'] = config.get('server_port', 8388) if config['verbose'] >= 2: level = VERBOSE_LEVEL elif config['verbose'] == 1: level = logging.DEBUG elif config['verbose'] == -1: level = logging.WARN elif config['verbose'] <= -2: level = logging.ERROR else: level = logging.INFO verbose = config['verbose'] logging.basicConfig( level=level, format= '%(asctime)s %(levelname)-8s %(filename)s:%(lineno)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S') check_config(config, is_local) return config