OnepilotDownload
Onepilot mascot

SSH Connection Refused: How to Tell What Is Actually Wrong

Connection refused, connection timed out, no route to host, and could not resolve hostname are four different failures with four different causes. How to read which one you have, and fix each.

sofiane8910

by sofiane8910 · July 25, 2026 · 9 min read

Onepilot runs these agents from your iPhone, download it on the App Store.

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?

ErrorWhat happenedWhat it rules out
Connection refusedTCP reset came backHost is up and reachable. Look at sshd and the port.
Connection timed outNothing came back at allNothing. Packets are vanishing: firewall dropping, wrong address, host down, or NAT.
No route to hostICMP unreachable came backThe failure is at the network layer: routing, subnet, or the host is off on a local network.
Could not resolve hostnameDNS returned nothingEverything 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.

FAQ

What does SSH connection refused mean?

It means your packet reached the machine and the machine actively rejected it by sending back a TCP reset. Something is there and answering; nothing is listening on the port you tried. The usual causes are that sshd is not running, that it is listening on a different port than the one you used, or that a firewall is configured to reject rather than silently drop. Importantly, 'refused' is good news compared to a timeout, because it proves the network path works.

What is the difference between connection refused and connection timed out?

Refused means something answered and said no, so you reached the host. Timed out means nothing answered at all, so your packets are disappearing somewhere. A timeout points at a firewall configured to drop rather than reject, the wrong IP address, a host that is powered off, or a machine behind NAT with no route in. The two errors point at opposite halves of the problem and should not be debugged the same way.

How do you check if sshd is running?

On the host, run sudo systemctl status ssh on Debian and Ubuntu, or sudo systemctl status sshd on RHEL-family systems, since the unit has a different name on each. Then confirm it is actually listening where you think with sudo ss -tlnp | grep ssh, which shows the port and the interface it is bound to. A service that is 'active (running)' but bound only to 127.0.0.1 will still refuse every connection from outside.

Why does SSH work on the local network but not from outside?

Almost always because the machine is behind NAT and has no public address, so there is nothing for an outside connection to reach. That usually shows as a timeout rather than a refusal, since the packets are dropped before they get anywhere. The fix is not an SSH setting; it is a way in, whether that is port forwarding, a mesh VPN, a reverse tunnel, or an outbound relay.

Related reading

Run your AI agents from your iPhone

Download Onepilot on the App Store.

See also: the three-layer agent overview, run Hermes on iPhone, or all articles.