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')
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')
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)
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)
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