Exemplo n.º 1
0
class RemoteConnection(asyncore.dispatcher):

    buffer_send_raw = b''
    buffer_send = b''
    buffer_recv_raw = b''
    buffer_recv = b''
    local = None
    cipher = None

    def __init__(self, host, port, token):
        asyncore.dispatcher.__init__(self)
        self.buffer_send_raw += token
        magic = bytearray(os.urandom(MAGIC_LEN))
        self.buffer_send_raw += magic
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, port))
        self.cipher = AESCipher()

    def handle_connect(self):
        pass

    def handle_close(self):
        LOGGER.info('%s remote close', id(self))
        self.local.handle_close()
        self.close()

    def handle_read(self):
        data = self.recv(BUF_SIZE)
        #LOGGER.debug('%s remote recv: %s', id(self), data)
        self.buffer_recv += data
        ddata, dlen = self.cipher.decrypt_all(self.buffer_recv)
        self.buffer_recv_raw += ddata
        self.buffer_recv = self.buffer_recv[dlen:]
        if len(self.buffer_recv_raw) > 0:
            self.local.buffer_send += self.buffer_recv_raw
            self.buffer_recv_raw = b''

    def writable(self):
        if len(self.buffer_send_raw) > 0:
            self.buffer_send += self.cipher.encrypt_all(self.buffer_send_raw)
            self.buffer_send_raw = b''
        return (len(self.buffer_send) > 0)

    def handle_write(self):
        sent = self.send(self.buffer_send)
        #LOGGER.debug('%s remote send %s', id(self), self.buffer[:sent])
        self.buffer_send = self.buffer_send[sent:]
Exemplo n.º 2
0
class LocalConnection(asyncore.dispatcher):

    buffer_recv = b''
    buffer_recv_raw = b''
    buffer_send = b''
    buffer_send_raw = b''
    server = None
    remote = None
    stage = STAGE_INIT
    cipher = None
    token = None

    def __init__(self, sock):
        super().__init__(sock)
        self.cipher = AESCipher()

    def handle_read(self):
        data = self.recv(BUF_SIZE)
        if not data:
            return
        if self.token:
            self.server.add_traffic(self.token, len(data) / (1024.0 * 1024.0))
        self.buffer_recv += data
        ddata, dlen = self.cipher.decrypt_all(self.buffer_recv)
        self.buffer_recv_raw += ddata
        self.buffer_recv = self.buffer_recv[dlen:]

        #LOGGER.debug('%s local recv %s', id(self), data)
        while True:
            if self.stage == STAGE_INIT:
                if len(self.buffer_recv_raw) < TOKEN_LEN + MAGIC_LEN:
                    return
                token = self.buffer_recv_raw[0:TOKEN_LEN]
                self.token = token
                magic = self.buffer_recv_raw[TOKEN_LEN:TOKEN_LEN + MAGIC_LEN]
                LOGGER.info("%s accept token: %s, magic: %s", id(self),
                            token.hex(), magic.hex())

                # auth
                if not self.server.query_token(token):
                    LOGGER.warning('%s token not exist!', id(self))
                    self.handle_close()
                    return
                if not self.server.query_magic(magic):
                    LOGGER.warning('%s duplicated magic!', id(self))
                    self.handle_close()
                    return

                self.buffer_recv_raw = self.buffer_recv_raw[TOKEN_LEN +
                                                            MAGIC_LEN:]
                self.stage = STAGE_HANDSHAKE
                continue
            elif self.stage == STAGE_HANDSHAKE:
                if len(self.buffer_recv_raw) < 1:
                    return
                atyp = self.buffer_recv_raw[0]
                addr = ""
                port = 0
                if atyp == 1:
                    if len(self.buffer_recv_raw) < 7:
                        return
                    addr = str(self.buffer_recv_raw[1]) + '.' + str(self.buffer_recv_raw[2]) + \
                        '.' + str(self.buffer_recv_raw[3]) + '.' + str(self.buffer_recv_raw[4])
                    port = self.buffer_recv_raw[
                        5] * 256 + self.buffer_recv_raw[6]
                    self.buffer_recv_raw = self.buffer_recv_raw[7:]
                elif atyp == 3:
                    if len(self.buffer_recv_raw) < 2:
                        return
                    alen = self.buffer_recv_raw[1]
                    if len(self.buffer_recv_raw) < 2 + alen + 2:
                        return
                    addr = self.buffer_recv_raw[2:2 + alen].decode('utf-8')
                    port = self.buffer_recv_raw[
                        2 + alen] * 256 + self.buffer_recv_raw[2 + alen + 1]
                    self.buffer_recv_raw = self.buffer_recv_raw[2 + alen + 2:]
                LOGGER.info('%s local handshake: %s:%d', id(self), addr, port)
                try:
                    self.remote = RemoteConnection(addr, port)
                except Exception:
                    LOGGER.error('%s cannot connect to %s:%d', id(self), addr,
                                 port)
                    return
                self.remote.local = self
                self.remote.buffer += self.buffer_recv_raw
                self.buffer_recv_raw = b''
                self.stage = STAGE_STREAM
                continue
            elif self.stage == STAGE_STREAM:
                self.remote.buffer += self.buffer_recv_raw
                self.buffer_recv_raw = b''
            return

    def writable(self):
        if len(self.buffer_send_raw) > 0:
            self.buffer_send += self.cipher.encrypt_all(self.buffer_send_raw)
            self.buffer_send_raw = b''
        return (len(self.buffer_send) > 0 and self.stage == STAGE_STREAM)

    def handle_write(self):
        sent = self.send(self.buffer_send)
        #LOGGER.debug('%s local send %s', id(self), self.buffer[:sent])
        self.buffer_send = self.buffer_send[sent:]
        if self.token:
            self.server.add_traffic(self.token, sent / (1024.0 * 1024.0))

    def handle_close(self):
        LOGGER.info('%s local close', id(self))
        if self in self.server.conn_list:
            self.server.conn_list.remove(self)
        self.close()