Timo Kilpilehto
2018-Mar-02 08:40 UTC
Reverse ssh tunnel bound to remote socket reserves the socket address after disconnect preventing reconnecting
Hi all, I recently posted this question in unix stackexchange, but now figured it might be better suited here. https://unix.stackexchange.com/questions/427189/how-to-cleanup-ssh-reverse-tunnel-socket-after-connection-closed The culprit of the problem is that I have clients trying to publish certain services as unix sockets on a server through a reverse ssh tunnel and should the connection break for any reason, say the client reboots or crashes the tunnel will obviously break. I've set up the server to ping on the client and the client to ping on the server and according to logs the server does see that the client gets disconnected and does some cleanup. However, for some reason the now broken and unrecoverable socket is left around and when the client tries to reconnect it can't because "Address already in use". Why doesn't it clean up the sockets? Is this a bug? Feature? Could this be fixed somehow? How to best overcome this? Here's a mini sample demonstrating the basic problem in a local environment: #!/usr/bin/env sh if [ -e lol.socket ]; then rm lol.socket; fi ssh -N -T -R $(pwd)/lol.socket:127.0.0.1:4444 127.0.0.1 & pid="$!"; sleep 1; kill $pid #tunnel dies [ -e $(pwd)/lol.socket ] && echo 'Socket still exists!' ssh -v -N -T -R $(pwd)/lol.socket:127.0.0.1:4444 127.0.0.1 -o "ExitOnForwardFailure yes" 2>&1 | tail -5 I've been using OpenSSH 7.4 client/server when testing this.
David Newall
2018-Mar-02 09:30 UTC
Reverse ssh tunnel bound to remote socket reserves the socket address after disconnect preventing reconnecting
Hi Timo, I suspect that the reason the socket is not removed from the UNIX filesystem is because Linux (I assume) doesn't remove it when the socket is closed.? SSH probably does the same thing to create and to destroy UNIX-domain sockets as it does for IP sockets, namely, create using socket()+bind(), destroy using close().? Personally, I think it's wrong that the close() call doesn't remove the name, but that's something which is unlikely to change. You are right, SSH could remove the name, however, as it doesn't (although perhaps that might change), you could work around the problem by removing it yourself, e.g. sh -c 'ssh -N -T -R $(pwd)/lol.socket:127.0.0.1:4444 127.0.0.1; rm lol.socket' & Regards. David