I'm trying to automate launches of VNC-clients for multiple remote systems. Currently I achieve that with a LocalForward 15900 127.0.0.1:5900. VNC uses port 5900 by default, which is fine -- there should only be one VNC-server at a time on any machine. But I may some times have multiple VNC-viewers running, so the local port must be dynamic -- and cannot be hardcoded (such as to 15900). To make it nicer, I'd like to implement a script, which will: Find an unused local port (freePort). SSH into the specified remote computer (as the specified user). Create a tunnel from the remote 5900 to the local freePort. Invoke the x11vnc -xkb -display :0 -localhost remotely. Invoke the vncviewer localhost:freePort locally. The first item I do using this method. I then use SSHTunnelForwarder: import os import paramiko import socket import sys import sshtunnel import logging from paramiko import SSHClient def freePort(): s = socket.socket() s.bind(('localhost', 0)) port = s.getsockname()[1] s.close() return port logging.basicConfig(level = logging.DEBUG, format='%(asctime)s %(message)s') try: user, host = sys.argv[1].split('@') except ValueError: host = sys.argv[1] user = os.getlogin() tunnel = sshtunnel.SSHTunnelForwarder(host, ssh_username = user, local_bind_address = ('127.0.0.1', freePort()), remote_bind_address = ('127.0.0.1', 5900)) print(tunnel) The above works nicely and prints the following at the end: <class 'sshtunnel.SSHTunnelForwarder'> object ssh gateway: foo.example.com:23 proxy: no username: meow authentication: {'pkeys': [('ssh-rsa', b'081c323ca3b5bb6f157f91984b2cb7b2')]} hostkey: not checked status: not started keepalive messages: disabled tunnel connection check: disabled concurrent connections: allowed compression: not requested logging level: ERROR local binds: [('127.0.0.1', 21242)] remote binds: [('127.0.0.1', 5900)] But now I need to launch the remote command (step 4.)... Presumably, I need to use Paramiko's SSHClient() for that, but I don't see, how to do that without starting a whole new ssh-connection. There's got to be a way to issue a command over the already-created tunnel. How would I do that? Also: how would I insist on the remote hostkey being verified -- against the known_hosts-database? Continue reading...