Error Medic

How to Fix "ssh: connect to host port 22: Connection refused" (and Other SSH Errors)

Comprehensive troubleshooting guide to fix 'ssh connection refused'. Learn to resolve SSH failed connections, permission denied errors, and slow SSH logins.

Last updated:
Last verified:
2,145 words
Key Takeaways
  • A 'Connection refused' error means the server actively rejected the connection, typically because the SSH daemon (sshd) is down or listening on a different port.
  • If the connection drops completely without a response, it is a 'Connection timed out', which usually indicates a strict firewall or routing issue.
  • Permission denied errors are almost always related to incorrect file permissions on SSH keys or misconfigured sshd_config authentication settings.
  • Slow SSH logins are frequently caused by DNS resolution timeouts or GSSAPI authentication hangs; these can be fixed by modifying the server's sshd_config.
  • Always use the verbose flag (ssh -vvv) as your first diagnostic step to pinpoint exactly where the SSH handshake or authentication is failing.
SSH Troubleshooting Approaches Compared
Diagnostic MethodWhen to UseTime to ExecuteRisk Level
Verbose Mode (ssh -vvv)For 'ssh slow', 'ssh failed', or identifying exactly where the connection drops.1-2 minutesNone
Check SSH Daemon (systemctl status ssh)When encountering 'Connection refused' to ensure the service is running.2 minutesLow
Audit Port & IP (ss -tulpn)If SSH is running but unreachable, verifying it binds to the correct port/interface.3 minutesLow
Adjust Firewall Rules (ufw/iptables)When port 22 is actively blocked or filtering incoming TCP SYN packets.5-10 minutesHigh (Lockout risk)
Fix Key Permissions (chmod 600)When facing 'Permission denied (publickey)' due to overly permissive key files.1 minuteLow

Understanding the "SSH Connection Refused" Error

When you attempt to connect to a remote server using Secure Shell (SSH) and receive the exact error message: ssh: connect to host 192.168.1.10 port 22: Connection refused, it can halt your workflow immediately. To fix it, you must first understand what this error means at a network level.

Unlike a "Connection timed out" error—where your client sends a connection request and hears nothing back—a "Connection refused" error means your client reached the target server, but the server actively rejected the connection. Specifically, your client sent a TCP SYN packet to initiate the TCP handshake on port 22, and the server's operating system responded with a TCP RST (Reset) packet.

This actively negative response tells us a few critical things:

  1. The server is online: The machine is powered on and reachable over the network.
  2. Routing is correct: Your packets are successfully navigating the network path to the destination.
  3. The port is closed: The most common reason for a TCP RST is that there is no service actively listening on the requested port (typically port 22), or a local host-based firewall is explicitly configured to reject (rather than drop) the traffic.

Step 1: Diagnosing the Root Cause

To troubleshoot this, you need out-of-band access to the server. Since SSH is down, you must use your cloud provider's web console, a hypervisor console (like VMware vSphere or Proxmox), or a physical keyboard and monitor if it is a bare-metal server.

Verify the SSH Daemon is Running

The most frequent cause of ssh connection refused is that the OpenSSH server daemon (sshd) has crashed, was stopped manually, or failed to start during the boot process.

Check the status of the SSH service:

sudo systemctl status ssh
# On RHEL/CentOS/Fedora systems, the service is named sshd:
sudo systemctl status sshd

If the output indicates the service is inactive (dead) or failed, attempt to start it:

sudo systemctl start ssh

If it fails to start, investigate the systemd journal for specific error messages:

sudo journalctl -xeu ssh

Often, a syntax error in the /etc/ssh/sshd_config file prevents the service from starting. You can test the configuration file for validity before restarting the service by running: sudo sshd -t.

Verify the Listening Port and IP Binding

If the service is running perfectly, it might be listening on a non-standard port or bound to a specific IP address that you are not targeting.

Use the ss utility to check active listening ports:

sudo ss -tulpn | grep ssh

You should see an output similar to: tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1234,fd=3))

If the port is listed as something other than 22 (e.g., *:2222), you must instruct your client to use that port: ssh -p 2222 user@hostname

If the IP binding is strictly set to 127.0.0.1:22, the server is only accepting local connections. You will need to edit /etc/ssh/sshd_config, change the ListenAddress directive to 0.0.0.0 (or the specific public IP), and restart the service.

Investigate Host-Based Firewalls

If sshd is running and listening on the correct port, a local firewall might be explicitly rejecting the traffic.

On Ubuntu/Debian systems using UFW:

sudo ufw status

If port 22 is not allowed, add the rule:

sudo ufw allow ssh

On RHEL/CentOS systems using firewalld:

sudo firewall-cmd --list-all

To add the SSH service permanently:

sudo firewall-cmd --add-service=ssh --permanent
sudo firewall-cmd --reload

Note: Do not forget to check external firewalls, such as AWS Security Groups, Azure Network Security Groups, or physical network edge firewalls that might be interfering with traffic.

Fixing "SSH Permission Denied"

Often, you will successfully establish a network connection, but the server rejects your authentication attempt with Permission denied (publickey,password). This means SSH is working, but you lack the correct credentials or your keys are misconfigured.

1. Client-Side Key Permissions

SSH is notoriously strict about file permissions. If your private key (~/.ssh/id_rsa, ~/.ssh/id_ed25519) is readable by other users on your local machine, the SSH client will outright refuse to use it, silently falling back to password authentication (which may be disabled).

Ensure your local private key has strict permissions:

chmod 600 ~/.ssh/id_ed25519

2. Server-Side Configuration and Permissions

