Locked out of SSH: how to get back into your server
Read the exact error message first: a timeout, "Connection refused" and "Permission denied" point to three different causes. Then get in another way (provider console, KVM or rescue system), fix the one thing that is wrong, and test from a second window before you log out.
Do this first.
- If you still have an open SSH session anywhere, keep it open. Do not log out until the fix is tested.
- Run
ssh -v user@serverand note where it stops. - Try from a different network (a phone hotspot, for example). If that works, your own IP address is probably banned.
- Open your provider's web console, serial console or KVM. You don't need SSH to use it.
Symptoms: read the error
- Connection timed out
- Packets get dropped before they reach sshd. Usual causes: a firewall rule (on the server or in the cloud provider's security group), the server is down or overloaded, or you have the wrong IP address.
- Connection refused
- The server answered, but nothing is listening on that port, or a firewall rule rejects the connection. sshd may have failed to start, or it now listens on another port.
- Permission denied (publickey) or (publickey,password)
- sshd is running and reachable, and authentication failed. Check the username, the key, the file permissions, SELinux labels and settings such as
AllowUsersorPermitRootLogin. - Connection closed or reset right after connecting
- sshd is limiting you. Possible causes:
MaxStartups(too many unauthenticated connections), thePerSourcePenaltiesfeature in recent OpenSSH (enabled by default, for example in OpenSSH 10.0 on Debian 13), or a fail2ban rule (fail2ban is a tool that bans addresses after repeated failed logins).
A fail2ban ban can show up as either a timeout or "refused", depending on which ban action it uses.
Get in another way
- Dedicated server: use the IPMI/KVM console, or boot the provider's rescue system. On Hetzner Robot, for example, you activate the rescue system in the Rescue tab, then reboot. You log in as root with the password shown at activation, or with an SSH key you already uploaded.
- AWS EC2: the EC2 Serial Console works on Nitro-based instances once an administrator enables account access. You need an OS user with a password. The
AWSSupport-TroubleshootSSHrunbook can check for and fix common SSH problems. If neither is possible, stop the instance, attach its root volume to a temporary instance and fix the files there. - Google Cloud: enable the interactive serial console with
gcloud compute instances add-metadata INSTANCE --metadata serial-port-enable=TRUE, then rungcloud compute connect-to-serial-port INSTANCE. Google images don't allow password logins by default. - Azure: open the VM, then Help, then Serial console. Boot diagnostics must be on, and you need a user with a password. "Reset password" in the same Help section can create one.
Fix: fail2ban banned you
Find your public IP address from another device, then on the server, as root:
sudo fail2ban-client banned 203.0.113.10
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.10
fail2ban-client unban 203.0.113.10 removes the address from every jail at once. To stop it happening again, add your fixed office or VPN address to ignoreip in /etc/fail2ban/jail.local (never in jail.conf), then run sudo fail2ban-client reload.
Fix: firewall rule mistakes
List the active rules, then add back an allow rule for SSH. Use the tool that manages your server's firewall. Don't mix tools.
# ufw (Debian/Ubuntu)
sudo ufw status numbered
sudo ufw allow proto tcp from 203.0.113.10 to any port 22
# firewalld (RHEL, AlmaLinux, Rocky, Fedora)
sudo firewall-cmd --query-panic
sudo firewall-cmd --list-all
sudo firewall-cmd --add-service=ssh
sudo firewall-cmd --runtime-to-permanent
# plain nftables: show rule handles, then delete the bad rule
sudo nft -a list ruleset
sudo nft delete rule inet filter input handle 5
If you changed the SSH port, the new port must be open too. Check the cloud provider's firewall or security group as well. A rule there blocks traffic before it ever reaches the server.
Fix: sshd config errors
A typo in /etc/ssh/sshd_config or a file in /etc/ssh/sshd_config.d/ can stop sshd from starting after a restart. From the console:
sudo sshd -t # syntax and key check; no output = OK
sudo sshd -T | grep -iE '^(port|listenaddress|passwordauthentication|permitrootlogin|allowusers|authenticationmethods)'
sudo ss -tlnp 'sport = :22'
sudo journalctl -u ssh -b # Debian/Ubuntu (RHEL family: -u sshd)
Fix the line that sshd -t reports, then restart the service. This restarts a service, but existing sessions stay connected:
sudo systemctl restart ssh # Debian/Ubuntu
sudo systemctl restart sshd # RHEL family
On Ubuntu 22.10 and later, sshd is started by ssh.socket (socket activation). If you changed Port or ListenAddress, run sudo systemctl daemon-reload and then sudo systemctl restart ssh.socket. On RHEL-family systems with SELinux, a new port must also be allowed: sudo semanage port -a -t ssh_port_t -p tcp 2222.
Fix: lost key or wrong permissions
Create a new key pair on your own computer (ssh-keygen -t ed25519). Through the console, add the contents of the .pub file as a new line in ~/.ssh/authorized_keys for the user, then set the ownership and permissions:
sudo chown -R alice:alice /home/alice/.ssh
sudo chmod 700 /home/alice/.ssh
sudo chmod 600 /home/alice/.ssh/authorized_keys
sudo chmod go-w /home/alice
sshd ignores authorized_keys if other users can write to the file, the .ssh directory or the home directory (StrictModes, on by default). From a rescue system, mount the server's disk first (for example mount /dev/md2 /mnt) and edit /mnt/home/alice/.ssh/authorized_keys. If you lost a key you also suspect was stolen, follow the credential rotation steps.
Fix: SELinux labels on authorized_keys
On RHEL-family systems, a file you moved into ~/.ssh (for example from /tmp) keeps its old SELinux label, and sshd is not allowed to read it. Key login then fails even though the permissions look right. Restore the default labels:
ls -Z /home/alice/.ssh/authorized_keys
sudo restorecon -Rv /home/alice/.ssh
If you fixed files from a rescue system, which doesn't set SELinux labels, run touch /mnt/.autorelabel before you reboot. The next boot then relabels the whole file system, which can take a while.
Confirm it is fixed
- From a second terminal,
ssh -v user@serverlogs in. Your old session stays open until this works. sudo sshd -tprints nothing.- The service survives a restart:
systemctl is-active ssh(orsshd) printsactive. - The firewall changes are permanent and survive a reboot.
Prevent it next time
- Run
sudo sshd -tbefore every restart, and keep one session open while you test. - Test firewall changes with a timeout. In firewalld, a runtime rule added with
--timeout=10mremoves itself after ten minutes, so a rule that locks you out does not stay. - Keep two keys from two devices in
authorized_keys, and store a backup key offline. - Know how to reach your console before you need it. Set a strong password on one admin account so that you can log in at the serial console.
- See SSH hardening for a safe baseline.
When to call your host or a professional
Contact your hosting provider if the console shows that the server doesn't boot, if you can't reach any console, or if a network-level block (a provider firewall or null route) is in place. If you see logins you don't recognise, keys you didn't add, or sshd_config changes you didn't make, treat it as a possible break-in: see Signs of compromise and Incident response.
Sources
- sshd(8) manual page, OpenBSD/OpenSSH
- sshd_config(5) manual page, OpenBSD/OpenSSH
- fail2ban-client(1), Debian manpages
- jail.conf(5), Debian manpages
- ufw(8), Ubuntu manpages
- firewall-cmd manual page, firewalld
- nft(8), Debian manpages
- restorecon(8), Debian manpages
- sshd now uses socket-based activation (Ubuntu 22.10 and later), Ubuntu Discourse
- Hetzner Rescue System, Hetzner Docs
- EC2 Serial Console for instances, AWS
- Troubleshoot issues connecting to your Amazon EC2 Linux instance, AWS
- Troubleshoot an impaired EC2 Linux instance using EC2Rescue, AWS
- Troubleshooting using the serial console, Google Cloud
- Azure Serial Console for Linux, Microsoft Learn