Troubleshooting SSH Session Freezes: Network Keepalive Configuration and Timeout Solutions


2 views

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:

  1. Network middleboxes (NAT/firewalls) aggressively dropping idle connections
  2. TCP keepalive packets not being properly transmitted
  3. 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:

  1. Test with VPN to bypass ISP-level issues
  2. Use mosh (mobile shell) as alternative
  3. 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