Resolving SSH Connection Timeout on Port 22 with Keepalive Intervals
Experiencing SSH connection timeouts or frequent disconnections on port 22? Learn to diagnose and fix intermittent issues using client and server-side keepalive configurations, and network troubleshooting.
SSH (Secure Shell) connection timeouts can be one of the most frustrating issues for system administrators and developers alike. Whether your session freezes mid-command, or you’re unable to establish a connection to port 22 in the first place, these timeouts disrupt workflows and cause significant productivity loss. This comprehensive guide will walk you through diagnosing and resolving SSH connection timeouts, with a particular focus on network keepalive intervals.
Symptom & Error Signature
Users typically encounter one of the following symptoms or error messages when an SSH connection times out:
-
During connection establishment: The SSH client hangs for an extended period, then displays an error.
$ ssh [email protected] ssh: connect to host example.com port 22: Connection timed out -
After connection establishment (idle timeout): The SSH session freezes after a period of inactivity. Commands stop responding, and eventually, the session closes or displays an error.
# (Session freezes for a while) Read from remote host example.com: Connection reset by peer Packet write failed: Broken pipe -
After connection establishment (intermittent network issues): The session might momentarily hang, then recover, or disconnect abruptly.
# (During command execution or shortly after) Broken pipe
Root Cause Analysis
Understanding the root causes is crucial for effective troubleshooting. SSH connection timeouts on port 22, especially those related to keepalive intervals, typically stem from these underlying issues:
- Network Middleboxes (NAT/Firewalls/Load Balancers): This is by far the most common cause. Many network devices (routers, firewalls, load balancers, cloud security groups) have aggressive default idle connection timeout policies (e.g., 300 seconds or 5 minutes). If no data passes through an SSH connection for this duration, these devices assume the connection is idle or stale and drop its state from their connection tracking tables. Subsequent attempts by either the client or server to send data will fail, leading to a timeout or “connection reset by peer.”
- Client-Side Inactivity: When the client sends no data (e.g., the user is AFK, or a script is waiting for a long-running process on the server), it triggers the idle timeout policies of network middleboxes.
- Server-Side Inactivity: While less common for default SSH server configurations, a misconfigured
sshddaemon might drop connections that appear idle from its perspective. - Network Congestion and Instability: High packet loss, excessive latency, or general network instability between the client and the server can cause packets to be dropped or delayed beyond acceptable thresholds, leading to timeouts. While not an “idle timeout,” it manifests similarly.
- Incorrect Firewall Rules: Though typically preventing initial connection, a firewall (either on the client, server, or in between) might drop established connections if its state tracking is misconfigured or overloaded.
- Server Resource Exhaustion: If the server is severely overloaded (CPU, RAM, disk I/O), the
sshddaemon might not be able to respond to client requests promptly, leading to client-side timeouts.
Step-by-Step Resolution
Follow these steps to diagnose and resolve SSH connection timeouts effectively.
1. Initial Network Connectivity & Port Check
Before diving into SSH configurations, ensure basic network connectivity and port accessibility.
# Test basic reachability
ping example.com
# Test if port 22 is open and listening on the remote host
# Using netcat (nc)
nc -vz example.com 22
# Output for success: Connection to example.com 22 port [tcp/ssh] succeeded!
# Using telnet (if nc is not available)
telnet example.com 22
# If successful, you'll see something like: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.7
# Then Ctrl+] to exit, then 'quit'
If ping fails, your server might be down, or there’s a routing issue. If nc or telnet fails, port 22 might be blocked by a firewall, sshd might not be running, or it’s listening on a different port.
2. Configure Client-Side SSH Keepalives (Recommended First Step)
This is the most common and often effective solution for idle timeouts. SSH client keepalives (controlled by ServerAliveInterval) instruct your client to send a small, encrypted packet to the server if no other data has been sent for a specified duration. This keeps the connection “alive” in the eyes of any intermediate network devices.
You can configure this globally, per-user, or on a per-host basis.
A. Per-User Configuration (~/.ssh/config)
Edit or create the ~/.ssh/config file on your local machine.
# Open the file with your preferred editor
nano ~/.ssh/config
Add or modify the following lines for all hosts or a specific host:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
# Or for a specific host:
# Host my-web-server
# Hostname 192.168.1.100
# User webadmin
# ServerAliveInterval 45
# ServerAliveCountMax 2
ServerAliveInterval: Specifies the time in seconds after which the client will send a null packet to the server if no data has been received from the server.ServerAliveCountMax: Sets the number of server alive messages (see above) which may be sent withoutsshreceiving any messages back from the server. If this threshold is reached,sshwill disconnect.
[!IMPORTANT] A
ServerAliveIntervalof30to60seconds is generally a good starting point.ServerAliveCountMaxof2or3means the connection will be dropped after 2-3 intervals without a response. ForServerAliveInterval 60andServerAliveCountMax 3, the connection will effectively be dropped after3 * 60 = 180seconds (3 minutes) of unresponsiveness. Adjust these values based on your network’s typical idle timeout.
B. Global Client Configuration (/etc/ssh/ssh_config.d/)
For systems where you want to apply this globally for all users, you can create a new configuration file under /etc/ssh/ssh_config.d/.
sudo nano /etc/ssh/ssh_config.d/90-keepalive.conf
Add the same Host * configuration:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
This ensures that the settings apply to all SSH connections made from this client machine.
C. Command-Line Option (Temporary)
For a one-off connection or testing, you can specify these options directly when invoking ssh:
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 [email protected]
3. Configure Server-Side SSH Keepalives
While client-side keepalives are usually sufficient, configuring server-side keepalives can be beneficial in some specific scenarios, such as when the server needs to ensure client presence and drop dead connections faster. This setting instructs the sshd daemon to send null packets to the client.
[!WARNING] Modifying
sshd_configaffects all users connecting to the server. Be cautious and ensure you understand the implications. An incorrect configuration could lock you out of your server. Always test changes carefully.
A. Edit sshd_config
Log in to your server and open the sshd_config file:
sudo nano /etc/ssh/sshd_config
Add or modify the following lines. Uncomment them if they exist and adjust the values.
ClientAliveInterval 30
ClientAliveCountMax 5
ClientAliveInterval: Specifies the time in seconds that thesshddaemon will wait before sending a null packet to the client if no data has been received from the client.ClientAliveCountMax: Sets the number of client alive messages (see above) which may be sent withoutsshdreceiving any messages back from the client. If this threshold is reached whilesshdis waiting for a client alive response,sshdwill disconnect the client.
[!IMPORTANT]
ClientAliveInterval 30andClientAliveCountMax 5mean the server will disconnect the client after5 * 30 = 150seconds (2.5 minutes) of unresponsiveness from the client. Choose values appropriate for your network and security policy. These settings are less common thanServerAliveIntervalfor resolving typical idle timeouts, but can be useful for managing resources on busy servers by proactively dropping truly dead connections.
B. Restart SSH Service
After modifying sshd_config, you must restart the SSH service for changes to take effect.
# For Systemd-based systems (Ubuntu, Debian, CentOS 7+, RHEL 7+)
sudo systemctl restart sshd
# To check the service status after restart
sudo systemctl status sshd
4. Check Server-Side Firewall Configuration
Ensure that your server’s firewall (e.g., UFW on Ubuntu) is correctly configured to allow SSH traffic on port 22.
# Check UFW status
sudo ufw status verbose
# If port 22 is not allowed, enable it (default SSH port)
sudo ufw allow OpenSSH
sudo ufw enable # if not already enabled
If you are using a cloud provider, check their security group or network ACL settings to ensure port 22 is open from your IP address or appropriate ranges.
5. Review Server Logs for Clues
Server logs can provide valuable insights into why connections are being dropped or failing.
# For Systemd-based systems (Ubuntu, Debian, CentOS 7+, RHEL 7+)
journalctl -u sshd -f # Follow sshd logs in real-time
# Alternatively, check auth.log (Ubuntu/Debian)
tail -f /var/log/auth.log | grep sshd
# For CentOS/RHEL
tail -f /var/log/secure | grep sshd
Look for messages related to connection attempts, disconnections, authentication failures, or error conditions. If you’ve enabled LogLevel DEBUG in sshd_config (temporarily), you’ll get much more verbose output.
6. System Resource Checks (Secondary Cause)
While less direct for “keepalive” issues, server resource exhaustion can cause the sshd daemon to become unresponsive, leading to client-side timeouts.
# Check CPU and memory usage
top
# Or a more user-friendly alternative
htop
# Check disk space
df -h
# Check load average
uptime
If the server is constantly under high load, consider upgrading resources, optimizing applications, or load balancing.
7. Diagnose Network Path with mtr or traceroute
If issues persist, especially with initial connection timeouts, there might be a problem with a router or firewall along the network path.
# Install mtr if not already present
sudo apt update && sudo apt install mtr -y # Ubuntu/Debian
sudo yum install mtr -y # CentOS/RHEL
# Run mtr (more informative than traceroute)
mtr -rw example.com
# Or use traceroute
traceroute example.com
mtr continuously sends packets and displays latency and packet loss for each hop, helping you pinpoint where the network connection might be failing or experiencing high latency.
By systematically applying these steps, you should be able to diagnose and resolve most SSH connection timeout issues related to port 22 and keepalive intervals, ensuring stable and reliable access to your servers.
