SSH gives you four different errors when it cannot open a connection, and each one narrows the problem down considerably. Most guides treat them as interchangeable and offer the same checklist for all four, which wastes time. The message you got is evidence. Here is how to read it.
What does "Connection refused" mean in SSH?
It means your packet arrived and the machine sent back a TCP reset, which is an active, deliberate "no." Something is there, awake, and answering. Nothing is listening on the port you tried, or something is rejecting it on purpose.
This is genuinely good news. A refusal proves the network path works end to end: DNS resolved, routing worked, the host is up, and it processed your packet fast enough to say no. The problem is confined to the machine and to one port. That is a much smaller search space than the alternatives.
Connection refused, timed out, no route to host: what is the difference?
| Error | What happened | What it rules out |
|---|---|---|
Connection refused | TCP reset came back | Host is up and reachable. Look at sshd and the port. |
Connection timed out | Nothing came back at all | Nothing. Packets are vanishing: firewall dropping, wrong address, host down, or NAT. |
No route to host | ICMP unreachable came back | The failure is at the network layer: routing, subnet, or the host is off on a local network. |
Could not resolve hostname | DNS returned nothing | Everything else. You never got as far as sending a packet. |
The distinction that matters most is refused versus timed out, because they point in opposite directions. Refused means go and look at the server. Timed out means go and look at the network between you and it. Applying the refused checklist to a timeout, which is what most people do, means checking a service that your packets are never reaching.
A useful first move for a timeout is to find out whether anything about the host is reachable at all. ping host is a weak signal, since plenty of firewalls drop ICMP while allowing TCP, but nc -vz host 22 tells you specifically whether port 22 accepts a TCP connection, and separates a broken SSH service from a broken path.
How do you fix SSH connection refused?
1. Check that sshd is running
The service name differs by distribution, which is itself a small trap:
sudo systemctl status ssh on Debian and Ubuntu
sudo systemctl status sshd on RHEL, Fedora, Rocky, and Alma
If it is not running, sudo systemctl start ssh starts it and sudo systemctl enable ssh makes that survive a reboot. If it refuses to start, sudo sshd -t validates the config and names the offending line, which is the usual explanation after someone edited sshd_config.
2. Check what it is listening on
A running service is not the same as a reachable one:
sudo ss -tlnp | grep ssh
Read the address column carefully. 0.0.0.0:22 means all interfaces, which is what you want. 127.0.0.1:22 means loopback only, and every connection from outside the machine will be refused no matter what the firewall says. That happens when ListenAddress is set in sshd_config. The port matters too: plenty of hosts move SSH off 22, and connecting to the wrong port produces exactly this error. Try ssh -p 2222 user@host if you suspect that.
3. Check the firewall
A firewall that rejects gives you connection refused; one that drops gives you a timeout. So a refusal can come from the firewall as easily as from a missing service:
sudo ufw status on Ubuntu, then sudo ufw allow 22/tcp
sudo firewall-cmd --list-all on RHEL-family, then sudo firewall-cmd --add-service=ssh --permanent and --reload
sudo iptables -L -n for the raw rules
On a cloud host there is a second firewall you do not see from inside the machine. AWS security groups, Hetzner and DigitalOcean cloud firewalls, and GCP VPC rules all sit in front of the instance, and none of them show up in ufw status. If the host-level firewall looks correct, check the provider's console next. This is one of the most common causes of a connection failure that makes no sense from inside the box.
4. Check you are connecting to the right address
Obvious and worth ruling out early, especially on home networks where DHCP moves addresses around. A Raspberry Pi that answered on 192.168.1.50 last week may be on .61 today, and the old address may now belong to something else entirely, which is how you end up with a confident refusal from a printer. Reserve the address in your router's DHCP settings, or use the hostname with .local if mDNS is available.
What if SSH works locally but not from outside?
Then the service is fine and the problem is reachability. A machine behind a home router or an office NAT has a private address that means nothing on the public internet, so a connection from outside has nowhere to land. This usually shows as a timeout rather than a refusal, because the packets are dropped upstream rather than rejected by the host.
No SSH setting fixes this, because SSH is not what is broken. You need a route in, and there are four ways to get one: forward a port on the router, put both machines on a mesh VPN, hold a reverse tunnel to a server you own, or have the host dial out to a relay. Which to pick, and why port forwarding fails outright under CGNAT, is covered in SSH without port forwarding.
How do you get in when you cannot get in at all?
If SSH is the only way onto the machine and SSH is what is broken, you need an out-of-band route. On a cloud host that is the provider's serial or web console, which reaches the login prompt without touching the network stack: AWS EC2 Serial Console, the DigitalOcean and Hetzner web consoles, or a rescue mode that boots a recovery image with your disk mounted. On hardware you can reach, a keyboard and monitor. On a Pi, the SD card in another computer.
The habit that prevents most of this: whenever you edit sshd_config, run sudo sshd -t before reloading, and keep your current session open while you test a new one from a second terminal. An existing session survives a broken config; you only discover the mistake when you disconnect, and by then it is too late.
The short version
Read the error before doing anything else. Refused means the host answered and you should look at sshd, its port, and the firewall, including the cloud-provider firewall you cannot see from inside. Timed out means nothing answered and you should look at the path, the address, and whether the host is behind NAT. No route to host is a network-layer problem. Could not resolve hostname is DNS and nothing else.
For a machine at home that you keep needing to reach from elsewhere, the underlying issue is usually reachability rather than SSH itself, which is the part Onepilot handles differently: pairing runs one command on the host, provisions a relay when the host has no public address, and there is no port to open or forward. Once you are connected, the two failures you are most likely to meet next are Permission denied (publickey) and sessions that drop.
