Exemple #1
0
 def client_encode(self, buf):
     if self.has_sent_header:
         return buf
     head_size = len(self.server_info.iv) + self.server_info.head_len
     if len(buf) - head_size > 64:
         headlen = head_size + random.randint(0, 64)
     else:
         headlen = len(buf)
     headdata = buf[:headlen]
     buf = buf[headlen:]
     port = b''
     if self.server_info.port != 80:
         port = b':' + to_bytes(str(self.server_info.port))
     body = None
     hosts = (self.server_info.obfs_param or self.server_info.host)
     pos = hosts.find("#")
     if pos >= 0:
         body = hosts[pos + 1:].replace("\n", "\r\n")
         body = body.replace("\\n", "\r\n")
         hosts = hosts[:pos]
     hosts = hosts.split(',')
     host = random.choice(hosts)
     http_head = b"GET /" + self.encode_head(headdata) + b" HTTP/1.1\r\n"
     http_head += b"Host: " + to_bytes(host) + port + b"\r\n"
     if body:
         http_head += body + "\r\n\r\n"
     else:
         http_head += b"User-Agent: " + random.choice(
             self.user_agent) + b"\r\n"
         http_head += b"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.8\r\nAccept-Encoding: gzip, deflate\r\nDNT: 1\r\nConnection: keep-alive\r\n\r\n"
     self.has_sent_header = True
     return http_head + buf
 def pack_auth_data(self, auth_data, buf):
     if len(buf) == 0:
         return b''
     if len(buf) > 400:
         rnd_len = struct.unpack('<H', os.urandom(2))[0] % 512
     else:
         rnd_len = struct.unpack('<H', os.urandom(2))[0] % 1024
     data = auth_data
     data_len = 7 + 4 + 16 + 4 + len(buf) + rnd_len + 4
     data = data + struct.pack('<H', data_len) + struct.pack('<H', rnd_len)
     mac_key = self.server_info.iv + self.server_info.key
     uid = os.urandom(4)
     if b':' in to_bytes(self.server_info.protocol_param):
         try:
             items = to_bytes(self.server_info.protocol_param).split(b':')
             self.user_key = self.hashfunc(items[1]).digest()
             uid = struct.pack('<I', int(items[0]))
         except:
             pass
     if self.user_key is None:
         self.user_key = self.server_info.key
     encryptor = encrypt.Encryptor(
         to_bytes(base64.b64encode(self.user_key)) + self.salt,
         'aes-128-cbc', b'\x00' * 16)
     data = uid + encryptor.encrypt(data)[16:]
     data += hmac.new(mac_key, data, self.hashfunc).digest()[:4]
     check_head = os.urandom(1)
     check_head += hmac.new(mac_key, check_head, self.hashfunc).digest()[:6]
     data = check_head + data + os.urandom(rnd_len) + buf
     data += hmac.new(self.user_key, data, self.hashfunc).digest()[:4]
     return data
 def client_udp_pre_encrypt(self, buf):
     if self.user_key is None:
         if b':' in to_bytes(self.server_info.protocol_param):
             try:
                 items = to_bytes(
                     self.server_info.protocol_param).split(':')
                 self.user_key = self.hashfunc(items[1]).digest()
                 self.user_id = struct.pack('<I', int(items[0]))
             except:
                 pass
         if self.user_key is None:
             self.user_id = os.urandom(4)
             self.user_key = self.server_info.key
     authdata = os.urandom(3)
     mac_key = self.server_info.key
     md5data = hmac.new(mac_key, authdata, self.hashfunc).digest()
     uid = struct.unpack('<I', self.user_id)[0] ^ struct.unpack(
         '<I', md5data[:4])[0]
     uid = struct.pack('<I', uid)
     rand_len = self.udp_rnd_data_len(md5data, self.random_client)
     encryptor = encrypt.Encryptor(
         to_bytes(base64.b64encode(self.user_key)) +
         to_bytes(base64.b64encode(md5data)), 'rc4')
     out_buf = encryptor.encrypt(buf)
     buf = out_buf + os.urandom(rand_len) + authdata + uid
     return buf + hmac.new(self.user_key, buf, self.hashfunc).digest()[:1]
 def client_udp_post_decrypt(self, buf):
     if len(buf) <= 8:
         return (b'', None)
     if hmac.new(self.user_key, buf[:-1],
                 self.hashfunc).digest()[:1] != buf[-1:]:
         return (b'', None)
     mac_key = self.server_info.key
     md5data = hmac.new(mac_key, buf[-8:-1], self.hashfunc).digest()
     rand_len = self.udp_rnd_data_len(md5data, self.random_server)
     encryptor = encrypt.Encryptor(
         to_bytes(base64.b64encode(self.user_key)) +
         to_bytes(base64.b64encode(md5data)), 'rc4')
     return encryptor.decrypt(buf[:-8 - rand_len])
 def client_udp_pre_encrypt(self, buf):
     if self.user_key is None:
         if b':' in to_bytes(self.server_info.protocol_param):
             try:
                 items = to_bytes(
                     self.server_info.protocol_param).split(':')
                 self.user_key = self.hashfunc(items[1]).digest()
                 self.user_id = struct.pack('<I', int(items[0]))
             except:
                 pass
         if self.user_key is None:
             self.user_id = os.urandom(4)
             self.user_key = self.server_info.key
     buf += self.user_id
     return buf + hmac.new(self.user_key, buf, self.hashfunc).digest()[:4]
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
    # 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 create(self, ouri, name, size, oplock, securitystyle, sync):
        parms = {
            'name': name,
        }
        if(size):
            size = common.to_bytes(size)
            parms["size"] = size
        if(oplock):
            parms["oplock"] = oplock
        if(securitystyle):
            parms["security_style"] = securitystyle
            
        body = json.dumps(parms)

        # REST api call
        (s, h) = common.service_json_request(
            self.__ipAddr, self.__port,
            "POST",
            QuotaDirectory.URI_QUOTA_DIRECTORY.format(ouri), body)

        o = common.json_decode(s)

        if(sync):
            return (
                self.block_until_complete(
                    o['resource']['id'],
                    o["id"])
            )
        else:
            return o
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
    # 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 update(self, ouri, name, size, oplock, securitystyle, sync):
        qduri = self.quotadirectory_query(ouri, name)
	    
        params = dict()
        if(size):
            size = common.to_bytes(size)
	    params['size'] = size
        if(oplock):
            params['oplock'] = oplock
        if(securitystyle):
            params['security_style'] = securitystyle
     
        body = json.dumps(params)
        (s, h) = common.service_json_request(
            self.__ipAddr, self.__port,
            "PUT",
            QuotaDirectory.URI_QUOTA_DIRECTORY_UPDATE.format(qduri), body)

        o = common.json_decode(s)

        if(sync):
            return (
                self.block_until_complete(
                    o['resource']['id'],
                    o["id"])
            )
        else:
            return o
    def quotadirectory_updates(self, resourceUri, name, size, oplock,
                               securitystyle, advlim, softlim, grace):
        qdUri = self.quotadirectory_query(resourceUri, name)
        parms = dict()

        if (size):
            size = common.to_bytes(size)
            parms["size"] = size
        if (oplock):
            parms["oplock"] = oplock
        if (securitystyle):
            parms["security_style"] = securitystyle
        if advlim:
            parms['notification_limit'] = advlim
        if softlim:
            parms['soft_limit'] = softlim
        if grace:
            parms['soft_grace'] = grace

        body = json.dumps(parms)

        # REST api call
        (s, h) = common.service_json_request(
            self.__ipAddr, self.__port, "POST",
            QuotaDirectory.URI_QUOTA_DIRECTORY_UPDATE.format(qdUri), body)

        o = common.json_decode(s)

        return
