ngrok-python icon indicating copy to clipboard operation
ngrok-python copied to clipboard

TCP tunnel disconnect behaviour

Open mathsman5133 opened this issue 8 months ago • 1 comments

Hi,

I'm trying to implement a system where tunnels (specifically TCP, SSH tunnels) have a "timeout" - process goes roughly like

  • Open tunnel
  • Someone connects via SSH (in seperate process / terminal)
  • Wait 15min
  • Close tunnel
  • Upon closing tunnel my SSH session gets closed

When I close the tunnel, I would expect any connected hosts (via SSH) to be "kicked off" (connection closed). However, what I'm seeing is that any new connections are refused, but any existing connections stay open. This can be mitigated by killing the agent (exiting the script), but that is not ideal as it would close any other tunnels the process has open, and I'm working in the context of long-running processes.

What's even stranger is that the tunnel seems to almost "disappear":

  • ngrok.get_listeners() doesn't include the (disconnected) tunnel
  • The "Agent" tab in the ngrok dashboard shows "0 Tunnels" for the agent in question

But, the tunnel still appears in the "TCP Addresses" tab: image

... and in the "Endpoints" tab: image

Although this is not entirely consistent - sometimes they just don't show up.

What is also strange is that while this zombie tunnel is still alive I'd (possibly) expect an error that I can't create a new tunnel with that same URI. However, I can create (and use) a new tunnel as if nothing happened, and exit the newly created one with no problems, and have the original "zombie" tunnel still active.

Some basic code to illustrate what I'm talking about:

import time

import ngrok

listener = ngrok.forward("host:port", "tcp", authtoken="token", remote_addr="xxx.ngrok.io:port")
print(listener.url())

# now in the next 20 seconds, go to your terminal and `ssh [email protected] -p port`

time.sleep(20)
print("Disconnecting...")
ngrok.disconnect(listener.url())  # <--- at this point I would expect my SSH session to be kicked off, but it doesn't

time.sleep(10)
ngrok.kill()  # <--- perhaps if the above didn't work I'd definitely expect killing the agent to kick my SSH session off, but it doesn't
print("Killed agent connection, waiting...")
time.sleep(10)

# only now when the script exits does my SSH session get forcibly closed

Is this expected behaviour? A bug? I know what I'd expect to happen (disconnect = remove tunnel and disconnect any connected hosts).

If anyone could shed some light on this that would be much appreciated.

Cheers

mathsman5133 avatar Jun 28 '24 00:06 mathsman5133