示例#1
0
  def socks_auth(self, client_sock : socket.socket, client_addr : Tuple[str, int]):
    """
    Initial greeting from client:
    +---------------------+
    | VER | LEN | METHODS |
    +---------------------+
    """
    future = Future()
    reg_socket_future_read(future, client_sock)
    yield future
    greeting : bytes = client_sock.recv(4096)

    if greeting == b'shutdown':
      raise ShutdownException('')

    try:
      ver, length, methods = decode_greating(greeting)
      if not ver == 5 or 0 not in methods:
        return
    except ValueError as e:
      raise e

    """
    The server's choice is communicated:
    +-----+--------+
    | VER | METHOD |
    +--------------+
    """
    client_sock.send(bytes([5, 0]))
    future = Future()
    reg_socket_future_write(future, client_sock)
    yield future
示例#2
0
    def wait_client_connection(self, remote_socks: List[socket.socket]):
        future = Future()
        reg_multi_sockets_future_read(future, remote_socks)
        remote_sock = yield future
        local_sock, local_addr = remote_sock.accept()
        local_sock.setblocking(False)

        logging.info("Connection from %s:%d to %s:%d" %
                     (local_addr + remote_sock.getsockname()))
        self.loop.add_event(self.local_handle(local_sock, local_addr))
示例#3
0
  def wait_client_connection(self, local_socks: List[socket.socket]):
    future = Future()
    reg_multi_sockets_future_read(future, local_socks)
    local_sock = yield future
    client_sock, client_addr = local_sock.accept()
    client_sock.setblocking(False)
    listen_ip, listen_port = client_sock.getsockname()
    dest_addr = self.port_to_address[listen_port]

    self.loop.add_event(self.client_handle(client_sock, client_addr, dest_addr))
示例#4
0
 def wait_client_connection(self, local_sock: socket.socket):
   future = Future()
   reg_socket_future_read(future, local_sock)
   yield future
   client_sock, client_addr = local_sock.accept()
   print(client_addr)
   print(client_sock.getsockname())
   client_sock.setblocking(False)
   logging.info("Connection from %s:%s" % client_addr)
   self.loop.add_event(self.client_handle(client_sock, client_addr))
示例#5
0
  def local_relay(self,
                  client_sock : socket.socket,
                  client_addr : Tuple[str, int],
                  dest_addr: Tuple[str, int]
                  ):
    try:

      remote_sock = socket.socket()
      remote_sock.setblocking(False)

      try:
        if isinstance(self.remote_port, int):
          remote_sock.connect((self.remote_ip, self.remote_port))
        elif isinstance(self.remote_port, list):
          port_choice = self.select_port(self.remote_port)
          remote_sock.connect((self.remote_ip, port_choice))
        else:
          raise ValueError(self.remote_port)
      except BlockingIOError as e:
        pass

      logging.info("connected to %s" % (remote_sock.getsockname(),))

      future = Future()
      reg_socket_future_write(future, remote_sock)
      yield future

      sock_addr = create_socks_addr(*dest_addr)
      remote_sock.send(self.encryptor.encode(sock_addr, 0))
      len_sock_addr = len(sock_addr)

      def client_data_to_local_data(data : bytes, offset : int):
        return self.encryptor.encode(data, offset + len_sock_addr), 0


      def local_data_to_client_data(data : bytes, offset : int):
        # return self.encryptor.decode(data, offset)
        decoded = self.encryptor.decode(data, offset)
        #logging.debug("data get from remote (%d, %d):\n%s" % (offset, len(decoded), decoded))
        return decoded, 0

      relay_start = time.time()
      yield from relay(client_sock, remote_sock,
                       client_data_to_local_data, local_data_to_client_data)
      logging.info("[%s:%d] for %r relay used %f" % (client_addr + (dest_addr, time.time() - relay_start)))


    except ValueError as e:
      logging.error(str(e))
      traceback.print_exc()
示例#6
0
  def relay_connection(self, client_sock : socket.socket, client_addr : Tuple[str, int]):
    """
    Address: [1-byte type][variable-length host][2-byte port]
    The client's connection request is:
    +-----+----------+----------+-----------+-----------+----------+
    | VER | CMD CODE | RESERVED | ADDR TYPE | DEST TYPE | PORT NUM |
    +-----+----------+----------+-----------+-----------+----------+
    """
    future = Future()
    reg_socket_future_read(future, client_sock)
    yield future
    check_socket(client_sock)
    request_bytes = client_sock.recv(4096)
    try:
      logging.debug(str(decode_connection_request(request_bytes)))
    except:
      pass

    yield from self.local_relay(client_sock, client_addr, request_bytes)