Exemple #11
0
def run_aead_method(method, key_len=16):

    if not loaded:
        load_openssl(None)
    print(method, ': [payload][tag]', key_len)
    cipher = libcrypto.EVP_get_cipherbyname(common.to_bytes(method))
    if not cipher:
        cipher = load_cipher(common.to_bytes(method))
    if not cipher:
        print('cipher not avaiable, please upgrade openssl')
        return
    key_len = int(key_len)
    cipher = OpenSSLAeadCrypto(method, b'k' * key_len, b'i' * key_len, 1)
    decipher = OpenSSLAeadCrypto(method, b'k' * key_len, b'i' * key_len, 0)

    util.run_cipher(cipher, decipher)
    def create(self, ouri, name, size, oplock, securitystyle, sync,
               synctimeout, advlim, softlim, grace):
        parms = {
            'name': name,
        }
        if (size):
            size = common.to_bytes(size)
            parms["size"] = size
        if (oplock):
            parms["oplock"] = oplock
        if (securitystyle):
            parms["security_style"] = securitystyle
        if advlim:
            parms['notification_limit'] = advlim
        if softlim:
            parms['soft_limit'] = softlim
        if grace:
            parms['soft_grace'] = grace

        body = json.dumps(parms)

        # REST api call
        (s, h) = common.service_json_request(
            self.__ipAddr, self.__port, "POST",
            QuotaDirectory.URI_QUOTA_DIRECTORY.format(ouri), body)

        o = common.json_decode(s)

        if (sync):
            return (self.block_until_complete(o['resource']['id'], o["id"],
                                              synctimeout))
        else:
            return o
    def __init__(self, local_sock, local_addr, passwd):
        '''
        初始化连接的状态。

        应该由监听套接字的回调函数调用。
        '''
        self.state = None
        self.local_sock = local_sock
        self.local_addr = local_addr
        self.remote_sock = None
        self.remote_addr = None  # 远程服务器

        self.passwd = passwd

        self.cryptor = aes_256_cfb_Cyptor(to_bytes(passwd))  #加密器

        self.upstream_buffer = b''  # 从本地读,向远程写
        self.downstream_buffer = b''  # 从远程读,向本地写

        self.local_closed = False
        self.remote_closed = False
        self.id = Connection.count
        Connection.count = Connection.count + 1

        self.update_state(self.S_INIT)
    def quotadirectory_updates(self, resourceUri, name, size, oplock, securitystyle, advlim, softlim, grace):
        qdUri = self.quotadirectory_query(
            resourceUri,
            name)
        parms = dict()

        if(size):
            size = common.to_bytes(size)
            parms["size"] = size
        if(oplock):
            parms["oplock"] = oplock
        if(securitystyle):
            parms["security_style"] = securitystyle
        if advlim:
            parms['notification_limit'] = advlim
        if softlim:
            parms['soft_limit'] = softlim
        if grace:
            parms['soft_grace'] = grace
            
        body = json.dumps(parms)

        # REST api call
        (s, h) = common.service_json_request(
            self.__ipAddr, self.__port,
            "POST",
            QuotaDirectory.URI_QUOTA_DIRECTORY_UPDATE.format(qdUri), body)

        o = common.json_decode(s)

        return
 def server_udp_pre_encrypt(self, buf, uid):
     if uid in self.server_info.users:
         user_key = self.server_info.users[uid]
     else:
         uid = None
         if not self.server_info.users:
             user_key = self.server_info.key
         else:
             user_key = self.server_info.recv_iv
     authdata = os.urandom(7)
     mac_key = self.server_info.key
     md5data = hmac.new(mac_key, authdata, self.hashfunc).digest()
     rand_len = self.udp_rnd_data_len(md5data, self.random_server)
     encryptor = encrypt.Encryptor(
         to_bytes(base64.b64encode(user_key)) +
         to_bytes(base64.b64encode(md5data)), 'rc4')
     out_buf = encryptor.encrypt(buf)
     buf = out_buf + os.urandom(rand_len) + authdata
     return buf + hmac.new(user_key, buf, self.hashfunc).digest()[:1]
