Esempio n. 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
Esempio n. 2
0
    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)
Esempio n. 3
0
 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
Esempio n. 4
0
 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])
Esempio n. 5
0
 def _handel_protocol_error(self, client_address, ogn_data):
     logging.warn("Protocol ERROR, TCP ogn data %s from %s:%d via port %d" % (binascii.hexlify(ogn_data), client_address[0], client_address[1], self._server._listen_port))
     self._encrypt_correct = False
     #create redirect or disconnect by hash code
     host, port = self._get_redirect_host(client_address, ogn_data)
     if port == 0:
         raise Exception('can not parse header')
     data = b"\x03" + common.to_bytes(common.chr(len(host))) + common.to_bytes(host) + struct.pack('>H', port)
     logging.warn("TCP data redir %s:%d %s" % (host, port, binascii.hexlify(data)))
     return data + ogn_data
Esempio n. 6
0
def run_aead_method(method, key_len=16):

    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)
Esempio n. 7
0
 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]
Esempio n. 8
0
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:
        logging.error(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
Esempio n. 9
0
File: ss.py Progetto: rain10154/ss
def getSimpleConfig():
    VERBOSE_LEVEL = 5
    config['password'] = to_bytes(config.get('password', b''))
    config['method'] = to_str(config.get('method', 'aes-256-cfb'))
    config['port_password'] = ssDict
    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['server'] = to_str(config.get('server', '0.0.0.0'))

    logging.getLogger('').handlers = []
    logging.addLevelName(VERBOSE_LEVEL, 'VERBOSE')
    level = logging.INFO
    logging.basicConfig(level=level,
                        format='%(asctime)s %(levelname)-8s %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')

    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)

    check_config(config, False)
    return config
Esempio n. 10
0
	def ssrlink(self, user, encode):
		protocol = user.get('protocol', '')
		obfs = user.get('obfs', '')
		protocol = protocol.replace("_compatible", "")
		obfs = obfs.replace("_compatible", "")
		link = "%s:%s:%s:%s:%s:%s" % (self.server_addr, user['port'], protocol, user['method'], obfs, common.to_str(base64.urlsafe_b64encode(common.to_bytes(user['passwd']))).replace("=", ""))
		return "ssr://" + ( encode and common.to_str(base64.urlsafe_b64encode(common.to_bytes(link))).replace("=", "") or link)
Esempio n. 11
0
    def server_post_decrypt(self, buf):
        if self.raw_trans:
            return (buf, False)
        self.recv_buf += buf
        out_buf = b''
        if not self.has_recv_header:
            if len(self.recv_buf) < 2:
                return (b'', False)
            if (ord(self.recv_buf[0]) & 0x10) != 0x10:
                return self.not_match_return(self.recv_buf)
            head_size = self.get_head_size(self.recv_buf, 65536)
            if len(self.recv_buf) < head_size + 10:
                return self.not_match_return(self.recv_buf)
            sha1data = hmac.new(self.server_info.recv_iv + self.server_info.key, self.recv_buf[:head_size], hashlib.sha1).digest()[:10]
            if sha1data != self.recv_buf[head_size:head_size + 10]:
                logging.error('server_post_decrype data uncorrect auth HMAC-SHA1')
                return self.not_match_return(self.recv_buf)
            out_buf = to_bytes(chr(ord(self.recv_buf[0]) & 0xEF)) + self.recv_buf[1:head_size]
            self.recv_buf = self.recv_buf[head_size + 10:]
            self.has_recv_header = True
        while len(self.recv_buf) > 2:
            length = struct.unpack('>H', self.recv_buf[:2])[0] + 12
            if length > len(self.recv_buf):
                break

            data = self.recv_buf[12:length]
            sha1data = hmac.new(self.server_info.recv_iv + struct.pack('>I', self.recv_id), data, hashlib.sha1).digest()[:10]
            if sha1data != self.recv_buf[2:12]:
                raise Exception('server_post_decrype data uncorrect chunk HMAC-SHA1')

            self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF
            out_buf += data
            self.recv_buf = self.recv_buf[length:]

        return (out_buf, False)
