SSH Cheatsheet

Troubleshooting

Use this SSH reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

First Steps: Verbose Mode

Always start here. Add -v flags to get a detailed trace of what SSH is doing.

ssh -v user@host      # basic debug
ssh -vv user@host     # more detail
ssh -vvv user@host    # maximum detail (key offers, channel ops, etc.)

Read the output from the top — it shows each phase: DNS, TCP connect, version exchange, key exchange, authentication offers.

Common Errors and Fixes

ErrorCauseFix
Connection refusedsshd not running, wrong portCheck port with -p; verify systemctl status sshd on server
Connection timed outFirewall blocking port 22Check firewall; try -v to see where it hangs
Permission denied (publickey)Key not in authorized_keys, wrong perms, wrong key offeredSee auth section below
Permission denied (publickey,password)Password auth disabled and key not acceptedVerify key is in authorized_keys
Host key verification failedServer host key changedRun ssh-keygen -R host then reconnect
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!Same as above (or MITM)Verify the new fingerprint out-of-band, then ssh-keygen -R host
No such file or directory (socket)Control socket staleDelete the stale socket file under ~/.ssh/
Too many authentication failuresAgent offering too many keysUse -o IdentitiesOnly=yes -i key
Could not resolve hostnameDNS failureTry IP directly; check /etc/hosts
Broken pipeIdle connection droppedAdd ServerAliveInterval 60
channel 0: open failed: administratively prohibitedTCP forwarding disabled on serverSet AllowTcpForwarding yes in sshd_config
bind: Address already in useLocal port taken (tunnel conflict)Change local port or kill the process using it

Diagnosing Authentication Failures

# Show which keys the client is offering
ssh -vvv user@host 2>&1 | grep -E "Offering|Trying|key:|identity"

# Force only a specific key (bypass agent)
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 user@host

# Skip the config file entirely
ssh -F /dev/null user@host

# Try password auth explicitly
ssh -o PreferredAuthentications=password user@host

On the server, check the auth log:

# Debian/Ubuntu
tail -f /var/log/auth.log | grep sshd

# RHEL/CentOS/Fedora
journalctl -u sshd -f

# Look for permission errors
grep "Authentication refused\|bad ownership" /var/log/auth.log

Permission Problems

# Fix all at once
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/config

# Verify ownership (must be the user, not root)
ls -la ~/.ssh/

SSH silently rejects keys if ~/.ssh or authorized_keys is writable by group/other, or not owned by the user.

Stale Host Keys

# Server reimage / key rotation / new VM
ssh-keygen -R hostname
ssh-keygen -R 192.168.1.10

# Or edit manually
nano ~/.ssh/known_hosts    # delete the line for the host

Testing sshd Config

# Syntax check without restarting
sudo sshd -t

# Run in foreground on a test port (safe — doesn't replace your main sshd)
sudo /usr/sbin/sshd -ddd -p 2222

Then connect ssh -p 2222 user@localhost and watch both sides for detailed output.

Network Diagnostics

# Confirm sshd is listening
ss -tlnp | grep :22           # Linux
netstat -an | grep .22        # macOS/older

# Test TCP reachability
nc -zv host 22
telnet host 22

# Trace the route
traceroute host
mtr host

# Check if a firewall is blocking
nmap -p 22 host

Slow Login

# DNS reverse lookup causing delay (common cause)
# In /etc/ssh/sshd_config:
UseDNS no

# GSSAPI delay (Kerberos lookup timing out)
# In /etc/ssh/sshd_config:
GSSAPIAuthentication no
# Or on the client:
ssh -o GSSAPIAuthentication=no user@host

Debugging Tunnels and Forwarding

# Confirm tunnel is listening
ss -tlnp | grep PORT         # Linux
lsof -iTCP:PORT -sTCP:LISTEN # macOS

# Check the tunnel is routing correctly
curl -v http://localhost:LOCAL_PORT

# Kill a specific tunnel by control socket
ssh -S ~/.ssh/cm-user@host -O cancel -L 5432:db:5432 user@host

Useful One-Liners

# Fingerprint of a server you haven't connected to yet
ssh-keyscan host | ssh-keygen -lf -

# Which config block matches a host
ssh -G user@host | head -20

# Print the effective config for a host alias
ssh -G myalias