SSH session freezes typically occur due to network interruptions or timeout configurations. When your connection remains idle beyond certain thresholds, intermediate network devices (like routers or firewalls) may drop the TCP connection, while the SSH client and server remain unaware of the disconnection.
These SSH settings control connection persistence:
# Server-side configuration (/etc/ssh/sshd_config)
ClientAliveInterval 300
ClientAliveCountMax 3
TCPKeepAlive yes
# Client-side configuration (~/.ssh/config)
Host *
ServerAliveInterval 60
ServerAliveCountMax 5
TCPKeepAlive yes
To diagnose network issues:
# Check for packet loss
ping your.server.com
mtr your.server.com
# Test connection stability
while true; do date; nc -zv your.server.com 22; sleep 10; done
# Check firewall/NAT timeouts
sudo iptables -L -n -v | grep ESTABLISHED
For unstable connections, consider these approaches:
# Auto-reconnect with tmux
ssh user@host -t 'tmux attach || tmux new'
# Persistent connection with ControlMaster
Host *
ControlMaster auto
ControlPath ~/.ssh/control:%h:%p:%r
ControlPersist 4h
Home ISP issues often involve:
- Dynamic IP changes
- Aggressive NAT timeouts (typically 30-60 minutes)
- Transparent proxy interference
Test with different ports or VPN:
ssh -p 443 user@host # Try alternative port
ssh -o ProxyCommand="nc -X 5 -x proxy:port %h %p" user@host
When configuration changes aren't possible:
# Keepalive using cron (client-side)
*/5 * * * * ssh -O check user@host || ssh -fN user@host
# Terminal multiplexer persistence
ssh user@host -t 'screen -d -RR'
SSH session freezes typically occur due to network-level interruptions or misconfigured timeout settings. When your connection hangs indefinitely without proper termination, it suggests either:
- Network middleboxes (NAT/firewalls) aggressively dropping idle connections
- TCP keepalive packets not being properly transmitted
- Server/client SSH configurations mismatching timeout thresholds
First, verify if this is a network-level issue:
# Check for packet drops on your route
mtr --report --report-cycles 10 your.server.com
# Test connection stability
ping -i 60 your.server.com # Send packets every minute
For SSH-specific debugging, enable verbose mode:
ssh -vvv user@your.server.com
Add these settings to ~/.ssh/config:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
TCPKeepAlive yes
EscapeChar ~
Alternatively, set these parameters at connection time:
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 user@host
On the SSH server (typically in /etc/ssh/sshd_config):
ClientAliveInterval 120
ClientAliveCountMax 3
TCPKeepAlive yes
After modifying, reload the SSH daemon:
sudo systemctl reload sshd
For home routers/ISP-level NAT timeouts, consider these advanced solutions:
# Configure lower-layer keepalives (requires root)
sudo sysctl -w net.ipv4.tcp_keepalive_time=60
sudo sysctl -w net.ipv4.tcp_keepalive_intvl=30
sudo sysctl -w net.ipv4.tcp_keepalive_probes=3
When standard fixes don't work:
- Test with VPN to bypass ISP-level issues
- Use mosh (mobile shell) as alternative
- Check for MTU mismatches with:
ping -s 1472 -M do your.server.com
For Mosh installation:
# On client
sudo apt install mosh
# On server
sudo apt install mosh
mosh user@your.server.com
For mission-critical sessions, use tmux/screen on the server:
tmux new -s mysession
# Later, after disconnect:
tmux attach -t mysession
Or configure automatic reconnection with:
#!/bin/bash
while true; do
ssh -o ExitOnForwardFailure=yes user@host
sleep 2
done