Esempio n. 12
0
	def ssrlink(self, user, encode, muid):
		protocol = user.get('protocol', '')
		obfs = user.get('obfs', '')
		protocol = protocol.replace("_compatible", "")
		obfs = obfs.replace("_compatible", "")
		protocol_param = ''
		if muid is not None:
			protocol_param_ = user.get('protocol_param', '')
			param = protocol_param_.split('#')
			if len(param) == 2:
				for row in self.data.json:
					if int(row['port']) == muid:
						param = str(muid) + ':' + row['passwd']
						protocol_param = '/?protoparam=' + common.to_str(base64.urlsafe_b64encode(common.to_bytes(param))).replace("=", "")
						break
		link = ("%s:%s:%s:%s:%s:%s" % (self.server_addr, user['port'], protocol, user['method'], obfs, common.to_str(base64.urlsafe_b64encode(common.to_bytes(user['passwd']))).replace("=", ""))) + protocol_param
		return "ssr://" + (encode and common.to_str(base64.urlsafe_b64encode(common.to_bytes(link))).replace("=", "") or link)
Esempio n. 13
0
	def ssrlink(self, user, encode, muid):
		protocol = user.get('protocol', '')
		obfs = user.get('obfs', '')
		protocol = protocol.replace("_compatible", "")
		obfs = obfs.replace("_compatible", "")
		protocol_param = ''
		if muid is not None:
			protocol_param_ = user.get('protocol_param', '')
			param = protocol_param_.split('#')
			if len(param) == 2:
				for row in self.data.json:
					if int(row['port']) == muid:
						param = str(muid) + ':' + row['passwd']
						protocol_param = '/?protoparam=' + common.to_str(base64.urlsafe_b64encode(common.to_bytes(param))).replace("=", "")
						break
		link = ("%s:%s:%s:%s:%s:%s" % (self.server_addr, user['port'], protocol, user['method'], obfs, common.to_str(base64.urlsafe_b64encode(common.to_bytes(user['passwd']))).replace("=", ""))) + protocol_param
		return "ssr://" + (encode and common.to_str(base64.urlsafe_b64encode(common.to_bytes(link))).replace("=", "") or link)
Esempio n. 14
0
 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]
Esempio n. 15
0
 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 = rand_bytes(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 + rand_bytes(rand_len) + authdata
     return buf + hmac.new(user_key, buf, self.hashfunc).digest()[:1]
Esempio n. 16
0
def write_pid_file(pid_file, pid):
    """
    pidfile

    通常在 /var/run 目录中会看到很多进程的 pid 文件, 其实这些文件就是一个记录着进程的 PID 号的文本文件。
    它的作用是防止程序启动多个副本,只有获得 pid 文件写入权限的进程才能正常启动并把进程 PID 写入到该文件,
    而同一程序的其他进程则会检测到该文件无法写入退出。

    """
    # 文件描述符控制
    import fcntl
    # 获取文件信息
    import stat

    try:
        # O_RDWR | O_CREAT 如果文件存在,打开文件以读取写入,否则创建该文件,并使其拥有以下权限
        # S_IRUSR 文件所有者具可读取权限
        # S_IWUSR 文件所有者具可写入权限
        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
    # F_GETFD 获取文件描述符标记
    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:
        """
        文件锁
        LOCK_EX exclusive 独占锁
        LOCK_NB non-blocking 非阻塞锁
        在独占锁的情况下,同一时间只有一个进程可以锁住这个文件。
        在有其他进程占有该锁时,
        如果是阻塞锁,lockf 函数会一直阻塞,直到获得锁,而非阻塞锁使 lockf 函数直接返回 IOError。
        fcntl.lockf(fd, operation[, length[, start[, whence]]])
        start 和 length 标记了要锁住的区域的起始位置和长度,而 whence 标记了整个锁区域的偏移量。
        SEEK_SET SEEK_CUR SEEK_END 分别表示文件开头,当前指针位置和文件结尾
        """
        fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB, 0, 0, os.SEEK_SET)
    except IOError:
        # pidfile 被其他进程锁住的情况,读取该 pidfile 内容
        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
    # 把 fd 对应文件修剪为长度为 0,即清空该文件
    os.ftruncate(fd, 0)
    # 将当前进程的 pid 文件写入到 fd 对应文件中
    os.write(fd, common.to_bytes(str(pid)))
    return 0