Exemple #16
0
    def server_encode(self, buf):
        if self.has_sent_header:
            return buf

        header = b'HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Encoding: gzip\r\nContent-Type: text/html\r\nDate: '
        header += to_bytes(
            datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S GMT'))
        header += b'\r\nServer: nginx\r\nVary: Accept-Encoding\r\n\r\n'
        self.has_sent_header = True
        return header + buf
Exemple #17
0
def get_ssr_conf(ssr_conf_path: str) -> Dict:
    _ssr_conf: Dict = utils.parse_json(ssr_conf_path)

    if not _ssr_conf:
        exit.error('Require ssr-config.')

    # -- check params --
    port = _ssr_conf.get('server_port')
    if port is None:
        exit.error('Require \'server_port\'.')
    if type(port) != int or port <= 0:
        exit.error('Illegal \'server_port\'.')

    password = _ssr_conf.get('password')
    if common.is_blank(password):
        exit.error('Require \'password\'.')

    method = _ssr_conf.get('method')
    if common.is_blank(method):
        exit.error('Require \'method\'.')
    if not encrypt.is_supported(method):
        exit.error(f'Not supported method [{method}]')

    protocol = _ssr_conf.get('protocol')
    if common.is_blank(protocol):
        exit.error('Require \'protocol\'.')

    obfs = _ssr_conf.get('obfs')
    if common.is_blank(obfs):
        exit.error('Require \'obfs\'.')

    # -- default params --
    _ssr_conf['server'] = '::'
    _ssr_conf['password'] = common.to_bytes(_ssr_conf['password'])
    _ssr_conf['protocol_param'] = _ssr_conf.get('protocol_param', '')
    _ssr_conf['obfs_param'] = _ssr_conf.get('obfs_param', '')

    # process default data
    try:
        _ssr_conf['forbidden_ip'] = \
            common.IPNetwork(_ssr_conf.get('forbidden_ip', '127.0.0.0/8,::1/128'))
    except Exception as e:
        exit.error('error configuration \'forbidden_ip\'.')
    try:
        _ssr_conf['forbidden_port'] = common.PortRange(
            _ssr_conf.get('forbidden_port', ''))
    except Exception as e:
        exit.error('error configuration \'forbidden_port\'.')
    try:
        _ssr_conf['ignore_bind'] = \
            common.IPNetwork(_ssr_conf.get('ignore_bind', '127.0.0.0/8,::1/128,10.0.0.0/8,192.168.0.0/16'))
    except Exception as e:
        exit.error('error configuration \'ignore_bind\'.')

    return _ssr_conf
Exemple #18
0
def build_address(address):
    address = address.strip(b'.')
    labels = address.split(b'.')
    results = []
    for label in labels:
        l = len(label)
        if l > 63:
            return None
        results.append(to_bytes(chr(l)))
        results.append(label)
    results.append(b'\0')
    return b''.join(results)
    def pack_auth_data(self, auth_data, buf):
        data = auth_data
        data_len = 12 + 4 + 16 + 4
        data = data + (struct.pack('<H', self.server_info.overhead) +
                       struct.pack('<H', 0))
        mac_key = self.server_info.iv + self.server_info.key

        check_head = os.urandom(4)
        self.last_client_hash = hmac.new(mac_key, check_head,
                                         self.hashfunc).digest()
        check_head += self.last_client_hash[:8]

        if b':' in to_bytes(self.server_info.protocol_param):
            try:
                items = to_bytes(self.server_info.protocol_param).split(b':')
                self.user_key = items[1]
                uid = struct.pack('<I', int(items[0]))
            except:
                uid = os.urandom(4)
        else:
            uid = os.urandom(4)
        if self.user_key is None:
            self.user_key = self.server_info.key

        encryptor = encrypt.Encryptor(
            to_bytes(base64.b64encode(self.user_key)) + self.salt,
            'aes-128-cbc', b'\x00' * 16)

        uid = struct.unpack('<I', uid)[0] ^ struct.unpack(
            '<I', self.last_client_hash[8:12])[0]
        uid = struct.pack('<I', uid)
        data = uid + encryptor.encrypt(data)[16:]
        self.last_server_hash = hmac.new(self.user_key, data,
                                         self.hashfunc).digest()
        data = check_head + data + self.last_server_hash[:4]
        self.encryptor = encrypt.Encryptor(
            to_bytes(base64.b64encode(self.user_key)) +
            to_bytes(base64.b64encode(self.last_client_hash)), 'rc4')
        return data + self.pack_client_data(buf)
Exemple #20
0
 def get_cipher(self, password, method, op, iv):
     password = common.to_bytes(password)
     m = self._method_info
     if m[0] > 0:
         key, iv_ = EVP_BytesToKey(password, m[0], m[1])
     else:
         # key_length == 0 indicates we should use the key directly
         key, iv = password, b''
     self.key = key
     iv = iv[:m[1]]
     if op == 1:
         # this iv is for cipher not decipher
         self.cipher_iv = iv[:m[1]]
     return m[2](method, key, iv, op)
    def get_cipher(self, password, method, op, iv):
        password = common.to_bytes(password)
        m = self._method_info
        if m[0] > 0:
            key, iv_ = EVP_BytesToKey(password, m[0], m[1])
        else:
            # key_length == 0 indicates we should use the key directly
            key, iv = password, b''

        iv = iv[:m[1]]
        if op == 1:
            # this iv is for cipher not decipher
            self.cipher_iv = iv[:m[1]]
        return m[2](method, key, iv, op)
 def server_udp_post_decrypt(self, buf):
     mac_key = self.server_info.key
     md5data = hmac.new(mac_key, buf[-8:-5], self.hashfunc).digest()
     uid = struct.unpack('<I', buf[-5:-1])[0] ^ struct.unpack(
         '<I', md5data[:4])[0]
     uid = struct.pack('<I', uid)
     if uid in self.server_info.users:
         user_key = self.server_info.users[uid]
     else:
         uid = None
         if not self.server_info.users:
             user_key = self.server_info.key
         else:
             user_key = self.server_info.recv_iv
     if hmac.new(user_key, buf[:-1],
                 self.hashfunc).digest()[:1] != buf[-1:]:
         return (b'', None)
     rand_len = self.udp_rnd_data_len(md5data, self.random_client)
     encryptor = encrypt.Encryptor(
         to_bytes(base64.b64encode(user_key)) +
         to_bytes(base64.b64encode(md5data)), 'rc4')
     out_buf = encryptor.decrypt(buf[:-8 - rand_len])
     return (out_buf, uid)
    def __init__(self, config, dns_resolver, is_local, stat_callback=None):
        self._config = config
        if is_local:
            self._listen_addr = config['local_address']
            self._listen_port = config['local_port']
            self._remote_addr = config['server']
            self._remote_port = config['server_port']
        else:
            self._listen_addr = config['server']
            self._listen_port = config['server_port']
            self._remote_addr = None
            self._remote_port = None
        self._dns_resolver = dns_resolver
        self._password = common.to_bytes(config['password'])
        self._method = config['method']
        self._timeout = config['timeout']
        if 'one_time_auth' in config and config['one_time_auth']:
            self._one_time_auth_enable = True
        else:
            self._one_time_auth_enable = False
        self._is_local = is_local
        # 地址到socket的映射
        self._cache = lru_cache.LRUCache(timeout=config['timeout'],
                                         close_callback=self._close_client)
        # client上行upstream发送的地址
        self._client_fd_to_server_addr = \
            lru_cache.LRUCache(timeout=config['timeout'])
        # 服务器地址到socket.getaddrinfo的映射,上行upstream的dns
        self._dns_cache = lru_cache.LRUCache(timeout=300)
        self._eventloop = None
        self._closed = False
        self._sockets = set()
        if 'forbidden_ip' in config:
            self._forbidden_iplist = config['forbidden_ip']
        else:
            self._forbidden_iplist = None

        addrs = socket.getaddrinfo(self._listen_addr, self._listen_port, 0,
                                   socket.SOCK_DGRAM, socket.SOL_UDP)
        if len(addrs) == 0:
            raise Exception("UDP can't get addrinfo for %s:%d" %
                            (self._listen_addr, self._listen_port))
        af, socktype, proto, canonname, sa = addrs[0]
        server_socket = socket.socket(af, socktype, proto)
        server_socket.bind((self._listen_addr, self._listen_port))
        server_socket.setblocking(False)
        # udp监听
        self._server_socket = server_socket
        self._stat_callback = stat_callback
Exemple #24
0
 def get_cipher(self, password, method, op, iv):
     password = common.to_bytes(password)
     m = self._method_info
     if m[METHOD_INFO_KEY_LEN] > 0:
         key, _ = EVP_BytesToKey(password, m[METHOD_INFO_KEY_LEN],
                                 m[METHOD_INFO_IV_LEN])
     else:
         # key_length == 0 indicates we should use the key directly
         key, iv = password, b''
     self.key = key
     iv = iv[:m[METHOD_INFO_IV_LEN]]
     if op == CIPHER_ENC_ENCRYPTION:
         # this iv is for cipher not decipher
         self.cipher_iv = iv
     return m[METHOD_INFO_CRYPTO](method, key, iv, op, self.crypto_path)
Exemple #25
0
 def __init__(self, cipher_name, crypto_path=None):
     self._ctx = None
     self._cipher = None
     if not loaded:
         load_openssl(crypto_path)
     cipher_name = common.to_bytes(cipher_name)
     cipher = libcrypto.EVP_get_cipherbyname(cipher_name)
     if not cipher:
         cipher = load_cipher(cipher_name)
     if not cipher:
         raise Exception('cipher %s not found in libcrypto' % cipher_name)
     self._ctx = libcrypto.EVP_CIPHER_CTX_new()
     self._cipher = cipher
     if not self._ctx:
         raise Exception('can not create cipher context')
 def _update_users(self, protocol_param, acl):
     if protocol_param is None:
         protocol_param = self._config['protocol_param']
     param = common.to_bytes(protocol_param).split(b'#')
     if len(param) == 2:
         user_list = param[1].split(b',')
         if user_list:
             for user in user_list:
                 items = user.split(b':')
                 if len(items) == 2:
                     user_int_id = int(items[0])
                     uid = struct.pack('<I', user_int_id)
                     if acl is not None and user_int_id not in acl:
                         self.del_user(uid)
                     else:
                         passwd = items[1]
                         self.add_user(uid, {'password': passwd})
Exemple #27
0
    def __init__(self, cipher_name, crypto_path=None):
        global loaded
        self._ctx = create_string_buffer(b'\0' * CIPHER_CTX_SIZE)
        self._cipher = None
        if not loaded:
            load_mbedtls(crypto_path)
        cipher_name = common.to_bytes(cipher_name.upper())
        cipher = libmbedtls.mbedtls_cipher_info_from_string(cipher_name)
        if not cipher:
            raise Exception('cipher %s not found in libmbedtls' % cipher_name)
        libmbedtls.mbedtls_cipher_init(byref(self._ctx))
        if libmbedtls.mbedtls_cipher_setup(byref(self._ctx), cipher):
            raise Exception('can not setup cipher')
        self._cipher = cipher

        self.encrypt_once = self.update
        self.decrypt_once = self.update
Exemple #28
0
    def __init__(self, config, dns_resolver, is_local, stat_callback=None):
        self._config = config
        if is_local:
            self._listen_addr = config['local_address']
            self._listen_port = config['local_port']
            self._remote_addr = config['server']
            self._remote_port = config['server_port']
        else:
            self._listen_addr = config['server']
            self._listen_port = config['server_port']
            self._remote_addr = None
            self._remote_port = None
        self.tunnel_remote = config.get('tunnel_remote', "8.8.8.8")
        self.tunnel_remote_port = config.get('tunnel_remote_port', 53)
        self.tunnel_port = config.get('tunnel_port', 53)
        self._is_tunnel = False
        self._dns_resolver = dns_resolver
        self._password = common.to_bytes(config['password'])
        self._method = config['method']
        self._timeout = config['timeout']
        self._ota_enable = config.get('one_time_auth', False)
        self._ota_enable_session = self._ota_enable
        self._is_local = is_local
        self._cache = lru_cache.LRUCache(timeout=config['timeout'],
                                         close_callback=self._close_client)
        self._client_fd_to_server_addr = \
            lru_cache.LRUCache(timeout=config['timeout'])
        self._dns_cache = lru_cache.LRUCache(timeout=300)
        self._eventloop = None
        self._closed = False
        self._sockets = set()
        self._forbidden_iplist = config.get('forbidden_ip')
        self._crypto_path = config['crypto_path']

        addrs = socket.getaddrinfo(self._listen_addr, self._listen_port, 0,
                                   socket.SOCK_DGRAM, socket.SOL_UDP)
        if len(addrs) == 0:
            raise Exception("UDP can't get addrinfo for %s:%d" %
                            (self._listen_addr, self._listen_port))
        af, socktype, proto, canonname, sa = addrs[0]
        server_socket = socket.socket(af, socktype, proto)
        server_socket.bind((self._listen_addr, self._listen_port))
        server_socket.setblocking(False)
        self._server_socket = server_socket
        self._stat_callback = stat_callback
Exemple #29
0
 def get_cipher(self, password, method, op, iv):
     # iv 是随机值 os.urandom
     password = common.to_bytes(password)
     m = self._method_info
     if m[0] > 0:
         key, iv_ = EVP_BytesToKey(password, m[0], m[1])
     else:
         # key_length == 0 indicates we should use the key directly
         key, iv = password, b''
     self.key = key
     # 长度不够也没问题
     iv = iv[:m[1]]
     if op == 1:
         # ope 1 表示iv用于加密
         # this iv is for cipher not decipher
         # 什么鬼,直接赋值不就好
         self.cipher_iv = iv[:m[1]]
     return m[2](method, key, iv, op)
 def __init__(self, cipher_name, key, iv, op):
     self._ctx = None
     if not loaded:
         load_openssl()
     cipher = libcrypto.EVP_get_cipherbyname(common.to_bytes(cipher_name))
     if not cipher:
         cipher = load_cipher(cipher_name)
     if not cipher:
         raise Exception('cipher %s not found in libcrypto' % cipher_name)
     key_ptr = c_char_p(key)
     iv_ptr = c_char_p(iv)
     self._ctx = libcrypto.EVP_CIPHER_CTX_new()
     if not self._ctx:
         raise Exception('can not create cipher context')
     r = libcrypto.EVP_CipherInit_ex(self._ctx, cipher, None,
                                     key_ptr, iv_ptr, c_int(op))
     if not r:
         self.clean()
         raise Exception('can not initialize cipher context')
 def __init__(self, cipher_name, key, iv, op):
     self._ctx = None
     if not loaded:
         load_openssl()
     cipher_name = common.to_bytes(cipher_name)
     cipher = libcrypto.EVP_get_cipherbyname(cipher_name)
     if not cipher:
         cipher = load_cipher(cipher_name)
     if not cipher:
         raise Exception('cipher %s not found in libcrypto' % cipher_name)
     key_ptr = c_char_p(key)
     iv_ptr = c_char_p(iv)
     self._ctx = libcrypto.EVP_CIPHER_CTX_new()
     if not self._ctx:
         raise Exception('can not create cipher context')
     r = libcrypto.EVP_CipherInit_ex(self._ctx, cipher, None,
                                     key_ptr, iv_ptr, c_int(op))
     if not r:
         self.clean()
         raise Exception('can not initialize cipher context')
    def expand_volume(self, vol, new_size):
        """expands the volume to new_size specified."""
        self.authenticate_user()
        volume_name = self._get_volume_name(vol)
        import common as vipr_utils
        size_in_bytes = vipr_utils.to_bytes(str(new_size) + "G")
        from common import SOSError

        try:
            self.volume_obj.expand(
                self.configuration.vipr_tenant + "/" +
                self.configuration.vipr_project + "/" + volume_name,
                size_in_bytes, True)
        except SOSError as e:
            if (e.err_code == SOSError.SOS_FAILURE_ERR):
                raise SOSError(
                    SOSError.SOS_FAILURE_ERR,
                    "Volume " + volume_name + ": expand failed\n" + e.err_text)
            else:
                raise e
Exemple #33
0
    def update(self, ouri, name, size, oplock, securitystyle, sync):
        qduri = self.quotadirectory_query(ouri, name)

        params = dict()
        if (size):
            size = common.to_bytes(size)
            params['size'] = size
        if (oplock):
            params['oplock'] = oplock
        if (securitystyle):
            params['security_style'] = securitystyle

        body = json.dumps(params)
        (s, h) = common.service_json_request(
            self.__ipAddr, self.__port, "PUT",
            QuotaDirectory.URI_QUOTA_DIRECTORY_UPDATE.format(qduri), body)

        o = common.json_decode(s)

        if (sync):
            return (self.block_until_complete(o['resource']['id'], o["id"]))
        else:
            return o
def get_config(is_local):
    global verbose
    global config

    if is_local:
        shortopts = 'hd:s:b:p:k:l:m:c:t:vq'
        longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'user='******'version']
    else:
        shortopts = 'hd:s:p:k:m:c:t:vq'
        longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'workers=',
                    'forbidden-ip=', 'user='******'version']
    try:
        config_path = find_config()
        optlist, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
        for key, value in optlist:
            if key == '-c':
                config_path = value

        if config_path:
            logging.info('loading config from %s' % config_path)
            with open(config_path, 'rb') as f:
                try:
                    config = json.loads(f.read().decode('utf8'),
                                        object_hook=_decode_dict)
                except ValueError as e:
                    logging.error('found an error in config.json: %s',
                                  e.message)
                    sys.exit(1)
        else:
            config = {}

        optlist, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
        v_count = 0
        for key, value in optlist:
            if key == '-p':
                config['server_port'] = int(value)
            elif key == '-k':
                config['password'] = to_bytes(value)
            elif key == '-l':
                config['local_port'] = int(value)
            elif key == '-s':
                config['server'] = to_str(value)
            elif key == '-m':
                config['method'] = to_str(value)
            elif key == '-b':
                config['local_address'] = to_str(value)
            elif key == '-v':
                v_count += 1
                # '-vv' turns on more verbose mode
                config['verbose'] = v_count
            elif key == '-t':
                config['timeout'] = int(value)
            elif key == '--fast-open':
                config['fast_open'] = True
            elif key == '--workers':
                config['workers'] = int(value)
            elif key == '--user':
                config['user'] = to_str(value)
            elif key == '--forbidden-ip':
                config['forbidden_ip'] = to_str(value).split(',')
            elif key in ('-h', '--help'):
                if is_local:
                    print_local_help()
                else:
                    print_server_help()
                sys.exit(0)
            elif key == '--version':
                print_shadowsocks()
                sys.exit(0)
            elif key == '-d':
                config['daemon'] = to_str(value)
            elif key == '--pid-file':
                config['pid-file'] = to_str(value)
            elif key == '--log-file':
                config['log-file'] = to_str(value)
            elif key == '-q':
                v_count -= 1
                config['verbose'] = v_count
    except getopt.GetoptError as e:
        print(e, file=sys.stderr)
        print_help(is_local)
        sys.exit(2)

    if not config:
        logging.error('config not specified')
        print_help(is_local)
        sys.exit(2)

    config['password'] = to_bytes(config.get('password', b''))
    config['method'] = to_str(config.get('method', 'aes-256-cfb'))
    config['port_password'] = config.get('port_password', None)
    config['timeout'] = int(config.get('timeout', 300))
    config['fast_open'] = config.get('fast_open', False)
    config['workers'] = config.get('workers', 1)
    config['pid-file'] = config.get('pid-file', '/var/run/shadowsocks.pid')
    config['log-file'] = config.get('log-file', '/var/log/shadowsocks.log')
    config['workers'] = config.get('workers', 1)
    config['verbose'] = config.get('verbose', False)
    config['local_address'] = to_str(config.get('local_address', '127.0.0.1'))
    config['local_port'] = config.get('local_port', 1080)
    if is_local:
        if config.get('server', None) is None:
            logging.error('server addr not specified')
            print_local_help()
            sys.exit(2)
        else:
            config['server'] = to_str(config['server'])
    else:
        config['server'] = to_str(config.get('server', '0.0.0.0'))
        try:
            config['forbidden_ip'] = \
                IPNetwork(config.get('forbidden_ip', '127.0.0.0/8,::1/128'))
        except Exception as e:
            logging.error(e)
            sys.exit(2)
    config['server_port'] = config.get('server_port', 8388)

    logging.getLogger('').handlers = []
    logging.addLevelName(VERBOSE_LEVEL, 'VERBOSE')
    if config['verbose'] >= 2:
        level = VERBOSE_LEVEL
    elif config['verbose'] == 1:
        level = logging.DEBUG
    elif config['verbose'] == -1:
        level = logging.WARN
    elif config['verbose'] <= -2:
        level = logging.ERROR
    else:
        level = logging.INFO
    verbose = config['verbose']
    logging.basicConfig(level=level,
                        format='%(asctime)s %(levelname)-8s %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S',
                        filemode='w')
    # 定义一个1分钟换一次log文件的handler
    filehandler = logging.handlers.TimedRotatingFileHandler(
        "/var/log/shadowsocks/sslog", 'D', 2, 15)
    filehandler.suffix = "%Y%m%d-%H%M.log"
    # set a format which is simpler for console use
    formatter = logging.Formatter("%(asctime)s %(levelname)-8s %(message)s","%Y-%m-%d %H:%M:%S");
    filehandler.setFormatter(formatter)
    #logging.getLogger('').addHandler(console)
    logging.getLogger('').addHandler(filehandler)

    check_config(config, is_local)

    return config
    def server_post_decrypt(self, buf):
        if self.raw_trans:
            return (buf, False)
        self.recv_buf += buf
        out_buf = b''
        sendback = False

        if not self.has_recv_header:
            if len(self.recv_buf) >= 12 or len(self.recv_buf) in [7, 8]:
                recv_len = min(len(self.recv_buf), 12)
                mac_key = self.server_info.recv_iv + self.server_info.key
                md5data = hmac.new(mac_key, self.recv_buf[:4],
                                   self.hashfunc).digest()
                if md5data[:recv_len - 4] != self.recv_buf[4:recv_len]:
                    return self.not_match_return(self.recv_buf)

            if len(self.recv_buf) < 12 + 24:
                return (b'', False)

            self.last_client_hash = md5data

            self.user_key = self.server_info.key
            md5data = hmac.new(self.user_key, self.recv_buf[12:12 + 20],
                               self.hashfunc).digest()
            if md5data[:4] != self.recv_buf[32:36]:
                logging.error(
                    '%s data uncorrect auth HMAC-MD5 from %s:%d, data %s' %
                    (self.no_compatible_method, self.server_info.client,
                     self.server_info.client_port,
                     binascii.hexlify(self.recv_buf)))
                if len(self.recv_buf) < 36:
                    return (b'', False)
                return self.not_match_return(self.recv_buf)

            self.last_server_hash = md5data
            encryptor = encrypt.Encryptor(
                to_bytes(base64.b64encode(self.user_key)) + self.salt,
                'aes-128-cbc')
            head = encryptor.decrypt(
                b'\x00' * 16 + self.recv_buf[16:32] +
                b'\x00')  # need an extra byte or recv empty
            self.client_over_head = struct.unpack('<H', head[12:14])[0]

            utc_time = struct.unpack('<I', head[:4])[0]
            client_id = struct.unpack('<I', head[4:8])[0]
            connection_id = struct.unpack('<I', head[8:12])[0]
            time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff))
            if time_dif < -self.max_time_dif or time_dif > self.max_time_dif:
                logging.info('%s: wrong timestamp, time_dif %d, data %s' %
                             (self.no_compatible_method, time_dif,
                              binascii.hexlify(head)))
                return self.not_match_return(self.recv_buf)
            elif self.server_info.data.insert(self.user_id, client_id,
                                              connection_id):
                self.has_recv_header = True
                self.client_id = client_id
                self.connection_id = connection_id
            else:
                logging.info(
                    '%s: auth fail, data %s' %
                    (self.no_compatible_method, binascii.hexlify(out_buf)))
                return self.not_match_return(self.recv_buf)

            self.encryptor = encrypt.Encryptor(
                to_bytes(base64.b64encode(self.user_key)) +
                to_bytes(base64.b64encode(self.last_client_hash)), 'rc4')
            self.recv_buf = self.recv_buf[36:]
            self.has_recv_header = True
            sendback = True

        while len(self.recv_buf) > 4:
            mac_key = self.user_key + struct.pack('<I', self.recv_id)
            data_len = struct.unpack('<H',
                                     self.recv_buf[:2])[0] ^ struct.unpack(
                                         '<H', self.last_client_hash[14:16])[0]
            rand_len = self.rnd_data_len(data_len, self.last_client_hash,
                                         self.random_client)
            length = data_len + rand_len
            if length >= 4096:
                self.raw_trans = True
                self.recv_buf = b''
                if self.recv_id == 0:
                    logging.info(self.no_compatible_method + ': over size')
                    return (b'E' * 2048, False)
                else:
                    raise Exception('server_post_decrype data error')

            if length + 4 > len(self.recv_buf):
                break

            client_hash = hmac.new(mac_key, self.recv_buf[:length + 2],
                                   self.hashfunc).digest()
            if client_hash[:2] != self.recv_buf[length + 2:length + 4]:
                logging.info('%s: checksum error, data %s' %
                             (self.no_compatible_method,
                              binascii.hexlify(self.recv_buf[:length])))
                self.raw_trans = True
                self.recv_buf = b''
                if self.recv_id == 0:
                    return (b'E' * 2048, False)
                else:
                    raise Exception(
                        'server_post_decrype data uncorrect checksum')

            self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF
            pos = 2
            if data_len > 0 and rand_len > 0:
                pos = 2 + self.rnd_start_pos(rand_len, self.random_client)
            out_buf += self.encryptor.decrypt(self.recv_buf[pos:data_len +
                                                            pos])
            self.last_client_hash = client_hash
            self.recv_buf = self.recv_buf[length + 4:]
            if data_len == 0:
                sendback = True

        if out_buf:
            self.server_info.data.update(self.user_id, self.client_id,
                                         self.connection_id)
        return (out_buf, sendback)
    def server_post_decrypt(self, buf):
        if self.raw_trans:
            return (buf, False)
        self.recv_buf += buf
        out_buf = b''
        sendback = False

        if not self.has_recv_header:
            if len(self.recv_buf) >= 7 or len(self.recv_buf) in [2, 3]:
                recv_len = min(len(self.recv_buf), 7)
                mac_key = self.server_info.recv_iv + self.server_info.key
                sha1data = hmac.new(mac_key, self.recv_buf[:1],
                                    self.hashfunc).digest()[:recv_len - 1]
                if sha1data != self.recv_buf[1:recv_len]:
                    return self.not_match_return(self.recv_buf)

            if len(self.recv_buf) < 31:
                return (b'', False)
            sha1data = hmac.new(mac_key, self.recv_buf[7:27],
                                self.hashfunc).digest()[:4]
            if sha1data != self.recv_buf[27:31]:
                logging.error(
                    '%s data uncorrect auth HMAC-SHA1 from %s:%d, data %s' %
                    (self.no_compatible_method, self.server_info.client,
                     self.server_info.client_port,
                     binascii.hexlify(self.recv_buf)))
                if len(self.recv_buf) < 31 + self.extra_wait_size:
                    return (b'', False)
                return self.not_match_return(self.recv_buf)

            self.user_key = self.server_info.key
            encryptor = encrypt.Encryptor(
                to_bytes(base64.b64encode(self.user_key)) + self.salt,
                'aes-128-cbc')
            head = encryptor.decrypt(
                b'\x00' * 16 + self.recv_buf[11:27] +
                b'\x00')  # need an extra byte or recv empty
            length = struct.unpack('<H', head[12:14])[0]
            if len(self.recv_buf) < length:
                return (b'', False)

            utc_time = struct.unpack('<I', head[:4])[0]
            client_id = struct.unpack('<I', head[4:8])[0]
            connection_id = struct.unpack('<I', head[8:12])[0]
            rnd_len = struct.unpack('<H', head[14:16])[0]
            if hmac.new(self.user_key, self.recv_buf[:length - 4],
                        self.hashfunc).digest()[:4] != self.recv_buf[length -
                                                                     4:length]:
                logging.info('%s: checksum error, data %s' %
                             (self.no_compatible_method,
                              binascii.hexlify(self.recv_buf[:length])))
                return self.not_match_return(self.recv_buf)
            time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff))
            if time_dif < -self.max_time_dif or time_dif > self.max_time_dif:
                logging.info('%s: wrong timestamp, time_dif %d, data %s' %
                             (self.no_compatible_method, time_dif,
                              binascii.hexlify(head)))
                return self.not_match_return(self.recv_buf)
            elif self.server_info.data.insert(self.user_id, client_id,
                                              connection_id):
                self.has_recv_header = True
                out_buf = self.recv_buf[31 + rnd_len:length - 4]
                self.client_id = client_id
                self.connection_id = connection_id
            else:
                logging.info(
                    '%s: auth fail, data %s' %
                    (self.no_compatible_method, binascii.hexlify(out_buf)))
                return self.not_match_return(self.recv_buf)
            self.recv_buf = self.recv_buf[length:]
            self.has_recv_header = True
            sendback = True

        while len(self.recv_buf) > 4:
            mac_key = self.user_key + struct.pack('<I', self.recv_id)
            mac = hmac.new(mac_key, self.recv_buf[:2],
                           self.hashfunc).digest()[:2]
            if mac != self.recv_buf[2:4]:
                self.raw_trans = True
                logging.info(self.no_compatible_method + ': wrong crc')
                if self.recv_id == 0:
                    logging.info(self.no_compatible_method + ': wrong crc')
                    return (b'E' * 2048, False)
                else:
                    raise Exception('server_post_decrype data error')
            length = struct.unpack('<H', self.recv_buf[:2])[0]
            if length >= 8192 or length < 7:
                self.raw_trans = True
                self.recv_buf = b''
                if self.recv_id == 0:
                    logging.info(self.no_compatible_method + ': over size')
                    return (b'E' * 2048, False)
                else:
                    raise Exception('server_post_decrype data error')
            if length > len(self.recv_buf):
                break

            if hmac.new(mac_key, self.recv_buf[:length - 4],
                        self.hashfunc).digest()[:4] != self.recv_buf[length -
                                                                     4:length]:
                logging.info('%s: checksum error, data %s' %
                             (self.no_compatible_method,
                              binascii.hexlify(self.recv_buf[:length])))
                self.raw_trans = True
                self.recv_buf = b''
                if self.recv_id == 0:
                    return (b'E' * 2048, False)
                else:
                    raise Exception(
                        'server_post_decrype data uncorrect checksum')

            self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF
            pos = common.ord(self.recv_buf[4])
            if pos < 255:
                pos += 4
            else:
                pos = struct.unpack('<H', self.recv_buf[5:7])[0] + 4
            out_buf += self.recv_buf[pos:length - 4]
            self.recv_buf = self.recv_buf[length:]
            if pos == length - 4:
                sendback = True

        if out_buf:
            self.server_info.data.update(self.user_id, self.client_id,
                                         self.connection_id)
        return (out_buf, sendback)
