elliotchance / sshtunnel

🚇 Ultra simple SSH tunnelling for Go programs.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tunnel closed if forwarded connection is not in use anymore

rnsc opened this issue · comments

Hello,

I was testing forwarding of ports and discovered that if you setup a tunnel and use the locally forwarded port, you can only use it once (example: one curl request), after that connection is closed by the client, the tunnel closes.

2020/01/15 10:25:44.654482 accepted connection
2020/01/15 10:25:44.654620 tunnel closed
2020/01/15 10:25:46.868374 connected to windows-host -> bastion-host:22 (1 of 2)
2020/01/15 10:25:47.816384 connected to windows-host:3389 (2 of 2)
2020/01/15 10:25:54.982384 io.Copy error: readfrom tcp 127.0.0.1:59612->127.0.0.1:59615: write tcp 127.0.0.1:59612->127.0.0.1:59615: write: broken pipe
2020/01/15 10:26:10.249962 close signal received, closing...

So basically, to reproduce the above, I create a tunnel and forward the RDP port of a windows machine that is accessible through a linux bastion host.
Then my program launches another program to open an RDP connection to that windows host.
If I close my RDP connection (the io.Copy error happens), then the tunnel closes.

Same symptom if I forward an HTTP port, I can do a cURL request just fine, but all subsequent requests will fail because the tunnel is closed.

Tunnel starting
Tunnel started
[INFO] You can access the remote port 9200 on your local port 9200
host: linux-host
proxyHost: bastion-host
Tunnel starting
Tunnel started
2020/01/15 10:37:10.310800 accepted connection
2020/01/15 10:37:10.310924 tunnel closed
2020/01/15 10:37:16.838399 connected to bastion-host:22 (1 of 2)
2020/01/15 10:37:17.353177 connected to linux-host:9200 (2 of 2)

~$ curl localhost:9200/_cat/health
1579081037 09:37:17 elasticsearch green 3 3 92 46 0 0 0 0 - 100.0%
~$
~$ curl localhost:9200/_cat/health
curl: (7) Failed to connect to localhost port 9200: Connection refused

In the above example, I'm create two tunnels, one to do SSH stuff and one to forward the 9200 port. (Thus the two "Tunnel Starting/Started" lines of log from my program)

Now I don't know if there's a logic flaw in my code or if it's an expected behaviour of the library.

Kind regards,

rnsc

I believe this has been raised before. That it would be nice to allow reusing of connections. However, I'm not sure what this actually entails. If you find a fix, throw in a PR.

Ok, I'll have a poke at it :)

I've poked around a little bit and it's not a trivial change.
I resorted to create another package for my use case to do the TCP proxying.
However, even that is not great in itself as I'm struggling with concurrent connections locking the whole thing.

I'll it sink for a bit, maybe another idea will come up. :)