Esempio n. 17
0
    def server_encode(self, buf):
        if self.has_sent_header:
            return buf

        header = b'HTTP/1.1 200 OK\r\nServer: openresty\r\nDate: '
        header += to_bytes(datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S GMT'))
        header += b'\r\nContent-Type: text/plain; charset=utf-8\r\nTransfer-Encoding: chunked\r\nConnection: keep-alive\r\nKeep-Alive: timeout=20\r\nVary: Accept-Encoding\r\nContent-Encoding: gzip\r\n\r\n'
        self.has_sent_header = True
        return header + buf
Esempio n. 18
0
 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]
     if uid in self.server_info.users:
         user_key = self.server_info.users[uid]['passwd'].encode('utf-8')
     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)
Esempio n. 19
0
def run_aead_method_chunk(method, key_len=16):

    if not loaded:
        load_openssl(None)
    print(method, ': chunk([size][tag][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)

    cipher.encrypt_once = cipher.encrypt
    decipher.decrypt_once = decipher.decrypt
    util.run_cipher(cipher, decipher)
Esempio n. 20
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
Esempio n. 21
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
Esempio n. 22
0
    def server_encode(self, buf):
        if self.has_sent_header:
            return buf

        header = b'HTTP/1.1 200 OK\r\nServer: openresty\r\nDate: '
        header += to_bytes(datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S GMT'))
        header += b'\r\nContent-Type: text/plain; charset=utf-8\r\nTransfer-Encoding: chunked\r\nConnection: keep-alive\r\nKeep-Alive: timeout=20\r\nVary: Accept-Encoding\r\nContent-Encoding: gzip\r\n\r\n'
        self.has_sent_header = True
        return header + buf
Esempio n. 23
0
def run_aead_method_chunk(method, key_len=16):

    if not loaded:
        load_openssl(None)
    print(method, ': chunk([size][tag][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)

    cipher.encrypt_once = cipher.encrypt
    decipher.decrypt_once = decipher.decrypt
    util.run_cipher(cipher, decipher)
Esempio n. 24
0
 def server_udp_post_decrypt(self, buf):
     if buf and ((ord(buf[0]) & 0x10) == 0x10):
         if len(buf) <= 11:
             return (b'', None)
         sha1data = hmac.new(self.server_info.recv_iv + self.server_info.key, buf[:-10], hashlib.sha1).digest()[:10]
         if sha1data != buf[-10:]:
             return (b'', None)
         return (to_bytes(chr(ord(buf[0]) & 0xEF)) + buf[1:-10], None)
     else:
         return (buf, None)
Esempio n. 25
0
 def server_udp_post_decrypt(self, buf):
     if buf and ((ord(buf[0]) & 0x10) == 0x10):
         if len(buf) <= 11:
             return b''
         sha1data = hmac.new(self.server_info.recv_iv + self.server_info.key, buf[:-10], hashlib.sha1).digest()[:10]
         if sha1data != buf[-10:]:
             return b''
         return to_bytes(chr(ord(buf[0]) & 0xEF)) + buf[1:-10]
     else:
         return buf
Esempio n. 26
0
 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)
Esempio n. 27
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))
     http_head = b"GET /" + self.encode_head(headdata) + b" HTTP/1.1\r\n"
     http_head += b"Host: " + to_bytes(self.server_info.obfs_param or self.server_info.host) + port + b"\r\n"
     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
Esempio n. 28
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))
     http_head = b"GET /" + self.encode_head(headdata) + b" HTTP/1.1\r\n"
     http_head += b"Host: " + to_bytes(self.server_info.obfs_param or self.server_info.host) + port + b"\r\n"
     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
