Paramiko SSH Tunnel Shutdown Issue

前端 未结 4 879
萌比男神i
萌比男神i 2021-02-10 23:36

I\'m working on a python script to query a few remote databases over an established ssh tunnel every so often. I\'m fairly familiar with the paramiko library, so that was my cho

相关标签:
4条回答
  • 2021-02-11 00:02

    You may want to add some synchronization between the spawned thread and the caller so that you don't try to use the tunnel before it is ready. Something like:

        from threading import Event   
        def startTunnel(self):
            class SubHandler(Handler):
                chain_host = '127.0.0.1'
                chain_port = 5432
                ssh_transport = self.c.get_transport()
            mysignal = Event()
            mysignal.clear()
            def ThreadTunnel():
                global t
                t = ForwardServer(('', 3333), SubHandler)
                mysignal.set() 
                t.serve_forever()
            Thread(target=ThreadTunnel).start()
            mysignal.wait()
    
    0 讨论(0)
  • 2021-02-11 00:05

    You can also try sshtunnel it has two cases to close tunnel .stop() if you want to wait until the end of all active connections or .stop(force=True) to close all active connections.

    If you don't want to use it you can check the source code for this logic here: https://github.com/pahaz/sshtunnel/blob/090a1c1/sshtunnel.py#L1423-L1456

    0 讨论(0)
  • 2021-02-11 00:09

    It appears the SocketServer's shutdown method isn't properly shutting down/closing the socket. With the below changes in my code, I retain access to the SocketServer object and access the socket directly to close it. Note that socket.close() works in my case, but others might be interested in socket.shutdown() followed by a socket.close() if other resources are accessing that socket.

    [Ref: socket.shutdown vs socket.close

    def ThreadTunnel():
        self.t = ForwardServer(('127.0.0.1', 3333), SubHandler)
        self.t.serve_forever()
    Thread(target=ThreadTunnel).start()
    
    def stopTunnel(self):
        self.t.shutdown()
        self.trans.close()
        self.c.close()
        self.t.socket.close()
    
    0 讨论(0)
  • 2021-02-11 00:26

    Note that you don't have do the Subhandler hack as shown in the demo code. The comment is wrong. Handlers do have access to their Server's data. Inside a handler you can use self.server.instance_data.

    If you use the following code, in your Handler, you would use

    • self.server.chain_host
    • self.server.chain_port
    • self.server.ssh_transport

    class ForwardServer(SocketServer.ThreadingTCPServer):
        daemon_threads = True
        allow_reuse_address = True
    
        def __init__(
              self, connection, handler, chain_host, chain_port, ssh_transport):
            SocketServer.ThreadingTCPServer.__init__(self, connection, handler)
            self.chain_host = chain_host
            self.chain_port = chain_port
            self.ssh_transport = ssh_transport
    ...
    
    server = ForwardServer(('', local_port), Handler, 
                           remote_host, remote_port, transport)
    server.serve_forever()
    
    0 讨论(0)
提交回复
热议问题