Exemplo n.º 1
0
 def connection_requested(self, dest_host, dest_port, orig_host, orig_port):
     if dest_port == 7:
         return handle_connection
     else:
         raise asyncssh.ChannelOpenError(
                   asyncssh.OPEN_ADMINISTRATIVELY_PROHIBITED,
                   'Only echo connections allowed')
Exemplo n.º 2
0
 def connection_requested(self, dest_host, dest_port, orig_host, orig_port):
     if dest_port == 80:
         return True
     else:
         raise asyncssh.ChannelOpenError(
             asyncssh.OPEN_ADMINISTRATIVELY_PROHIBITED,
             'Only connections to port 80 are allowed')
def connection_requested(orig_host, orig_port):
    global conn

    if orig_host in ('127.0.0.1', '::1'):
        return conn.forward_connection('localhost', 80)
    else:
        raise asyncssh.ChannelOpenError(
            asyncssh.OPEN_ADMINISTRATIVELY_PROHIBITED,
            'Connections only allowed from localhost')
Exemplo n.º 4
0
    async def connect_to_server(self, host, port):
        # Split off any index from the name, defaulting to the most recent
        # client (index 0)
        name, index = util.split_hostname_index(host, 0)

        # Find the server
        servers = self.daemon.listener_names[name]
        if not servers:
            logging.error("Server %s not found", name)
            raise asyncssh.ChannelOpenError(asyncssh.OPEN_CONNECT_FAILED,
                                            "Server %s not found" % (name, ),
                                            "en")

        try:
            server = servers[index]
        except IndexError:
            logging.error("Invalid index %s for server %s", index, name)
            raise asyncssh.ChannelOpenError(
                asyncssh.OPEN_CONNECT_FAILED,
                "Invalid index %s for server %s" % (index, name), "en")

        # Find the port
        logging.debug("%s", server.listeners)
        listener = server.listeners.get(port, None)
        if not listener:
            logging.error("Port %s on server %s not found", port,
                          server.hostname)
            raise asyncssh.ChannelOpenError(
                asyncssh.OPEN_CONNECT_FAILED,
                "Port %s on server %s not found" % (port, server.hostname),
                "en")

        # This creates a connection back to the server that requested the port
        # forward (using the listener). It uses two instances of the
        # SSHForwarder class to forward data between this server connection and
        # the requested incoming connection.
        # TODO: SSHForwarder is not documented as a public API. Should we use
        # it?
        peer_factory = asyncssh.forward.SSHForwarder
        _, conn = await listener.create_connection(peer_factory)
        return asyncssh.forward.SSHForwarder(conn)
Exemplo n.º 5
0
    def connection_requested(self, dest_host, dest_port, orig_host, orig_port):
        """
        The client requested us to make a connection to a given host and port.

        The original host and port indicate the source of the connection on
        client side (but are irrelevant here).
        """
        if config.ENABLE_AUTH and Permissions.INITIATE not in self.permissions:
            logging.error("No INITIATE permission, denying request")
            raise asyncssh.ChannelOpenError(
                asyncssh.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
                "Insufficient permissions to connect", "en")
        return self.connect_to_server(dest_host, dest_port)
Exemplo n.º 6
0
    def connection_requested(self, dest_host, dest_port, orig_host, orig_port):
        # Only allow localhost connections
        if dest_host != '127.0.0.1':
            raise asyncssh.ChannelOpenError(
                asyncssh.OPEN_ADMINISTRATIVELY_PROHIBITED,
                "Only localhost connections allowed")

        username = self.conn.get_extra_info('username')
        user_pod = UserPod(username, self.namespace)

        cache_key = f'{user_pod.pod_name}:{dest_port}'

        if cache_key in self.forwarding_processes:
            proc = self.forwarding_processes[cache_key]

            port = proc.port
        else:
            port = random_port()
            command = [
                'kubectl', 'port-forward', user_pod.pod_name,
                f'{port}:{dest_port}'
            ]

            async def _socket_ready(proc):
                try:
                    sock = socket.create_connection(('127.0.0.1', port))
                    sock.close()
                    return True
                except:
                    # FIXME: Be more specific in errors we are catching?
                    return False

            proc = SupervisedProcess('kubectl',
                                     *command,
                                     always_restart=True,
                                     ready_func=_socket_ready)
            self.forwarding_processes[cache_key] = proc
            proc.port = port

        async def transfer_data(reader, writer):
            # Make sure our pod is running
            async for status in user_pod.ensure_running():
                if status == PodState.RUNNING:
                    break
            # Make sure our kubectl port-forward is running
            await proc.start()
            await proc.ready()

            # Connect to the local end of the kubectl port-forward
            (upstream_reader, upstream_writer) = await asyncio.open_connection(
                '127.0.0.1', port)

            # FIXME: This should be as fully bidirectional as possible, with minimal buffering / timeouts
            while not reader.at_eof():
                try:
                    data = await asyncio.wait_for(reader.read(8092),
                                                  timeout=0.1)
                except asyncio.TimeoutError:
                    data = None
                if data:
                    upstream_writer.write(data)
                    await upstream_writer.drain()

                try:
                    in_data = await asyncio.wait_for(
                        upstream_reader.read(8092), timeout=0.1)
                except asyncio.TimeoutError:
                    in_data = None
                if in_data:
                    writer.write(in_data)
                    await writer.drain()
                if upstream_reader.at_eof():
                    break
            writer.close()

        return transfer_data