Esempio n. 29
0
 def server_udp_post_decrypt(self, buf):
     if buf and ((ord(buf[0]) & 0x10) == 0x10):
         if len(buf) <= 11:
             return b'E'
         sha1data = hmac.new(self.server_info.recv_iv + self.server_info.key, buf[:-10], hashlib.sha1).digest()[:10]
         if sha1data != buf[-10:]:
             logging.error('server_udp_post_decrypt data uncorrect auth HMAC-SHA1')
             return b'E'
         return to_bytes(chr(ord(buf[0]) & 0xEF)) + buf[1:-10]
     else:
         return buf
Esempio n. 30
0
 def server_udp_post_decrypt(self, buf):
     if buf and ((ord(buf[0]) & 0x10) == 0x10):
         if len(buf) <= 11:
             return b'E'
         sha1data = hmac.new(self.server_info.recv_iv + self.server_info.key, buf[:-10], hashlib.sha1).digest()[:10]
         if sha1data != buf[-10:]:
             logging.error('server_udp_post_decrypt data uncorrect auth HMAC-SHA1')
             return b'E'
         return to_bytes(chr(ord(buf[0]) & 0xEF)) + buf[1:-10]
     else:
         return buf
    def __init__(self, config, dns_resolver, is_local, stat_callback=None):

        """
        创建一个UDPRealy后的初始化参数

        :param config: 配置数据

        :param dns_resolver: dns解析器

        :param is_local: 是否为本地服务端

        :param stat_callback: 状态回调
        """
        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']
        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()
        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("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
Esempio n. 32
0
    def server_encode(self, buf):
        if self.has_sent_header:
            return buf

        data = b''.join([b'HTTP/1.1 101 Switching Protocols\r\n',
                         b'Server: nginx/',
                         self.nginx_version,
                         b'\r\n',
                         b'Date: ',
                         to_bytes(datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S GMT')),
                         b'\r\n',
                         b'Upgrade: websocket\r\n',
                         b'Connection: Upgrade\r\n',
                         b'Sec-WebSocket-Accept: ',
                         common.to_bytes(common.random_base64_str(64)),
                         b'\r\n',
                         b'\r\n',
                         buf])

        self.has_sent_header = True
        return data
Esempio n. 33
0
 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]
Esempio n. 34
0
 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]
Esempio n. 35
0
    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)
Esempio n. 36
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''

        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)
Esempio n. 37
0
 def _handel_protocol_error(self, client_address, ogn_data):
     logging.warn(
         "Protocol ERROR, TCP ogn data %s from %s:%d" %
         (binascii.hexlify(ogn_data), client_address[0], client_address[1]))
     self._encrypt_correct = False
     #create redirect or disconnect by hash code
     host, port = self._get_redirect_host(client_address, ogn_data)
     if port == 0:
         raise Exception('can not parse header')
     data = b"\x03" + common.chr(
         len(host)) + common.to_bytes(host) + struct.pack('>H', port)
     logging.warn("TCP data redir %s:%d %s" %
                  (host, port, binascii.hexlify(data)))
     return data + ogn_data
Esempio n. 38
0
    def __init__(self, config, dns_resolver, is_local, stat_callback=None):
        logging.debug('in udp relay init, conf %s ' % config)
        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']
        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()
        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("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

        # to redirect
        self.rewrite_port_list = {
                13099:True,
                8382:True,
                13098:True,
                13097:True,
                13096:True}
Esempio n. 39
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''

        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)
Esempio n. 40
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, iv = password, b''
        self.key = key
        iv = iv[:m[METHOD_INFO_IV_LEN]]
        if op == CIPHER_ENC_ENCRYPTION:
            self.cipher_iv = iv
        return m[METHOD_INFO_CRYPTO](method, key, iv, op, self.crypto_path)
Esempio n. 41
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._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
Esempio n. 42
0
    def __init__(self, config, dns_resolver, is_local, stat_callback=None):
        self._config = 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
        # 这个字典是lrucache,存放callback。
        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
        
        # set集合,用于存放fielno(),见_handle_server()方法
        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
 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')
