Fix SSH No Route to Host: Routing, Firewall, and sshd Checks

Deepak Prasad
Tested on RHEL 10.2 (Coughlan) — vm2.lab.example (192.168.56.220, connects to vm1.lab.example from source 192.168.56.156) as SSH client; vm1.lab.example (192.168.56.116) as SSH server
Package openssh-clients 9.9p1-25.el10_2, openssh-server 9.9p1-25.el10_2, and firewalld on the server
Applies to RHEL, Rocky Linux, AlmaLinux, Fedora, Ubuntu, Debian, and other Linux systems with OpenSSH
Privilege Normal user on the client; sudo or root on the server for firewall and sshd checks (often via console when SSH is down)
Scope Interpreting No route to host for SSH, TCP reachability tests, local routing with ip route get, remote sshd and ListenAddress, and server firewalls (firewalld, nftables, ufw). Does not replace testing SSH end to end or cannot assign requested address on the server bind side.
Related guides ssh command
Test SSH connection
firewalld cheat sheet
ss command
traceroute command

ssh: connect to host … port 22: No route to host looks like a routing failure, but on Linux it often appears when a firewall REJECTs your TCP connection with an ICMP unreachable message. The wording is generic; the fix depends on whether the path, the port, or sshd itself is wrong.

There is no single switch that fixes every case. Work from the client first (can you open a TCP socket?), then routing and neighbor checks, then the server firewall. If the error becomes connection refused, check sshd on the server through the console or another out-of-band path.

The lab examples use vm2.lab.example reaching vm1.lab.example at 192.168.56.116. Your client may show a different source address than its primary hostname — check with ip route get <server-ip> before writing firewall rules.


What the error actually means

The OpenSSH client reports whatever errno the kernel returns from the TCP connect. No route to host (EHOSTUNREACH) means the kernel received or generated a host-unreachable condition while trying to connect. That can come from local routing, neighbor resolution, or an ICMP unreachable returned by another device or firewall — not from SSH authentication failure.

Linux maps both local routing or neighbor state and ICMP host-unreachable messages from remote routers or firewalls to the same errno on connect().

Common causes:

  • No usable route or gateway for the destination network
  • Same-subnet ARP failure (host down, wrong VLAN, duplicate IP)
  • A router or firewall returning ICMP host/network unreachable
  • A local or remote firewall REJECT rule (very common for SSH on RHEL-family systems with firewalld)

Do not assume the routing table is wrong until you rule out a REJECT on port 22.


Compare SSH connection errors

The message tells you which layer failed first:

Client message Typical meaning Server log useful?
No route to host ICMP unreachable or local unreachable before TCP handshake completes Usually no — packet may never reach sshd
Connection refused The TCP connection was actively refused — commonly because nothing is listening on that port, though a firewall can also reject with a reset Sometimes — check if sshd is down, bound elsewhere, or a firewall sent RST
Connection timed out Silent DROP along the path, or host not answering at L3/L4 Rarely
Network is unreachable No usable route to the destination network No

On the lab client, blocking sshd on the server produced connection refused, while a firewalld rich rule with reject type="icmp-host-prohibited" for the client source produced no route to host for the same target IP.


Test TCP reachability to the SSH port

Start with a plain TCP check to the SSH port (default 22). This avoids guessing from ping alone.

On the client, Bash can open /dev/tcp without extra packages:

bash
timeout 3 bash -c '</dev/tcp/192.168.56.116/22' && echo open || echo failed

When a lab firewall REJECT rule blocked the client source, the shell reported:

output
bash: connect: No route to host
bash: line 1: /dev/tcp/192.168.56.116/22: No route to host
failed

When sshd was stopped but the network path was open, OpenSSH reported connection refused instead — a different failure mode.

If you prefer netcat for port checks, use:

bash
nc -zv -w 3 192.168.56.116 22

A non-zero exit or No route to host here means the problem is still below SSH — fixing keys or sshd_config on the server will not help yet.


Check the local route to the server

Confirm the client knows how to reach the server IP:

bash
ip route get 192.168.56.116

Sample output from the lab client:

output
192.168.56.116 dev eth0 src 192.168.56.156 uid 0
    cache

The line names the outbound interface (eth0), the source address the kernel will use (192.168.56.156), and the direct path to the host. If this fails or points at the wrong interface (common with VPNs or multiple NICs), fix local routing before touching the server.

For remote networks, also verify a default gateway exists:

bash
ip route show default

When the destination is several hops away, traceroute or mtr shows where packets stop — useful when a gateway returns ICMP unreachable.

On the same subnet, check neighbor resolution when the host should be directly reachable:

bash
ip neigh show 192.168.56.116

A FAILED or incomplete entry can trigger host-unreachable errors even when the IP looks correct on paper.


Check the server firewall (common cause)

On RHEL-family systems, firewalld can REJECT blocked traffic with ICMP unreachable responses, which may surface as no route to host on the client — even though ping still works.

List the active zone and allowed services:

bash
firewall-cmd --list-all

Ensure the SSH service (or your custom port) is allowed for clients that need access:

bash
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload

In the lab, adding a rich rule that REJECTs the client source with icmp-host-prohibited reproduced the exact SSH error:

bash
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.56.156" service name="ssh" reject type="icmp-host-prohibited"'
sudo firewall-cmd --reload

From the client, SSH then failed with:

output
ssh: connect to host 192.168.56.116 port 22: No route to host

Removing that rule and reloading firewalld restored access. Check for:

  • Missing ssh service in the zone attached to the server interface
  • Rich rules that match your client source IP (not just the destination)
  • A separate source-based zone (for example NFS) that overrides public for specific clients — those clients can lose SSH while others still connect

