def _tunnel_to_kernel(self, connection_info, sshserver, sshkey=None): """Tunnel connections to a kernel over SSH This will open five SSH tunnels from localhost on this machine to the ports associated with the kernel. See jupyter_client/connect.py for original implementation. """ cf = connection_info lports = tunnel.select_random_ports(5) rports = cf['shell_port'], cf['iopub_port'], cf['stdin_port'], cf[ 'hb_port'], cf['control_port'] port_names = "SHELL", "IOPUB", "STDIN", "HB", "CONTROL" remote_ip = cf['ip'] if not tunnel.try_passwordless_ssh(sshserver, sshkey): raise RuntimeError( "Must use passwordless scheme by setting up the SSH public key on the cluster nodes" ) for lp, rp, pn in zip(lports, rports, port_names): self._create_ssh_tunnel(pn, lp, rp, remote_ip, sshserver, sshkey) return tuple(lports)
def _set_comm_port(self, port): """Set comm port.""" if port is None or port == self.remote_comm_port: return self.remote_comm_port = port client = self.kernel_client if hasattr(client, 'ssh_parameters'): # Need to tunnel port hostname, sshkey, password = client.ssh_parameters local_port = zmqtunnel.select_random_ports(1)[0] remote_port = port remote_ip = client.ip self.ssh_tunnel(local_port, remote_port, hostname, remote_ip, sshkey, password, timeout=10) port = local_port if not (hasattr(client, 'comm_port') and client.comm_port == port): client.comm_port = port identity = client.session.bsession socket = client._create_connected_socket('comm', identity=identity) client.comm_channel = client.shell_channel_class( socket, client.session, client.ioloop) # We emit in case we are waiting on this self._sig_comm_port_changed.emit()
def _tunnel_to_kernel(self, connection_info, server, port=ssh_port, key=None): """Tunnel connections to a kernel over SSH This will open five SSH tunnels from localhost on this machine to the ports associated with the kernel. See jupyter_client/connect.py for original implementation. """ cf = connection_info lports = tunnel.select_random_ports(5) rports = cf['shell_port'], cf['iopub_port'], cf['stdin_port'], cf[ 'hb_port'], cf['control_port'] channels = KernelChannel.SHELL, KernelChannel.IOPUB, KernelChannel.STDIN, \ KernelChannel.HEARTBEAT, KernelChannel.CONTROL remote_ip = cf['ip'] if not tunnel.try_passwordless_ssh(server + ":" + str(port), key): raise RuntimeError( "Must use password-less scheme by setting up the SSH public key on the cluster nodes" ) for lp, rp, kc in zip(lports, rports, channels): self._create_ssh_tunnel(kc, lp, rp, remote_ip, server, port, key) return tuple(lports)
def _tunnel_to_port(self, port_name, remote_ip, remote_port, sshserver, sshkey=None): """Analogous to _tunnel_to_kernel, but deals with a single port. This will typically called for any one-off ports that require tunnelling. Note - this method assumes that passwordless ssh is in use and has been previously validated. """ local_port = tunnel.select_random_ports(1)[0] self._create_ssh_tunnel(port_name, local_port, remote_port, remote_ip, sshserver, sshkey) return local_port
def tunnel_to_kernel(connection_info, sshserver, sshkey=None): """tunnel connections to a kernel via ssh This will open four SSH tunnels from localhost on this machine to the ports associated with the kernel. They can be either direct localhost-localhost tunnels, or if an intermediate server is necessary, the kernel must be listening on a public IP. Parameters ---------- connection_info : dict or str (path) Either a connection dict, or the path to a JSON connection file sshserver : str The ssh sever to use to tunnel to the kernel. Can be a full `user@server:port` string. ssh config aliases are respected. sshkey : str [optional] Path to file containing ssh key to use for authentication. Only necessary if your ssh config does not already associate a keyfile with the host. Returns ------- (shell, iopub, stdin, hb) : ints The four ports on localhost that have been forwarded to the kernel. """ from zmq.ssh import tunnel if isinstance(connection_info, string_types): # it's a path, unpack it with open(connection_info) as f: connection_info = json.loads(f.read()) cf = connection_info lports = tunnel.select_random_ports(4) rports = cf['shell_port'], cf['iopub_port'], cf['stdin_port'], cf[ 'hb_port'] remote_ip = cf['ip'] if tunnel.try_passwordless_ssh(sshserver, sshkey): password = False else: password = getpass("SSH Password for %s: " % cast_bytes_py2(sshserver)) for lp, rp in zip(lports, rports): tunnel.ssh_tunnel(lp, rp, sshserver, remote_ip, sshkey, password) return tuple(lports)
def tunnel_to_kernel(connection_info, sshserver, sshkey=None): """tunnel connections to a kernel via ssh This will open four SSH tunnels from localhost on this machine to the ports associated with the kernel. They can be either direct localhost-localhost tunnels, or if an intermediate server is necessary, the kernel must be listening on a public IP. Parameters ---------- connection_info : dict or str (path) Either a connection dict, or the path to a JSON connection file sshserver : str The ssh sever to use to tunnel to the kernel. Can be a full `user@server:port` string. ssh config aliases are respected. sshkey : str [optional] Path to file containing ssh key to use for authentication. Only necessary if your ssh config does not already associate a keyfile with the host. Returns ------- (shell, iopub, stdin, hb) : ints The four ports on localhost that have been forwarded to the kernel. """ from zmq.ssh import tunnel if isinstance(connection_info, string_types): # it's a path, unpack it with open(connection_info) as f: connection_info = json.loads(f.read()) cf = connection_info lports = tunnel.select_random_ports(4) rports = cf['shell_port'], cf['iopub_port'], cf[ 'stdin_port'], cf['hb_port'] remote_ip = cf['ip'] if tunnel.try_passwordless_ssh(sshserver, sshkey): password = False else: password = getpass("SSH Password for %s: " % cast_bytes_py2(sshserver)) for lp, rp in zip(lports, rports): tunnel.ssh_tunnel(lp, rp, sshserver, remote_ip, sshkey, password) return tuple(lports)
def test_random_ports(): for i in range(4096): ports = select_random_ports(10) assert len(ports) == 10 for p in ports: assert ports.count(p) == 1
def open_ssh_tunnel(log, config, server, ssh_port=622, timeout=5, ipc_wait_file=5): """Try to create ssh tunnels from localhost to server Try to create a a) passwordless ssh tunnel from localhost to server or b) munge rsh to server and create a passwordless reverse ssh tunnel from server to localhost. The transport protocol on localhost and server may differ if needed. """ user = config["user"] # server must be visable for now try: server_info = socket.gethostbyaddr(server) except socket.herror: raise TunnelError("host %s is inaccessible" % server) except socket.gaierror as e: raise TunnelError(str(e)) # make sure the kernel isn't on localhost if server_info[0] == "localhost": log("kernel on localhost - nothing to do") return # no gui password prompt env = os.environ.copy() env.pop("SSH_ASKPASS", None) if try_ssh(log, server, ssh_port, env): mode = "ssh" elif try_mrsh(log, server, ssh_port, env): mode = "mrsh" else: raise TunnelError("Unable to connect, tried ssh and mrsh") protocol = config["protocol"] # remote (r) ports are the ports for the machine hosting the kernel if protocol == "ipc": rport = config["uds"] lport = "%s-%s" % (rport, localhost) config["uds"] = lport elif protocol == "tcp": rport = config["port"] lport = select_random_ports(1)[0] config["port"] = lport else: raise TunnelError("Unsupported protocol %s" % protocol) log("attempting to create tunnels from %s@%s to %s@%s" % (protocol, localhost, protocol, server)) ssh_tunnel(log, mode, ltransport=protocol, lport=lport, rtransport=protocol, rport=rport, server=server, user=user, ssh_port=ssh_port) if protocol == "ipc": while not os.path.exists(lport) and ipc_wait_file > 0: log("waiting for local ipc socket - %d" % ipc_wait_file) time.sleep(1) ipc_wait_file -= 1 if not os.path.exists(lport): raise TunnelError("local ipc socket doesn't exist: %s" % lport) elif protocol == "tcp": time.sleep(2)