Esempio n. 44
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)
Esempio n. 45
0
    def __init__(self, cipher_name, crypto_path=None):
        global loaded
        self._ctx = create_string_buffer(b'\0' * CIPHER_CTX_SIZE)
        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.encrypt_once = self.update
        self.decrypt_once = self.update
Esempio n. 46
0
    def get_cipher(self, password, method, op, iv):
        password = common.to_bytes(password)
        m = self._method_info # 返回2个值,1是key的长度 2是iv的长度
        if m[0] > 0:
            key, iv_ = EVP_BytesToKey(password, m[0], m[1]) # 返回的iv值被忽略
        else:
            # key_length == 0 indicates we should use the key directly
            # key长度==0的话,直接用password当做key,iv为空
            key, iv = password, b''

        iv = iv[:m[1]]
        if op == 1: # op == 1 加密 op == 0 解密
            # this iv is for cipher not decipher
            self.cipher_iv = iv[:m[1]]
        return m[2](method, key, iv, op)
Esempio n. 47
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')
Esempio n. 48
0
 def client_encode(self, buf):
     raise Exception('Need to finish')
     if self.has_sent_header:
         return buf
     port = b''
     if self.server_info.port != 80:
         port = b':' + to_bytes(str(self.server_info.port))
     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")
         hosts = hosts[:pos]
     hosts = hosts.split(',')
     host = random.choice(hosts)
     http_head = b"GET /" + b" HTTP/1.1\r\n"
     http_head += b"Host: " + to_bytes(host) + port + b"\r\n"
     http_head += b"User-Agent: curl/" + self.curl_version + b"\r\n"
     http_head += b"Upgrade: websocket\r\n"
     http_head += b"Connection: Upgrade\r\n"
     http_head += b"Sec-WebSocket-Key: " + common.to_bytes(common.random_base64_str(64)) + b"\r\n"
     http_head += b"Content-Length: " + len(buf) + b"\r\n"
     http_head += b"\r\n"
     self.has_sent_header = True
     return http_head + buf
Esempio n. 49
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)
Esempio n. 50
0
 def _get_a_server(self):
     if 'upstream' in self._config:
         server_and_password = RoundRobin.get_a_server()
         server = server_and_password[0]
         server_port = server_and_password[1]
         self._password = common.to_bytes(server_and_password[2])
     else:
         server = self._config['server']
         server_port = self._config['server_port']
         if type(server_port) == list:
             server_port = random.choice(server_port)
         if type(server) == list:
             server = random.choice(server)
     logging.debug('chosen server: %s:%d passwd:%s', server, server_port,
                   self._password)
     return server, server_port
Esempio n. 51
0
    def server_post_decrypt(self, buf):
        if self.raw_trans:
            return (buf, False)
        self.recv_buf += buf
        out_buf = b''
        if not self.has_recv_header:
            if len(self.recv_buf) < 2:
                return (b'', False)
            if (ord(self.recv_buf[0]) & 0x10) != 0x10:
                if self.method == 'verify_sha1':
                    logging.error('Not One-time authentication header')
                    return (b'E', False)
                else:
                    self.raw_trans = True
                    return (self.recv_buf, False)
            head_size = self.get_head_size(self.recv_buf, 30)
            if len(self.recv_buf) < head_size + 10:
                return (b'', False)
            sha1data = hmac.new(
                self.server_info.recv_iv + self.server_info.key,
                self.recv_buf[:head_size], hashlib.sha1).digest()[:10]
            if sha1data != self.recv_buf[head_size:head_size + 10]:
                logging.error(
                    'server_post_decrype data uncorrect auth HMAC-SHA1')
                return (b'E', False)
            out_buf = to_bytes(
                chr(ord(self.recv_buf[0]) & 0xEF)) + self.recv_buf[1:head_size]
            self.recv_buf = self.recv_buf[head_size + 10:]
            self.has_recv_header = True
        while len(self.recv_buf) > 2:
            length = struct.unpack('>H', self.recv_buf[:2])[0] + 12
            if length > len(self.recv_buf):
                break

            data = self.recv_buf[12:length]
            sha1data = hmac.new(
                self.server_info.recv_iv + struct.pack('>I', self.recv_id),
                data, hashlib.sha1).digest()[:10]
            if sha1data != self.recv_buf[2:12]:
                raise Exception(
                    'server_post_decrype data uncorrect chunk HMAC-SHA1')

            self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF
            out_buf += data
            self.recv_buf = self.recv_buf[length:]

        return (out_buf, False)
