I have an unreliable network connection between two machines: sometimes active TCP connections get dropped for reasons beyond my control. I want to establish a reliable TCP connection between the two machines.
If the network was reliable, I'd just run ssh -L 1234:localhost:1234 remotehost
, with the server listening on port 1234 on remotehost
, and point the client at localhost:1234
. But if the ssh connection dies, so will the forwarded connection. How can I arrange to automatically restore the connection between the client and the server?
Non-solutions:
- This isn't for interactive applications, so screen does not apply.
- This isn't just about reconnecting an SSH tunnel automatically, � la autossh. I want to continue using the same tunneled TCP connection, not start a new one.
- In principle, a VPN would do the trick. But it seems overkill when I just want one TCP connection, and I'd like a solution that works even if I don't have root permissions on either side.
I have a dim memory of a program called rocks
that did just that, but it seems to have fallen off the face of the web. I'm mostly interested in Linux on both sides (though I'd expect a program at this level to be portable to other unices), but if you know of a program that works between QNX and VMS, all the better.
Is the old an unmaintained Reliable Sockets (Rocks) what you're looking for ?
The only standard protocol I know of with this capability is MPTCP. It is transparent to the application layer, so SSH on top of MPTCP should just work. It can run the underlying TCP connections over different paths with different IPs, so in principle it could be used to migrate your SSH connection in and out of the VPN connection depending on whether the VPN connection is up.
I don't know much about the maturity of MPTCP implementations, but the design of the protocol looks quite robust.
It should protect your SSH connections from getting lost due to flaky network connectivity. It won't protect you against a mitm who wants to break your SSH connection. A mitm can still inject corrupted data, which SSH will detect and break the connection.
An MPTCP like reconnect method build into the SSH protocol would be the method I could imagine keeping a connection alive for the longest possible time. But I don't think such a feature has been designed for the SSH protocol.
You could use
daemontools
to keep the ssh port forward up; it won't necessarily keep programs depending on the connection alive while it's down (as presumably when ssh disconnects the local port will start refusing their connections), but it's a start.I suspect there are some
iptables
tricks, like causing that port to DROP packets as soon as the ssh forward goes away, so the connecting programs just know that packets are disappearing, not being refused. I'm just learningdaemontools
myself (again) so I'm not sure if you can run a custom script when a service dies, but I suspect you can.TCP does this automatically. You need only disable or weaken the typical practical cleanup hacks used to kill moribund TCP connections. Disable TCP keepalive for your connection, and greatly increase the limit for excessive retransmissions. On Linux, for example, write a large number into
/proc/sys/net/ipv4/tcp_retries2
.However, in a modern network a stateful packet inspection firewall is likely to forget about a TCP connection which fails to exchange packets regularly, so it may rain on your parade.