The target server is equally strict. If the home directory, the .ssh directory, or the authorized_keys file has overly permissive rights, the SSH daemon will ignore the keys for security reasons.

On the remote server, ensure the following permissions are set for the connecting user:

chmod 700 ~/
chmod 700 ~/.ssh
chmod 644 ~/.ssh/authorized_keys

Additionally, check the ownership. The directory and files must be owned by the user you are trying to log in as:

chown -R username:username ~/.ssh

3. SELinux Contexts (Red Hat/CentOS/Fedora)

If you have verified permissions and are still getting Permission denied, SELinux might be blocking the SSH daemon from reading the authorized_keys file. This frequently happens if you move directories around instead of creating them natively.

Restore the default SELinux contexts for the SSH directory:

sudo restorecon -Rv ~/.ssh

Diagnosing "SSH Slow" or Hanging Connections

A highly frustrating scenario is when SSH connects successfully, but it takes 15 to 30 seconds for the password prompt to appear, or for the session to initialize after key authentication.

Disable Reverse DNS Lookups

By default, when you connect to an SSH server, the server attempts a reverse DNS lookup to resolve your IP address back to a hostname. If the DNS server is unreachable or slow to respond, SSH will hang until the query times out.

To disable this, edit /etc/ssh/sshd_config on the server:

UseDNS no

Disable GSSAPI Authentication

Another common culprit for slow logins is GSSAPI authentication (used for Kerberos). If you are not using Kerberos, the client may still attempt it and wait for a timeout.

Edit your client's ~/.ssh/config or the server's /etc/ssh/sshd_config to disable it:

GSSAPIAuthentication no

Restart the SSH service after making these changes: sudo systemctl restart ssh.

MTU and Path MTU Discovery Issues

If your SSH connection establishes the initial TCP handshake but hangs indefinitely at a debug message like expecting SSH2_MSG_KEX_ECDH_REPLY, you likely have a Maximum Transmission Unit (MTU) issue. This happens when packets are too large for a router along the path, and ICMP fragmentation needed messages are being dropped (a "black hole" router).

Lower the MTU on your client interface (e.g., to 1360) to see if the connection successfully completes.

Investigating the Rare "SSH Segfault"

While "connection refused" and "permission denied" are configuration issues, an ssh segfault (segmentation fault) is a programmatic crash of the SSH client or server binary. When you run the ssh command, it immediately terminates with Segmentation fault (core dumped).

Root Causes for Segfaults

  1. Library Mismatches: OpenSSH relies heavily on cryptographic libraries like OpenSSL (libcrypto). If your system performed a partial upgrade, or if a custom-compiled OpenSSL library conflicts with the system's glibc, the SSH binary will crash when attempting to dynamically link them.
  2. Hardware Security Tokens: If you use a YubiKey or SmartCard via PKCS#11 for SSH authentication, a bug in the middleware (like opensc) can crash the SSH client when it attempts to read the smartcard.
  3. Corrupted Known Hosts: Very rarely, a massively corrupted or maliciously malformed ~/.ssh/known_hosts file can trigger a buffer overflow bug in older SSH clients.

How to Fix a Segfault

First, isolate the issue by running SSH without reading local configuration files or known hosts:

ssh -F /dev/null -o UserKnownHostsFile=/dev/null user@host

If this works, your configuration or known_hosts file is the culprit.

If it still segfaults, you need to update or reinstall the OpenSSH package and its dependencies to ensure library consistency:

# On Debian/Ubuntu
sudo apt update
sudo apt install --reinstall openssh-client openssl

For advanced debugging, you can trace the segfault using strace or gdb:

strace -o ssh_trace.txt ssh user@host

Reviewing the bottom of ssh_trace.txt will show you exactly which system call or library load triggered the memory violation, allowing you to narrow down the faulty component.

Frequently Asked Questions

bash
#!/bin/bash
# SSH Diagnostic Script: Run this locally to troubleshoot connection issues

HOST=$1
PORT=${2:-22}

if [ -z "$HOST" ]; then
  echo "Usage: $0 <hostname_or_ip> [port]"
  exit 1
fi

echo "[1/3] Testing network reachability and TCP port $PORT on $HOST..."
nc -vz -w 3 "$HOST" "$PORT"
NC_STATUS=$?

if [ $NC_STATUS -eq 0 ]; then
    echo "✅ SUCCESS: Port $PORT is open. The network path is clear."
    echo "    If SSH still fails, the issue is authentication or sshd_config."
else
    echo "❌ ERROR: Port $PORT is unreachable or actively refusing connections."
    echo "    Check if sshd is running on the remote server, verify the port number,"
    echo "    and ensure no firewalls (UFW/iptables/Cloud Security Groups) are blocking port $PORT."
fi

echo ""
echo "[2/3] Checking local SSH private key permissions..."
find ~/.ssh -type f -name "id_*" ! -name "*.pub" -exec stat -c "%A %n" {} \; | while read PERMS FILE; do
    if [ "$PERMS" != "-rw-------" ]; then
        echo "❌ WARNING: Bad permissions ($PERMS) on $FILE"
        echo "    Run: chmod 600 $FILE"
    else
        echo "✅ OK: Permissions are correct for $FILE"
    fi
done

echo ""
echo "[3/3] To see a full debug trace of the connection, run:"
echo "ssh -vvv -p $PORT user@$HOST"
E

Error Medic Editorial

The Error Medic Editorial team consists of senior Site Reliability Engineers and DevOps practitioners dedicated to demystifying complex infrastructure issues. With decades of combined experience managing Linux servers at scale, we provide actionable, battle-tested solutions to keep your systems running smoothly.

Sources

Related Guides