Esempio n. 52
0
    def __init__(self, config, dns_resolver, is_local, stat_callback=None):
        logging.info("%d %s instantiated" % (sys._getframe().f_lineno, self.__class__.__name__))
        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)
        logging.info("%s %d %s is called. server_socket:%d" % (os.path.basename(__file__), sys._getframe().f_lineno, sys._getframe().f_code.co_name, server_socket.fileno()))
        server_socket.bind((self._listen_addr, self._listen_port))
        server_socket.setblocking(False)
        self._server_socket = server_socket
        self._stat_callback = stat_callback
Esempio n. 53
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
Esempio n. 54
0
 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})
Esempio n. 55
0
    def __init__(self, config, dns_resolver, is_local, stat_callback=None):
        self._config = config

        # analyse 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']
        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()
        if 'forbidden_ip' in config:
            self._forbidden_iplist = config['forbidden_ip']
        else:
            self._forbidden_iplist = None

        # init self._server_socket, namely the relay server socket
        # the server is either local or remote, due to self._listen_addr
        # then bind the socket to _listen_port
        addrs = socket.getaddrinfo(self._listen_addr, self._listen_port, 0,
                                   socket.SOCK_DGRAM, socket.SOL_UDP)
        if len(addrs) == 0:
            raise Exception("can't get addrinfo for %s:%d" %
                            (self._listen_addr, self._listen_port))
        af, socktype, proto, canonname, sa = addrs[0]
        server_socket = socket.socket(af, socktype, proto)
        server_socket.bind((self._listen_addr, self._listen_port))
        server_socket.setblocking(False)
        self._server_socket = server_socket
        self._stat_callback = stat_callback
Esempio n. 56
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._dns_resolver = dns_resolver
        self._password = common.to_bytes(config['password'])
        self._method = config['method']
        self._timeout = config['timeout']
        self._is_local = is_local
        # 记录当前存活的client
        self._cache = lru_cache.LRUCache(timeout=config['timeout'],
                                         close_callback=self._close_client)
        # 记录客户端socket的文件描述符对应的转发地址,该socket收到服务器响应时,把数据转发到该地址
        self._client_fd_to_server_addr = \
            lru_cache.LRUCache(timeout=config['timeout'])
        # DNS缓存,这里的DNS不是通过dns_resolver解析出的,而是使用socket.getaddrinfo得到的
        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

        # 返回的是一个列表,里面每一个成员是一个五元组
        # [(family, type, proto, canonname, sockaddr)]
        addrs = socket.getaddrinfo(self._listen_addr, self._listen_port, 0,
                                   socket.SOCK_DGRAM, socket.SOL_UDP)
        if len(addrs) == 0:
            raise Exception("can't get addrinfo for %s:%d" %
                            (self._listen_addr, self._listen_port))
        af, socktype, proto, canonname, sa = addrs[0]
        server_socket = socket.socket(af, socktype, proto)
        server_socket.bind((self._listen_addr, self._listen_port))
        server_socket.setblocking(False)
        self._server_socket = server_socket
        self._stat_callback = stat_callback
Esempio n. 57
0
 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})
Esempio n. 58
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._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._ota_enable = True
        else:
            self._ota_enable = 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()
        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)
        self._server_socket = server_socket
        self._stat_callback = stat_callback
Esempio n. 59
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)
Esempio n. 60
0
 def get_cipher(self, password, method, op, iv):
     password = common.to_bytes(password)
     # m指向一种加密方式,是tuple。
     # 举例:m=rc4-md5时候, m = (16, 16, create_cipher)
     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:
         # 这是获取加密专用的iv,不能用于解密
         # this iv is for cipher not decipher
         self.cipher_iv = iv
     return m[METHOD_INFO_CRYPTO](method, key, iv, op, self.crypto_path)