When working with SSH connections across different network environments, you may encounter inconsistent timeout behaviors. Here's a deep dive into why this happens and how to fix it.
The fundamental issue stems from how TCP connections are maintained across network boundaries:
# Server-side TCP keepalive settings (in /etc/ssh/sshd_config)
TCPKeepAlive yes
ClientAliveInterval 60
ClientAliveCountMax 3
Corporate networks typically have different firewall/NAT configurations than residential networks:
- Office LAN: Direct connections with no intermediate NAT timeouts
- Home networks: Multiple NAT layers with aggressive connection timeouts (typically 5-15 minutes)
For Mac OSX Terminal users, these client-side configurations work best:
# ~/.ssh/config
Host *
ServerAliveInterval 30
ServerAliveCountMax 3
TCPKeepAlive no
If the above doesn't resolve your issue, consider these additional measures:
# For persistent connections
ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=3 user@host
# For tunneling scenarios
autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -N -L ...
Use these commands to troubleshoot timeouts:
# Check TCP connection states
netstat -tn | grep ssh
# Monitor packets
tcpdump -i any port 22 -n
# Test keepalive packets
sudo tcpdump -i en0 'tcp port 22 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
Network middleboxes (NATs, firewalls, stateful packet inspectors) behave differently based on connection origin. When you SSH from within the LAN, your traffic bypasses most network security appliances. Remote connections traverse multiple state-tracking systems that aggressively prune idle TCP connections.
The timeout discrepancy stems from three layers:
- Transport Layer: Home routers/NATs typically enforce 300-600 second TCP state timeouts
- SSH Protocol: Default ClientAliveInterval (0) and ServerAliveInterval (0) settings
- System Level: Different TCP keepalive configurations between macOS and Linux
Create or modify ~/.ssh/config
with these parameters:
Host * ServerAliveInterval 60 ServerAliveCountMax 3 TCPKeepAlive no
For Fedora servers, edit /etc/ssh/sshd_config
:
ClientAliveInterval 30 ClientAliveCountMax 5 UseDNS no
After changes, restart sshd: sudo systemctl restart sshd
For environments where you can't modify configurations:
- Use
tmux
orscreen
to maintain session state - Implement SSH connection hopping through a bastion host
- Consider Mosh (Mobile Shell) for unstable connections
To diagnose exactly where connections drop:
# On macOS: sudo tcpdump -i en0 -vvv 'port 22' # On Linux server: journalctl -u sshd --follow sudo ss -t -a | grep ssh
For corporate environments, these additional measures help:
- Implement SSH certificates instead of key pairs
- Configure global keepalive settings in
/etc/ssh/ssh_config.d/
- Use VPN tunneling for all remote access