How to reliably keep an SSH tunnel open?
Sounds like you need autossh. This will monitor an ssh tunnel and restart it as needed. We've used it for a couple of years and it seems to work well.
autossh -M 20000 -f -N your_public_server -R 1234:localhost:22 -C
More details on the -M parameter here
All stateful firewalls forget about a connection after not seeing a packet for that connection for some time (to prevent the state tables from becoming full of connections where both ends died without closing the connection). Most TCP implementations will send a keepalive packet after a long time without hearing from the other side (2 hours is a common value). If, however, there is a stateful firewall which forgets about the connection before the keepalive packets can be sent, a long-lived but idle connection will die.
If that is the case, the solution is to prevent the connection from becoming idle. OpenSSH has an option called ServerAliveInterval which can be used to prevent the connection from being idle for too long (as a bonus, it will detect when the peer died sooner even if the connection is idle).
I've used the following Bash script to keep spawning new ssh tunnels when the previous one dies. Using a script is handy when you don't want or can't install additional packages or use compiler.
while true
do
ssh <ssh_options> [user@]hostname
sleep 15
done
Note that this requires a keyfile to establish the connection automatically but that is the case with autossh, too.