How to create a ssh tunnel using python and paramiko?

后端 未结 5 726
攒了一身酷
攒了一身酷 2020-12-02 13:13

I\'m learning python. I need to tunnel creators to read information from a database and close the tunnel. I use paramiko but I have not worked with tonelem example. please g

5条回答
  •  我在风中等你
    2020-12-02 14:04

    Even though this does not use paramiko, I believe it's a very clean solution to implement (similar to @dario's answer but without managing the thread in python).

    There's this little-mentioned feature in openssh client that allows us to control a ssh process through a unix socket, quoting man ssh:

    -M      Places the ssh client into “master” mode for connection sharing.  Multiple -M options places ssh
             into “master” mode with confirmation required before slave connections are accepted.  Refer to the
             description of ControlMaster in ssh_config(5) for details.
    -S ctl_path
             Specifies the location of a control socket for connection sharing, or the string “none” to disable
             connection sharing.  Refer to the description of ControlPath and ControlMaster in ssh_config(5)
             for details.
    

    So you can start background process of ssh (with -Nf) and then check (or terminate) it with a another ssh call.

    I use this in a project that requires a reverse tunnel to be established

    from subprocess import call, STDOUT
    import os
    DEVNULL = open(os.devnull, 'wb')
    
    
    CONFIG = dict(
        SSH_SERVER='ssh.server.com',
        SSH_PORT=2222,
        SSH_USER='myuser',
        SSH_KEY='/path/to/user.key',
        REMOTE_PORT=62222,
        UNIX_SOCKET='/tmp/ssh_tunnel.sock',
        KNOWN_HOSTS='/path/to/specific_known_host_to_conflicts',
    )
    
    
    def start():
        return call(
            [
                'ssh', CONFIG['SSH_SERVER'],
                '-Nfi', CONFIG['SSH_KEY'],
                '-MS', CONFIG['UNIX_SOCKET'],
                '-o', 'UserKnownHostsFile=%s' % CONFIG['KNOWN_HOSTS'],
                '-o', 'ExitOnForwardFailure=yes',
                '-p', str(CONFIG['SSH_PORT']),
                '-l', CONFIG['SSH_USER'],
                '-R', '%d:localhost:22' % CONFIG['REMOTE_PORT']
            ],
            stdout=DEVNULL,
            stderr=STDOUT
        ) == 0
    
    
    def stop():
        return __control_ssh('exit') == 0
    
    
    def status():
        return __control_ssh('check') == 0
    
    
    def __control_ssh(command):
        return call(
            ['ssh', '-S', CONFIG['UNIX_SOCKET'], '-O', command, 'x'],
            stdout=DEVNULL,
            stderr=STDOUT
        )
    

    -o ExitOnForwardFailure=yes makes sure the ssh command will fail if the tunnel cannot be established, otherwise it will not exit.

提交回复
热议问题