Beispiel #1
0
def service_to_public(conn, addr):
    logging.info('service to public from addr:%s' % str(addr))
    proxy_sock = None

    while True:
        try:
            chunk = conn.recv(BUFF_SIZE)
            if not chunk:
                break

            if not proxy_sock:
                rport = conn.getsockname()[1]

                if rport in client_reglist:
                    logging.info(
                        'public conn come in, rport=%s found in reg_client.' %
                        str(rport))
                    info = client_reglist[rport]
                    protocol.send_packet(info['ctrl_sock'],
                                         protocol.req_proxy())

                    reg_info = dict()
                    reg_info['rport'] = rport
                    reg_info['public_sock'] = conn
                    reg_info['queue'] = Queue()

                    public_reglist[info['client_id']].put(reg_info)
                    proxy_sock = reg_info['queue'].get()

            if proxy_sock:
                protocol.send_buff(proxy_sock, chunk)

        except socket.error as e:
            logging.info('public peer close')
            break
Beispiel #2
0
def parse_regproxy(js_buff, conn):
    client_id = ''

    if 'Payload' in js_buff:
        client_id = js_buff['Payload'].get('ClientId')
    if not (client_id in public_reglist):
        return None
    info = public_reglist[client_id].get()
    if not info:
        return None
    pub_sock = info['public_sock']
    rport = info['rport']
    sock_info = pub_sock.getpeername()
    pub_addr = sock_info[0] + ':' + str(sock_info[1])
    logging.info('recv Regproxy, pack_clientid:%s, public_addr:%s' %
                 (client_id, pub_addr))
    protocol.send_packet(conn, protocol.start_proxy(rport,
                                                    client_addr=pub_addr))
    info['queue'].put(conn)
    return pub_sock
Beispiel #3
0
def parse_reqtunnel(js_buff, conn, client_id):
    if 'Payload' in js_buff:
        rport = js_buff['Payload'].get('Rport', random.randint(1024, 65535))
        error = 'the tunnel for rport=%s is already registered' % str(rport)
        logging.info('recv reqtunnel, rport=%s' % str(rport))

        if rport in client_reglist:
            protocol.send_packet(conn, protocol.new_tunnel(error=error))
            conn.shutdown(socket.SHUT_WR)
            logging.info('recv reqtunnel but already registered, rport=%s' %
                         str(rport))
            return False

        logging.info('listening rport=%s' % str(rport))
        try:
            listen_sock = cross_nat_run('', rport, False, False,
                                        service_to_public)
        except socket.error as e:
            logging.info('recv reqtunnel ', e)
            protocol.send_packet(conn, protocol.new_tunnel(error=error))
            return False
        info = dict()
        info['ctrl_sock'] = conn
        info['client_id'] = client_id
        info['listen_sock'] = listen_sock
        client_reglist[rport] = info
        tunnels_tab[client_id].append(rport)

        protocol.send_packet(
            conn, protocol.new_tunnel(js_buff['Payload']['ReqId'], rport))
        return True
