pahaz / sshtunnel

SSH tunnels to remote server.
MIT License
1.23k stars 184 forks source link

open_tunnel is not closing sockets when it throws an exception #288

Open gabeblack opened 10 months ago

gabeblack commented 10 months ago

I think I have pretty up-to-date versions installed:

I have tried with both open_tunnel and SSHTunnelForwarder. If one opens a tunnel and the tunnel throws an exception (e.g., the remote doesn't have the ssh_key installed), it seems impossible to get the tunnel to fully clean up all its resources. Even if one allows open_tunnel to go out of scope (or by calling stop() on the SSHTunnelForwarder), the local sockets that are listening for tunnel connections are not closed. Thus a subsequent attempt to open a new tunnel fails because the port is already in use. Actually, in the case of SSHTunnelForwarder, a call to close() hangs indefinitely (even if you pass in force=True).

Here is a simple example demonstrating the problem.

def run_tunnel():
   with open_tunnel(tunnel_ip, ssh_pkey=pkey, local_bind_address=('',2345), remote_bind_address=(remote_ip,2345)):
      time.sleep(10)

try:
   run_tunnel() # don't have pkey installed at tunnel_ip, so an exception is raised
except:
   print("First attempt to establish the tunnel has failed.")

print("Sleeping to give you time to run `netstat -apn | grep 2345` in another shell...")
time.sleep(30) #  <--run the netstat program...

# If you install the `pkey` between the first and second call to `run_tunnel()` (i.e., during the sleep above), 
# then this call will create the ssh connection, but the tunnel won't be established and you'll get error logs saying 
# "Couldn't open tunnel :2345 <> <tunnel_ip>:2345 might be in use or destination not reachable 
run_tunnel()  

When running netstat -apn | grep 2345. You will get:

tcp        0      0 0.0.0.0:2345            0.0.0.0:*               LISTEN      python3

indicating that the python program is still listening on port 2345, even though at that point in the program the context manager for open_tunnel has already closed and the server and sockets should have been cleaned up.

pahaz commented 6 months ago

Do you want to fix this bug?

gabeblack commented 6 months ago

no, sorry. -- Found just invoking ssh -fN is a much better solution. I had forgotten that ssh client itself has very good tunnel 'daemon' support.

I contribute to projects on occasion and have to pick my battles.

curlicode commented 6 months ago

@gabeblack Thanks for pointing that alternative out. I packaged ssh_tunnel in the hopes of abstracting the process for others, but because my deployment environment does not need an ssh tunnel, it's probably better if I remove it altogether.