SSH troubleshooting is a critical, unavoidable skill for developers, sysadmins, and DevOps engineers. Secure Shell (SSH) is the backbone of modern infrastructure management, but when it fails, it can completely halt your productivity. Whether you are dealing with a cryptic Permission denied (publickey) error, staring at a sudden Connection refused SSH message, or dealing with an alarming Host key verification failed warning, debugging the SSH protocol requires a structured, logical approach.
In this comprehensive guide, we will break down the top 10 most common SSH errors, diagnose exactly why they happen, and provide the precise commands to fix them. If you need to generate proper commands instantly, use our SSH command builder. If you suspect your cryptographic keys are outdated or corrupted, generate a fresh, secure pair using our privacy-first SSH key generator. At ZeroData Tools, we believe in local-only processing—your private keys and server IPs never leave your browser.
Whenever an SSH connection fails, do not guess the problem. Append -vvv to your command. This enables maximum verbosity and shows you exactly where the handshake or authentication breaks down.
ssh -vvv user@hostname 1. Permission Denied (publickey)
The Permission denied (publickey) error is arguably the most frequent roadblock you will encounter. It explicitly means the server has rejected your connection because it could not authenticate your identity using the public keys it has on file. This usually happens when password authentication is disabled, and the server does not recognize the private key your client is offering.
Why it matters: Security best practices dictate disabling password authentication in favor of key-based auth. When it fails, you are locked out of your own infrastructure.
Client-Side Fixes:
- Specify the correct key: Your client might be offering the wrong default key. Force it to use a specific key using the identity flag.
ssh -i ~/.ssh/id_ed25519 user@hostname Server-Side Fixes:
- Check authorized_keys: Ensure your public key (the
.pubfile) is correctly pasted into the server's~/.ssh/authorized_keysfile without any line breaks or missing characters. - Fix file permissions: SSH is notoriously strict about file permissions. If your server's permissions are too open, SSH will silently ignore the key files for safety. Run these commands on the server (via console or another active session):
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys 2. Connection Refused SSH
Encountering a Connection refused SSH error indicates a network-level rejection. Your client successfully reached the target IP address, but the server actively refused the connection by sending a TCP RST (reset) packet.
Why it matters: This is rarely an authentication issue. It means the SSH service is either down, listening on a different port, or blocked by a strict local firewall that explicitly rejects packets rather than dropping them.
Diagnostic Steps:
First, verify that the SSH daemon is actually running on the server. If you have console access, check the service status:
sudo systemctl status sshd If it is inactive, restart it:
sudo systemctl restart sshd Check the Port:
Many sysadmins change the default SSH port from 22 to something else (e.g., 2222) to avoid automated bot scanners. If the server is listening on port 2222, connecting to port 22 will result in a connection refused. Specify the custom port in your command:
ssh -p 2222 user@hostname To avoid typing this every time, you can configure your local setup. Check out our SSH config generator to automate port handling.
3. Host Key Verification Failed
The terrifying Host key verification failed message is actually SSH doing its job perfectly. The first time you connect to a server, SSH saves its cryptographic footprint (host key) in your local ~/.ssh/known_hosts file. If you connect again and the server's footprint has changed, SSH panics.
Why it matters: This protects you against Man-In-The-Middle (MITM) attacks. However, it also triggers legitimately when a server is rebuilt, an IP address is reassigned, or an EC2 instance is recreated.
The Fix:
If you are absolutely certain the server was legitimately rebuilt and this is not an attack, you must remove the old, offending key from your local known_hosts file. Use the ssh-keygen utility to remove the specific IP or hostname:
ssh-keygen -R hostname_or_ip_address After running this, attempt the connection again. SSH will prompt you to accept the new fingerprint as if it were a brand new server.
4. Connection Timed Out
Unlike a refused connection, a timeout means your SSH request went into the void and no response ever came back. The client waited for the TCP handshake to complete, but the packets were dropped.
Common Causes: This is almost always a firewall issue, a routing problem, or a server that is completely offline. It could be AWS Security Groups, Google Cloud Firewall rules, or a local iptables/ufw configuration blocking port 22.
How to Troubleshoot:
- Ping the server: Check if basic ICMP traffic reaches the host.
ping target_ip - Trace the route: See where the packets are getting dropped.
traceroute target_ip(ortracerton Windows). - Test the port: Use netcat to see if the port is reachable through firewalls.
nc -vz target_ip 22 If netcat times out, you must log into your cloud provider's console and ensure inbound TCP traffic on port 22 is allowed for your current IP address.
5. WARNING: UNPROTECTED PRIVATE KEY FILE!
This error is extremely loud and for good reason. SSH clients will aggressively refuse to use a private key file that has overly permissive file rights. If other users on your local machine can read your private key, your security is compromised.
The Solution:
You must restrict the permissions of your private key file so that only your user account has read access. No one else, not even the group, should be able to read it.
chmod 600 ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_ed25519 If you are on Windows using OpenSSH, you must modify the file properties. Right-click the key file, go to Properties > Security > Advanced, disable inheritance, and ensure only your user account has "Full control".
6. Too Many Authentication Failures
SSH clients have a feature (or flaw, depending on how you look at it) where they will automatically attempt to use every single private key loaded into your SSH Agent or stored in your ~/.ssh directory before falling back to a password.
Servers typically have a MaxAuthTries limit (usually 6). If you have 7 different SSH keys on your local machine, the SSH client will try them one by one. The server will drop the connection before your client ever gets to the correct key or prompts for a password.
The Fix:
You can tell your SSH client to strictly use only the key you specify in the command line, ignoring the others. Use the IdentitiesOnly flag:
ssh -i /path/to/correct_key -o IdentitiesOnly=yes user@hostname If you want to make this permanent for a specific host, add it to your SSH config. For a deeper dive into optimal configurations, read our SSH complete guide.
7. No Matching Key Exchange Method Found
This error looks like cryptographic gibberish: Unable to negotiate with X.X.X.X port 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1.
Why it happens: Cryptography evolves. Modern SSH clients (like recent versions of OpenSSH) deprecate old, insecure encryption algorithms. If you are trying to connect to a legacy switch, an old router, or an unpatched server that only supports ancient algorithms, the handshake fails.
The Fix:
You can force your modern SSH client to temporarily re-enable the legacy algorithm required by the old server using the -o KexAlgorithms flag.
ssh -o KexAlgorithms=+diffie-hellman-group1-sha1 user@legacy_hostname Be warned: doing this means you are using weak encryption. You should strongly consider updating the firmware or SSH daemon on the target device.
8. Could Not Resolve Hostname
The ssh: Could not resolve hostname... Name or service not known error means your computer cannot convert the domain name you typed into an IP address.
Troubleshooting Steps:
- Check for typos in your command.
- Check your local
~/.ssh/configfile. You might have defined a host alias improperly. - Verify DNS resolution using
nslookupordig:
dig yourhostname.com If the DNS query fails, you need to fix your network's DNS settings or add a manual override in your local /etc/hosts file.
9. packet_write_wait: Broken Pipe
You successfully connect via SSH, run a long process, switch to another tab for five minutes, and when you return, your terminal is frozen. A minute later, you see packet_write_wait: Connection to X.X.X.X port 22: Broken pipe.
Why it happens: Stateful firewalls, NAT routers, and cloud load balancers track active TCP connections to save memory. If a connection is completely idle (no data transmitted) for a certain period, the router assumes the connection is dead and drops it from its state table.
The Fix:
You need to tell your SSH client to send a tiny "keep-alive" heartbeat packet to the server at regular intervals so the firewalls know the connection is still active.
Add this to your local ~/.ssh/config file:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3 10. Bad Owner or Permissions on ~/.ssh/config
If you try to organize your SSH connections using a config file, you might run into an error stating Bad owner or permissions on /home/user/.ssh/config. Similar to the unprotected private key error, SSH enforces strict permissions on its configuration files to prevent malicious local users from hijacking your connection aliases.
The Fix:
Ensure that the config file is owned by your user account and that no one else can read or write to it.
chown $USER:$USER ~/.ssh/config
chmod 600 ~/.ssh/config Masterclass: Advanced Sysadmin Debugging
When the standard fixes don't work, you must escalate to advanced sysadmin debugging. This involves cross-referencing verbose client output with server-side logs.
Step 1: The Verbose Client Log (-vvv)
Running ssh -vvv provides a mountain of data. Here is what you should look for:
- debug1: Reading configuration data: Shows exactly which config files are being parsed.
- debug1: Connecting to...: Shows the IP and port. If it hangs here, it's a firewall/network issue.
- debug1: Local version string / Remote protocol version: Ensures both sides are speaking the same protocol.
- debug1: Authentications that can continue: This is vital. It tells you what methods the server actually allows (e.g.,
publickey,password). - debug1: Offering public key: Shows which specific key file is being tested against the server.
Step 2: Server-Side Authentication Logs
If the client logs show that the key was offered but rejected, the absolute truth lies on the server. You need to read the authentication logs. If you have an alternate way into the server (like a cloud provider's web console), check these files.
On Debian and Ubuntu based systems:
sudo tail -f /var/log/auth.log | grep sshd On Red Hat, CentOS, Fedora, and Amazon Linux systems:
sudo tail -f /var/log/secure | grep sshd Common server-side log messages include:
- Authentication refused: bad ownership or modes for directory: The server's
~/.sshdirectory has the wrong permissions. - User not allowed because not listed in AllowUsers: The
sshd_configfile has anAllowUsersdirective, and your username is missing from it. - Connection closed by authenticating user: The client gave up, often due to the "too many authentication failures" issue.
Step 3: SELinux Contexts (RHEL/CentOS Specific)
If you are on an SELinux-enforced system (like RHEL, AlmaLinux, or Rocky Linux), having the correct Unix permissions (chmod 600) is not enough. The files must also have the correct SELinux security context. If you moved your .ssh directory or created it as the root user, the context might be wrong.
Restore the correct SELinux contexts with this command:
restorecon -Rv ~/.ssh Conclusion
Mastering SSH troubleshooting turns hours of frustrating downtime into a quick 2-minute diagnostic process. By understanding the difference between network timeouts, cryptographic mismatches, and strict permission requirements, you can identify the root cause immediately. Remember: never guess—always use ssh -vvv and read the logs.
Secure your infrastructure properly. Don't rely on passwords, manage your keys securely, and leverage local-only tools like ZeroData Tools to maintain ultimate privacy while building your configurations.