Beispiel #4
0
def client_handle(sock, phase, state=State.INIT, to_sock=None):
    logging.info('client_handle, %s, %s' % (phase, state))
    global ctrl_sock
    global client_id
    recv_buff = bytes()
    while True:
        try:
            if state == State.INIT:
                if phase == Phase.AUTH:
                    protocol.send_packet(sock, protocol.auth())
                    logging.info('sent auth to revserv_server %s' %
                                 sock.getpeername()[0])
                    state = State.WAIT
                    logging.info('client_handle, %s, change to %s' %
                                 (phase, state))

                if phase == Phase.PROXY:
                    protocol.send_packet(sock, protocol.reg_proxy(client_id))
                    logging.info('sent reg_proxy to revserv_server %s' %
                                 sock.getpeername()[0])
                    state = State.WAIT
                    logging.info('client_handle, %s, change to %s' %
                                 (phase, state))

                if phase == Phase.PRIVATE:
                    state = State.TRANSFER
                    logging.info('client_handle, %s, change to %s' %
                                 (phase, state))

            recv_chunk = sock.recv(BUFF_SIZE)
            if not recv_chunk:
                break

            if len(recv_chunk) > 0:
                if not recv_buff:
                    recv_buff = recv_chunk
                else:
                    recv_buff += recv_chunk

            if phase == Phase.AUTH or (phase == Phase.PROXY
                                       and state == State.WAIT):
                pack_len = protocol.bytes_to_len(recv_buff[0:8])
                if len(recv_buff) >= pack_len:
                    buff = recv_buff[8:8 + pack_len].decode('utf-8')
                    js = protocol.json.loads(buff)

                    if phase == Phase.AUTH:
                        if js['Type'] == 'AuthResp':
                            client_id = js['Payload']['ClientId']
                            logging.info('recv AuthResp, client_id:%s' %
                                         client_id)
                            for tunnel in tunnels:
                                protocol.send_packet(
                                    sock,
                                    protocol.req_tunnel(tunnel.get('rport')))
                                logging.info('sent ReqTunnel, rport:%s' %
                                             tunnel.get('rport'))

                        if js['Type'] == 'NewTunnel':
                            if js['Payload']['Error'] != '':
                                logging.info('recv NewTunnel. Error:%s' %
                                             js['Payload']['Error'])
                            else:
                                laddr = protocol.get_local_addr(
                                    tunnels, js['Payload']['Rport'])
                                logging.info(
                                    'recv NewTunnel. Established lport:%s<->rport:%s'
                                    % (laddr.get('lport'),
                                       js['Payload']['Rport']))

                        if js['Type'] == 'ReqProxy':
                            proxy_sock = connect_server(
                                revserv_server, revserv_port)
                            logging.info(
                                'recv ReqProxy, start proxy connection.')
                            if proxy_sock:
                                thread_proxy = threading.Thread(
                                    target=client_handle,
                                    args=(proxy_sock, Phase.PROXY))
                                thread_proxy.setDaemon(True)
                                thread_proxy.start()

                    if phase == Phase.PROXY:
                        if js['Type'] == 'StartProxy':
                            logging.info('recv StartProxy, rport:%s' %
                                         js['Payload']['Rport'])
                            local_addr = protocol.get_local_addr(
                                tunnels, js['Payload']['Rport'])
                            priv_sock = connect_local(local_addr.get('lhost'),
                                                      local_addr.get('lport'))
                            if priv_sock:
                                thread_private = threading.Thread(
                                    args=(priv_sock, Phase.PRIVATE, State.INIT,
                                          sock),
                                    target=client_handle)
                                thread_private.setDaemon(True)
                                thread_private.start()
                                state = State.TRANSFER
                                logging.info(
                                    'client_handle, %s, change to %s' %
                                    (phase, state))
                                to_sock = priv_sock

                    if js['Type'] == 'Echo':
                        logging.info('recv echo from %s' %
                                     sock.getpeername()[0])
                        protocol.send_packet(sock, protocol.ack())

                    if len(recv_buff) == (pack_len + 8):
                        recv_buff = bytes()
                    else:
                        recv_buff = recv_buff[8 + pack_len:]

            if phase == Phase.PRIVATE or (phase == Phase.PROXY
                                          and state == State.TRANSFER):
                protocol.send_buff(to_sock, recv_buff)
                recv_buff = bytes()

        except socket.error as err:
            print("%s %s %s" % (phase, state, err))
            break

    if phase == Phase.AUTH:
        ctrl_sock = False
    if phase == Phase.PRIVATE:
        try:
            to_sock.shutdown(socket.SHUT_WR)
        except socket.error:
            to_sock.close()
    sock.close()
Beispiel #5
0
 def _send_packet(self, typ: int, payload: bytes) -> None:
     send_packet(self.sock, typ, payload)
Beispiel #6
0
def service_to_ctrl_channel(conn, addr):
    logging.info('service to ctrl channel, addr:%s' % str(addr))
    global tunnels_tab
    public_sock = None
    client_id = ''
    recv_buff = bytes()
    while True:
        try:
            chunk = conn.recv(BUFF_SIZE)
            if not chunk:
                break

            if len(chunk) > 0:
                if not recv_buff:
                    recv_buff = chunk
                else:
                    recv_buff += chunk

            if len(recv_buff) < 8:
                continue

            pack_len = protocol.bytes_to_len(recv_buff[:8])
            if len(recv_buff) >= (pack_len + 8):
                str_buff = recv_buff[8:8 + pack_len].decode('utf-8')
                js_buff = json.loads(str_buff)
                pack_type = js_buff.get('Type')

                ip, _ = conn.getpeername()
                if pack_type == 'Auth' and 'Payload' in js_buff:
                    if js_buff['Payload'].get('User') == global_config['username'] and \
                       js_buff['Payload'].get('Password') == global_config['password']:
                        client_id = protocol.get_str_md5(str(time.time()))
                        tunnels_tab[client_id] = list()
                        public_reglist[client_id] = Queue()
                        auth_tab[ip] = True
                        protocol.send_packet(
                            conn, protocol.auth_resp(client_id=client_id))
                    else:
                        auth_tab[ip] = False
                        logging.info('auth failed1')
                        break
                else:
                    if ip not in auth_tab or not auth_tab[ip]:
                        logging.info('auth failed2')
                        break

                if pack_type == 'ReqTunnel':
                    parse_reqtunnel(js_buff, conn, client_id)
                if pack_type == 'RegProxy':
                    sock = parse_regproxy(js_buff, conn)
                    if sock:
                        public_sock = sock

                if len(recv_buff) == (8 + pack_len):
                    recv_buff = bytes()
                else:
                    recv_buff = recv_buff[8 + pack_len:]

            if public_sock:
                protocol.send_buff(public_sock, recv_buff)
                recv_buff = bytes()

        except Exception as e:
            logging.info(e)
            break

    if public_sock:
        public_sock.close()

    if client_id in public_reglist:
        del public_reglist[client_id]

    if client_id in tunnels_tab:
        for port in tunnels_tab[client_id]:
            if port in client_reglist:
                listen_sock = client_reglist[port].get('listen_sock')
                if listen_sock:
                    listen_sock.close()
                del client_reglist[port]
        del tunnels_tab[client_id]
    logging.info('close peer %s:%s' %
                 (conn.getpeername()[0], conn.getpeername()[1]))
    conn.close()