Every sysadmin and developer has faced this at some point: you're working remotely via SSH when suddenly the connection drops (network issues, VPN disconnects, or simply closing your laptop lid). Sometimes the session terminates cleanly, but other times your terminal just hangs indefinitely, becoming completely unresponsive to any keyboard input - even Ctrl+C/Ctrl+D won't bail you out.
The root cause lies in how SSH handles TCP connections at the transport layer. When a network connection breaks abruptly:
1. The SSH client enters a "hung" state waiting for TCP acknowledgments 2. The TCP stack keeps retransmitting packets (default 15+ times on Linux) 3. No proper session teardown occurs because FIN/RST packets never complete
When stuck in a frozen SSH session, try these key combinations in sequence:
1. Enter key (sometimes wakes up stalled terminal) 2. ~. (tilde followed by period - SSH escape sequence) 3. Ctrl+\ (SIGQUIT signal) 4. Ctrl+] (telnet-style escape to ssh client)
The most reliable is ~.
(must be first character on new line), which tells the SSH client to immediately terminate.
Add these to your ~/.ssh/config
to make sessions more resilient:
Host * ServerAliveInterval 60 ServerAliveCountMax 3 TCPKeepAlive yes EscapeChar ~ # For modern OpenSSH (7.3+) IPQoS throughput
On the SSH server, adjust these kernel parameters (/etc/sysctl.conf
):
# Reduce TCP retransmission attempts net.ipv4.tcp_retries2 = 5 # Faster connection timeouts net.ipv4.tcp_keepalive_time = 60 net.ipv4.tcp_keepalive_probes = 3
For critical connections, use this wrapper script that automatically reconnects:
#!/bin/bash while true; do ssh -o ConnectTimeout=10 -o ServerAliveInterval=30 user@host sleep 2 echo "Reconnecting..." done
Consider these more resilient alternatives for important remote work:
1. mosh (mobile shell) - UDP-based with roaming support 2. tmux/screen on server - Detach/re-attach sessions 3. webshell alternatives (ShellHub, Wetty)
Every Linux/Mac sysadmin has experienced this: you're working remotely via SSH when suddenly your connection drops (maybe due to network issues or VPN disconnection). Sometimes the session terminates cleanly, but other times your terminal just hangs indefinitely, leaving you unable to:
- Recover command history
- Regain terminal control
- Gracefully exit the session
This behavior stems from how SSH handles TCP connections and terminal sessions:
# TCP connection states involved
$ netstat -tn | grep ssh
ESTABLISHED # Normal state
FIN_WAIT # Connection closing
CLOSE_WAIT # Remote end closed connection
When the network drops abruptly, the SSH client may not receive proper TCP termination packets, leaving the session in a zombie state. The client waits indefinitely for server responses that will never arrive.
1. The Escape Sequence
SSH has a built-in escape character (default: ~) that can help terminate frozen sessions:
# Press in order (with Enter if needed):
1. Enter
2. ~
3. .
This sends the "terminate session" command directly to the SSH client.
2. Client-Side Timeout Configuration
Add these settings to your ~/.ssh/config
:
Host *
ServerAliveInterval 15
ServerAliveCountMax 3
TCPKeepAlive yes
This makes SSH detect dead connections within 45 seconds (15×3) instead of hanging forever.
3. Terminal Multiplexer Protection
Using tmux or screen prevents session loss:
# Start a persistent session
$ tmux new -s work_session
# Reattach after disconnect
$ tmux attach -t work_session
When troubleshooting, check these system-level details:
# Check SSH process states
$ ps aux | grep ssh
# Inspect TCP connections
$ ss -tnp | grep ssh
# Check for hung processes
$ lsof -n -P -iTCP -sTCP:CLOSE_WAIT
- Always use
tmux
orscreen
for critical work - Configure client-side timeouts as shown above
- Consider using Mosh (mobile shell) for unstable connections
- For automation scripts, implement connection checks:
#!/bin/bash
# Sample connection check wrapper
max_attempts=3
timeout=10
ssh_with_retry() {
for i in $(seq 1 $max_attempts); do
ssh -o ConnectTimeout=$timeout "$@"
[ $? -eq 0 ] && break
sleep 5
done
}