Introduction / Why This Is Needed
SSH (Secure Shell) is the primary tool for remote management of Linux servers. Connection issues can paralyze operations: you won't be able to deploy an application, update the system, or even regain access after a failure. This guide systematizes troubleshooting, starting from basic network checks and ending with log analysis. You'll get a clear action plan that works on most distributions (Ubuntu, Debian, CentOS, Arch).
Prerequisites / Preparation
- Console access on the target server (via KVM, iLO, hosting panel console) or access from another working node on the network.
- sudo or root privileges on the server to restart services and view logs.
- The
openssh-clientpackage installed on your local machine. - Basic understanding of the Linux command line.
Step 1: Checking Basic Network Accessibility
Before diving into SSH configuration, ensure the server is reachable over the network and the SSH port is open.
# 1. Check if the host responds (replace server_ip with the IP or domain)
ping -c 4 server_ip
# 2. Check if the SSH port (default 22) is open using netcat (nc)
# Install nc if missing: sudo apt install netcat (Debian/Ubuntu) or sudo yum install nc (RHEL/CentOS)
nc -zv server_ip 22
# Alternative with nmap (if installed)
nmap -p 22 server_ip
ncresult:Connection to server_ip 22 port [tcp/ssh] succeeded!— port is open.ncresult:Connection refused— port is closed or service is not listening.ncresult:No route to hostor timeout — issues at the network level (firewall, routing, host is down).
⚠️ Important: If
pingfails, the problem is not with SSH but with the network. Check IP settings, gateway, firewall on the local machine, and intermediate devices.
Step 2: Diagnosing the SSH Service on the Server
If the port is open but the connection isn't established, check if the sshd daemon is running.
# 1. Check service status (for systemd)
sudo systemctl status sshd
# 2. Find out which port(s) the service is listening on
sudo ss -tlnp | grep sshd
# Or
sudo netstat -tlnp | grep sshd
Common scenarios:
- Service is inactive (
inactive): Start it:sudo systemctl start sshdand enable autostart:sudo systemctl enable sshd. - Service listens only on
127.0.0.1:22instead of0.0.0.0:22(or:::22): This meanssshdis configured to accept connections only locally. Check theListenAddressparameter in the config (see Step 3). - Service listens on a non-standard port (e.g., 2222): Either change the port on the client (
ssh -p 2222 user@host) or revert to the standard port in the config.
Step 3: Analyzing SSH Server Configuration
The main configuration file is /etc/ssh/sshd_config. Make changes cautiously and create a backup: sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.
# View current configuration, ignoring comments
sudo cat /etc/ssh/sshd_config | grep -v "^#" | grep -v "^$"
Critical parameters to check:
| Parameter | Recommended value / What to check |
|---|---|
Port | Ensure the port matches the one you're trying to connect to (default 22). |
ListenAddress | Should be 0.0.0.0 (all interfaces) or the server's specific IP. If commented out — the default is used. |
PermitRootLogin | prohibit-password (recommended) or no. If root login is needed, temporarily set to yes for diagnostics. |
PasswordAuthentication | yes (if you want to use a password) or no (if only keys). |
PubkeyAuthentication | Must be yes if you're using key-based authentication. |
AllowUsers / AllowGroups | If these directives exist, ensure your user is listed. |
DenyUsers / DenyGroups | Ensure your user is not denied. |
After any config change, restart the service:
sudo systemctl restart sshd
Step 4: Checking SSH File and Directory Permissions (for Key-Based Authentication)
The SSH server is very strict about file permissions. Incorrect permissions are a frequent cause of Permission denied (publickey).
On the server (as the user you're trying to log in as):
# 1. Check permissions on the user's home directory
ls -ld ~
# 2. Check permissions on the .ssh directory
ls -ld ~/.ssh
# 3. Check permissions on the authorized_keys file
ls -l ~/.ssh/authorized_keys
Correct permissions:
- Home directory (
/home/username):drwxr-xr-x(755) or stricter. .sshdirectory:drwx------(700).authorized_keysfile:-rw-------(600).- Owner of all these objects should be the user logging in.
Fixing permissions:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
# Sometimes helps:
chown -R username:username ~/.ssh
💡 Tip: If you just generated a key and copied it to the server, ensure you copied the public key (file
id_ed25519.puborid_rsa.pub), not the private one, and that it was added toauthorized_keysas a single line.
Step 5: Analyzing SSH Logs
Logs are the most reliable source of truth. Where to look depends on the distribution.
# For RHEL/CentOS/Fedora/AlmaLinux/Rocky Linux and derivatives:
sudo tail -f /var/log/secure
# For Debian/Ubuntu and derivatives:
sudo tail -f /var/log/auth.log
# Universal method via systemd journal (works everywhere):
sudo journalctl -u sshd -f
What to look for in logs:
Failed password for ...— password error.Connection closed by ...— client disconnected, often due to key issues.Authentication refused: bad ownership or modes for directory /home/...— incorrect permissions (see Step 4).User ... not allowed because not listed in AllowUsers— user is denied in config.Received disconnect from ...: 11: Bye Bye— may indicate a session or key problem.Invalid user ...— attempt to log in as a non-existent user.
Example for quick filtering by IP or user:
sudo journalctl -u sshd | grep "192.168.1.100"
sudo journalctl -u sshd | grep "user_login"
Step 6: Testing Connection with Debugging (Client Side)
Run the connection with maximum verbosity. This will show exactly where the failure occurs.
# Maximum detailed logs (3 levels of -v)
ssh -vvv user@server_ip
What to notice in the output:
debug1: Connecting to server_ip [server_ip] port 22.— client found host and port.debug1: Connection established.— TCP connection succeeded.debug1: Authenticating to server_ip:22 as 'user'— start of authentication.debug1: Offering public key: /home/you/.ssh/id_ed25519 ...— client offers a key. If no key is offered, maybessh-agentisn't running or the key isn't added (ssh-add -l).debug1: Authentications that can continue: publickey,password— server lists accepted authentication methods.debug1: Offering public key: ...repeats, thendebug1: Authentications failed.— server rejected the key (server-side issue: key not inauthorized_keys, wrong permissions, SELinux).- If followed by
debug1: Next authentication method: password, the server accepted a fallback to password (ifPasswordAuthentication yes).
Client options for testing:
# Disable key usage (test password authentication)
ssh -o PubkeyAuthentication=no user@server_ip
# Specify a particular key
ssh -i ~/.ssh/my_specific_key user@server_ip
# Disable known_hosts check (dangerous, for testing only!)
ssh -o StrictHostKeyChecking=no user@server_ip
Verifying Success
A successful connection will end with the remote server's command prompt. In the client logs (-vvv), you'll see:
debug1: Authentication succeeded (publickey).
Authenticated to server_ip ([server_ip]:22).
On the server in the logs, an entry will appear:
Accepted publickey for user from client_ip port client_port ssh2: ED25519 SHA256:...
Common Issues
| Symptom | Likely Cause | Solution |
|---|---|---|
ssh: connect to host server_ip port 22: Connection refused | sshd service not running, listening on a different port, or blocked by firewall. | Start sshd (sudo systemctl start sshd). Check port (ss -tlnp). Check firewall (sudo ufw status or sudo firewall-cmd --list-all). |
ssh: connect to host server_ip port 22: Operation timed out | Network traffic is blocked along the route (server firewall, cloud Security Group, ISP). | Check all firewalls: on server (iptables -L -n, ufw, firewalld), in hosting/cloud control panel (Security Groups, Network ACLs). |
Permission denied (publickey,password). | 1. Incorrect/missing key in authorized_keys.2. Incorrect permissions on .ssh files.3. User denied in sshd_config (AllowUsers, DenyUsers).4. SELinux/AppArmor blocking access. | 1. Recopy the key. 2. Fix permissions (700/600). 3. Check sshd_config for denials.4. Check SELinux logs ( sudo ausearch -m avc -ts recent). Temporarily disable: sudo setenforce 0 (for diagnostics). |
The authenticity of host 'server_ip (server_ip)' can't be established. | First time connecting to the server; its key is missing from ~/.ssh/known_hosts. | This is a warning, not an error. If you trust the server, type yes. If the key changed (e.g., OS reinstall), remove the old record: ssh-keygen -R server_ip. |
Connection closed by remote host | Server disconnects during authentication. Often due to key mismatch or session issues. | Check sshd logs for errors. Ensure no restrictions like MaxSessions or ClientAliveInterval in sshd_config. |
Additional Diagnostic Methods
If standard steps didn't help, check the following:
- Checking the server firewall (UFW example):
sudo ufw status numbered # If a rule for 22/tcp is missing, add it: sudo ufw allow 22/tcp - Checking SELinux/AppArmor:
# For SELinux (RHEL/CentOS/Fedora) sudo sestatus sudo ausearch -m avc -ts recent | grep sshd # For AppArmor (Debian/Ubuntu) sudo aa-status | grep sshd - Checking
/etc/hosts.allowand/etc/hosts.deny: These files can block access. Ensuresshd: ALLor your IP is inhosts.allow, andsshd: ALLis not inhosts.deny. - Checking server resources: If the server is overloaded (out of memory, disk space),
sshdmay not accept new connections. Check:free -h,df -h,top. - Test from another client: Try connecting from a different machine. If it works — the problem is with the original client (its keys,
~/.ssh/config, firewall). - Temporarily increase logging level in
sshd_config: Uncomment or addLogLevel DEBUGand restartsshd. Remember to revert toINFOafter diagnostics!
sudo sed -i 's/^#LogLevel.*/LogLevel DEBUG/' /etc/ssh/sshd_config
sudo systemctl restart sshd
# ... perform connection attempt ...
# Revert:
sudo sed -i 's/^LogLevel.*/LogLevel INFO/' /etc/ssh/sshd_config
sudo systemctl restart sshd
Conclusion
SSH troubleshooting is a sequential process of elimination: network -> service -> config -> permissions -> logs. Start with simple checks (ping, nc, systemctl status sshd), then delve into configuration and permissions. Logs (journalctl -u sshd or /var/log/auth.log) almost always contain the specific reason for failure. Use the client-side debug mode (ssh -vvv) to see the process from the other side. After resolving the issue, don't forget to restore security settings (e.g., LogLevel and PermitRootLogin) to their original state.