On Ubuntu with ufw, verify Status: active and that OpenSSH or your port is allowed. On any distro, inspect nftables/iptables REJECT rules:

bash
sudo nft list ruleset | grep -i reject

Look for reject-with icmp host-prohibited or icmp-host-unreachable. REJECT differs from DROP: DROP tends to cause timeouts; REJECT often produces no route to host.

Avoid flushing entire firewall tables in production. Add explicit allow rules, or temporarily move the client into a trusted source list while you test.


If the error changes to Connection Refused

When TCP tests return connection refused instead of no route to host, the TCP connection was actively refused — commonly because nothing is listening on the SSH port, though a firewall can also reject with a reset. Check sshd and its listen settings first; if those look correct, inspect firewall rules that send TCP RST.

Run these on the server through the hypervisor console, IPMI, or provider shell when SSH is down.

Check the unit:

bash
systemctl status sshd

Confirm something listens on the SSH port (22 unless you changed it):

bash
ss -ntlp | grep ':22'

Sample output when sshd is healthy:

output
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1241,fd=7))
LISTEN 0 128    [::]:22    [::]:* users:(("sshd",pid=1241,fd=8))

Read the effective server settings (merged drop-ins), not just the file on disk:

bash
sshd -T | grep -E '^(port|listenaddress) '

Sample output:

output
port 22
listenaddress [::]:22
listenaddress 0.0.0.0:22

0.0.0.0:22 means all IPv4 addresses. A narrow listenaddress 10.0.0.5:22 accepts SSH only on that IP — connections to other addresses fail even when the service is running. Match the address you use in ssh user@….


Read ssh -vvv on the client

Verbose SSH still helps confirm where the client stops:

bash
ssh -vvv -o ConnectTimeout=5 user@192.168.56.116

When the network layer fails first, you see the TCP connect error immediately and no server banner or key exchange lines. That pattern means sshd logs on the server (journalctl -u sshd) stay quiet — the session never arrived.

Also review client-side config that might force the wrong address, port, or jump host:

bash
ssh -G 192.168.56.116 | grep -E '^(hostname|port|user|proxyjump) '

Files to check: ~/.ssh/config, /etc/ssh/ssh_config, and drop-ins under ssh_config.d.


Troubleshooting

Symptom Likely cause Fix
No route to host but ping works Remote or local firewall REJECT on TCP 22 (or your SSH port) Allow ssh service or port on the server zone; remove source-specific REJECT rich rules
Connection refused to port 22 sshd stopped or not listening on that IP/port systemctl start sshd; verify with ss -ntlp and sshd -T
Works from some clients only Source-based firewalld zone or rich rule firewall-cmd --get-active-zones; compare failing client source IP with ip route get
No route to host to every port Wrong route, down interface, or ARP failure ip route get, ip link, ip neigh; fix L2/L3 before SSH
Network is unreachable No route to destination network Check ip route get and the default/static routes; correct the route or gateway configuration
Local SSH OK, remote fails Host firewall or upstream filter Test TCP from remote client; inspect REJECT rules
After changing sshd_config Service not reloaded or ListenAddress too narrow sshd -T for effective values; systemctl reload sshd

References


Summary

SSH no route to host is a network-layer error, not an authentication problem. The name is misleading: Linux can return EHOSTUNREACH from local routing or neighbor state, or from an ICMP unreachable a firewall or router sends back — not only when the routing table lacks a path.

Follow the decision tree in order: test the SSH port with /dev/tcp or nc, run ip route get and ip neigh, inspect the server firewall for REJECT rules (especially when ping works but SSH does not), and only then — if the error is connection refused — check sshd and ListenAddress on the server console.

Once TCP connects, continue with SSH connection testing for keys, host keys, and auth. If the server fails at bind time with a local address error, see cannot assign requested address — a different failure than no route to host from the client.


Frequently Asked Questions

1. Does SSH no route to host always mean a routing problem?

No. Linux surfaces EHOSTUNREACH for several cases, including when a remote firewall answers with ICMP host-prohibited or host-unreachable on a REJECT rule. The host can be on the correct subnet and even respond to ping while SSH still prints no route to host.

2. What is the difference between no route to host and connection refused for SSH?

No route to host means the client never completed a TCP handshake because the kernel or an intermediate device reported the destination unreachable. Connection refused usually means the packet reached the host but nothing accepted the connection, often because sshd is stopped or listening on another address or port.

3. Can ping succeed while SSH shows no route to host?

Yes. Ping uses ICMP. SSH uses TCP port 22 or your custom port. A firewall can allow ICMP echo while REJECT-ing TCP to sshd, which produces no route to host on many Linux firewalls.

4. Why does ssh -vvv not help when the error is no route to host?

The failure happens before SSH protocol negotiation. Verbose client logs still show the TCP connect failing at the network layer, but the server auth log stays empty because sshd never received a completed connection.

5. How do I fix no route to host when I cannot SSH into the server?

Use out-of-band access such as a hypervisor console, IPMI, serial, or a cloud provider shell. From there confirm sshd is running, check ListenAddress and Port with sshd -T, and inspect firewalld, nftables, or ufw for REJECT or DROP rules on the SSH port or your client source address.
Omer Cakmak

Linux Administrator

Highly skilled at managing Debian, Ubuntu, CentOS, Oracle Linux, and Red Hat servers. Proficient in bash scripting, Ansible, and AWX central server management, he handles server operations on OpenStack, KVM, Proxmox, and VMware.

  • Debian
  • Ubuntu
  • Linux
  • Red Hat Enterprise Linux
  • Shell Script
  • System Administration