示例#7
0
def relay(
        sock1: socket.socket,
        sock2: socket.socket,
        sock1_data_to_sock2_data=lambda x, offset: (x, 0),
        sock2_data_to_sock1_data=lambda x, offset: (x, 0),
):
    def relay_callback(source_sock, tg_sock, event_key, event_mask):
        future.set_result((source_sock, tg_sock, event_key, event_mask))

    data_queues = {sock1.fileno(): [], sock2.fileno(): []}

    data_offset = {sock1.fileno(): 0, sock2.fileno(): 0}

    try:
        stopped = 0

        while True:
            future = Future()

            register_read_write(
                sock1, lambda k, m: relay_callback(sock1, sock2, k, m))
            register_read_write(
                sock2, lambda k, m: relay_callback(sock2, sock1, k, m))

            source_sock, tg_sock, event_key, event_mask = yield future
            unregister(sock1)
            unregister(sock2)

            try:

                if event_mask & EVENT_WRITE != 0:
                    # If a write is ready, write the corresponding data to it
                    if len(data_queues[source_sock.fileno()]) > 0:
                        data = data_queues[source_sock.fileno()][0]
                        check_socket(source_sock)
                        sent = source_sock.send(data)

                        # if source_sock.fileno() == sock2.fileno():
                        #   logging.debug("data sent to sock2 (%d):\n%s" % (sent, data[0 : sent]))

                        if sent < len(data):
                            data_queues[source_sock.fileno()][0] = data[sent:]
                        else:
                            data_queues[source_sock.fileno()].pop(0)
                        #logging.debug("sent %d" % len(data))
                if event_mask & EVENT_READ != 0:
                    check_socket(source_sock)

                    data = source_sock.recv(4096)
                    if len(data) == 0:
                        stopped += 1
                        if stopped >= 2:
                            break
                    if tg_sock.fileno() == sock2.fileno():
                        encoded_data, adjust = sock1_data_to_sock2_data(
                            data, data_offset[sock1.fileno()])
                        data_offset[sock1.fileno()] += len(data) + adjust
                    else:
                        encoded_data, adjust = sock2_data_to_sock1_data(
                            data, data_offset[sock2.fileno()])
                        data_offset[sock2.fileno()] += len(data) + adjust

                    data_queues[tg_sock.fileno()].append(encoded_data)

            except IOError as e:
                if e.errno == errno.EWOULDBLOCK:
                    pass
                elif e.errno == errno.ENOTCONN:
                    pass
                elif e.errno == errno.EAGAIN:
                    pass
                else:
                    logging.error("relay IOError: %s" % e)
                    break

    finally:
        check_socket(sock1)
        check_socket(sock2)
        sock1.close()
        sock2.close()
示例#8
0
  def local_relay(self, client_sock : socket.socket, client_addr : Tuple[str, int], request_bytes):
    try:
      try:
        ver, cmd_code, addr_type, dest_addr, port = decode_connection_request(request_bytes)
        if addr_type == 3:
          logging.info("[%s:%d] for %r" % (client_addr + (dest_addr,)))
        elif addr_type == 1:
          logging.info("[%s:%d] for [%s:%r]" % (client_addr + (bytes_ip_to_string(dest_addr), port)))
      except Exception as e:
        raise ValueError("Invalid request bytes %r from %s:%d" % ((request_bytes,) + client_addr))

      remote_sock = socket.socket()
      remote_sock.setblocking(False)

      try:
        if isinstance(self.remote_port, int):
          remote_sock.connect((self.remote_ip, self.remote_port))
        elif isinstance(self.remote_port, list):
          port_choice = self.select_port(self.remote_port)
          remote_sock.connect((self.remote_ip, port_choice))
        else:
          raise ValueError(self.remote_port)
      except BlockingIOError as e:
        pass

      logging.info("connected to %s" % (remote_sock.getsockname(),))

      future = Future()
      reg_socket_future_write(future, remote_sock)
      yield future

      future = Future()
      reg_socket_future_write(future, client_sock)
      yield future

      sock_name = client_sock.getsockname()
      client_hex_addr = socket.inet_aton(sock_name[0])
      client_hex_port = port_to_hex_string(sock_name[1])
      #response = encode_connection_repsonse(ver, 0, addr_type, dest_addr, port)
      response = b'\x05\x00\x00\x01' + client_hex_addr + client_hex_port
      logging.info("req bytes:  %r" % request_bytes)
      logging.info("response:  %r" % response)

      check_socket(client_sock)
      client_sock.send(response)

      sock_addr = get_socks_addr_bytes_from_request(request_bytes)
      remote_sock.send(self.encryptor.encode(sock_addr, 0))
      len_sock_addr = len(sock_addr)

      def client_data_to_local_data(data : bytes, offset : int):
        return self.encryptor.encode(data, offset + len_sock_addr), 0


      def local_data_to_client_data(data : bytes, offset : int):
        # return self.encryptor.decode(data, offset)
        decoded = self.encryptor.decode(data, offset)
        #logging.debug("data get from remote (%d, %d):\n%s" % (offset, len(decoded), decoded))
        return decoded, 0

      relay_start = time.time()
      yield from relay(client_sock, remote_sock,
                       client_data_to_local_data, local_data_to_client_data)
      logging.info("[%s:%d] for %r relay used %f" % (client_addr + (dest_addr, time.time() - relay_start)))


    except ValueError as e:
      logging.error(str(e))
      traceback.print_exc()