Exemple #37
0
def get_config(is_local):
    global verbose

    logging.basicConfig(level=logging.INFO,
                        format='%(levelname)-s: %(message)s')
    if is_local:
        shortopts = 'hd:s:b:p:k:l:m:c:t:vqa'
        longopts = [
            'help', 'fast-open', 'pid-file=', 'log-file=', 'user='******'version'
        ]
    else:
        shortopts = 'hd:s:p:k:m:c:t:vqa'
        longopts = [
            'help', 'fast-open', 'pid-file=', 'log-file=', 'workers=',
            'forbidden-ip=', 'user='******'manager-address=', 'version',
            'prefer-ipv6'
        ]
    try:
        config_path = find_config()
        optlist, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
        # 先解析命令行设置的配置文件,命令行优先级比较大,会覆盖配置文件
        for key, value in optlist:
            if key == '-c':
                config_path = value

        if config_path:
            logging.info('loading config from %s' % config_path)
            with open(config_path, 'rb') as f:
                try:
                    config = parse_json_in_str(f.read().decode('utf8'))
                except ValueError as e:
                    logging.error('found an error in config.json: %s',
                                  e.message)
                    sys.exit(1)
        else:
            config = {}

        v_count = 0
        for key, value in optlist:
            if key == '-p':
                config['server_port'] = int(value)
            elif key == '-k':
                config['password'] = to_bytes(value)
            elif key == '-l':
                config['local_port'] = int(value)
            elif key == '-s':
                config['server'] = to_str(value)
            elif key == '-m':
                config['method'] = to_str(value)
            elif key == '-b':
                config['local_address'] = to_str(value)
            elif key == '-v':
                v_count += 1
                # '-vv' turns on more verbose mode
                config['verbose'] = v_count
            elif key == '-a':
                config['one_time_auth'] = True
            elif key == '-t':
                config['timeout'] = int(value)
            elif key == '--fast-open':
                config['fast_open'] = True
            elif key == '--workers':
                config['workers'] = int(value)
            elif key == '--manager-address':
                config['manager_address'] = value
            elif key == '--user':
                config['user'] = to_str(value)
            elif key == '--forbidden-ip':
                config['forbidden_ip'] = to_str(value).split(',')
            elif key in ('-h', '--help'):
                if is_local:
                    print_local_help()
                else:
                    print_server_help()
                sys.exit(0)
            elif key == '--version':
                print_shadowsocks()
                sys.exit(0)
            elif key == '-d':
                config['daemon'] = to_str(value)
            elif key == '--pid-file':
                config['pid-file'] = to_str(value)
            elif key == '--log-file':
                config['log-file'] = to_str(value)
            elif key == '-q':
                v_count -= 1
                config['verbose'] = v_count
            elif key == '--prefer-ipv6':
                config['prefer_ipv6'] = True
    except getopt.GetoptError as e:
        print(e, file=sys.stderr)
        print_help(is_local)
        sys.exit(2)

    if not config:
        logging.error('config not specified')
        print_help(is_local)
        sys.exit(2)

    config['password'] = to_bytes(config.get('password', b''))
    config['method'] = to_str(config.get('method', 'aes-256-cfb'))
    config['port_password'] = config.get('port_password', None)
    config['timeout'] = int(config.get('timeout', 300))
    config['fast_open'] = config.get('fast_open', False)
    config['workers'] = config.get('workers', 1)
    config['pid-file'] = config.get('pid-file', '/var/run/shadowsocks.pid')
    config['log-file'] = config.get('log-file', '/var/log/shadowsocks.log')
    config['verbose'] = config.get('verbose', False)
    config['local_address'] = to_str(config.get('local_address', '127.0.0.1'))
    config['local_port'] = config.get('local_port', 1080)
    config['one_time_auth'] = config.get('one_time_auth', False)
    config['prefer_ipv6'] = config.get('prefer_ipv6', False)
    if is_local:
        if config.get('server', None) is None:
            logging.error('server addr not specified')
            print_local_help()
            sys.exit(2)
        else:
            config['server'] = to_str(config['server'])
    else:
        config['server'] = to_str(config.get('server', '0.0.0.0'))
        try:
            config['forbidden_ip'] = \
                IPNetwork(config.get('forbidden_ip', '127.0.0.0/8,::1/128'))
        except Exception as e:
            logging.error(e)
            sys.exit(2)
    config['server_port'] = config.get('server_port', 8388)

    logging.getLogger('').handlers = []
    logging.addLevelName(VERBOSE_LEVEL, 'VERBOSE')
    if config['verbose'] >= 2:
        level = VERBOSE_LEVEL
    elif config['verbose'] == 1:
        level = logging.DEBUG
    elif config['verbose'] == -1:
        level = logging.WARN
    elif config['verbose'] <= -2:
        level = logging.ERROR
    else:
        level = logging.INFO
    verbose = config['verbose']
    logging.basicConfig(level=level,
                        format='%(asctime)s %(levelname)-8s %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')

    check_config(config, is_local)

    return config