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
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
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
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()
def _send_packet(self, typ: int, payload: bytes) -> None: send_packet(self.sock, typ, payload)
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()