"No route to host": usually a firewall saying no, sometimes a machine that isn't there
Fix "No route to host" from ssh, curl or nc: check the firewall on the other machine (firewalld rejects by default), then whether the host is up.
by OhSudo ··
Not sure this is your cause?Find it step by step: Can't connect over SSH →
ssh: connect to host 203.0.113.20 port 22: No route to hostnc: connect to 203.0.113.20 port 8080 (tcp) failed: No route to hostNcat: No route to host.Recent versions of curl hide the reason, and only say Failed to connect to 203.0.113.20 port 8080 after 3 ms: Couldn't connect to server. To see which error it really is, try the same port with nc or ssh, as below.
The name suggests a routing problem, and that’s rarely it. In practice, this message has two causes:
- A firewall rejected you, and said so. The best-known source is firewalld, the default on RHEL, Rocky and AlmaLinux: its default zone answers anything it doesn’t allow with “host prohibited”, which Linux shows as
No route to host. - The machine isn’t there. On your own local network, nothing answered for that address.
A quick test tells them apart: does ping work?
- Clientconnects to 203.0.113.20:22reaches
- firewalld on the serverrejects: host prohibited(breaks here)answers with a reject(fails)
- Client seesNo route to host
TL;DR
ping -c 2 203.0.113.20nc -zv -w 5 203.0.113.20 8080Ping works, and the port says No route to host? It’s a firewall: on the other machine, open the port.
sudo firewall-cmd --permanent --add-port=8080/tcpsudo firewall-cmd --reload1. A firewall on the other machine
Practice this in the terminal: on the Rocky tab, the server has firewalld as installed, which allows only a few services.
ports: is empty, and services: lists only ssh, cockpit and dhcpv6-client. So port 8080 is rejected, while SSH works. That’s the telltale sign: some ports work, and others say No route to host. Open the one you need:
sudo firewall-cmd --permanent --add-port=8080/tcpsudo firewall-cmd --reloadexitnc -zv -w 5 app01 8080Now the answer changes to Connection refused, which is progress: the firewall lets you through, and nothing listens on that address. In this scenario, the app only listens on 127.0.0.1. That’s the next step, explained in “Connection timed out” vs “Connection refused”.
Other firewalls. An iptables or nftables rule with REJECT --reject-with icmp-host-prohibited gives the same result. On Ubuntu, ufw drops by default, which gives a timeout instead. Network firewalls and cloud security groups usually drop as well, so they give timeouts.
2. The machine isn’t there
If ping fails too, and the address is on your local network, then nothing answered when your machine asked who has that address:
ip neigh show 192.168.1.50FAILED or INCOMPLETE means no reply. The machine is off, has another address, or is on a different network segment or VLAN. Check its address from its console, and look for a typo. A virtual machine whose network adapter is disconnected, or on a different virtual switch, does this too.
3. Your own routes
Now the name fits: your machine doesn’t know where to send packets for that address.
ip route get 203.0.113.20ip routeNo default via line means no gateway, so only the local network is reachable. A VPN can add routes that capture traffic, and send it nowhere. Check the subnet mask too: with a wrong mask, a machine believes a remote address is local, and asks for it on the local network, where nothing answers. The Subnet Calculator shows which addresses a mask includes.
4. Docker networks
Docker creates networks such as 172.17.0.0/16 and 172.18.0.0/16. If your company network, or a VPN, uses the same range, then traffic for those addresses goes into Docker instead, and you get this error for real machines. Check:
ip route | grep -E 'docker|br-'Move Docker to another range in /etc/docker/daemon.json, with default-address-pools, then restart Docker and recreate the networks.
5. Check the firewall on your own side
Your outgoing rules can reject too. On RHEL, sudo firewall-cmd --list-all on the client, and on any machine, sudo nft list ruleset | grep -i reject shows reject rules.
Warning
Don’t stop firewalld to fix this: systemctl stop firewalld opens every port on the machine. Open the one port you need, and only to the addresses that need it, with a rich rule or a zone. The Port Lookup says which ports should never face the internet.
Shell, we have a problem!
Similar, but different: Connection refused means you reached the machine, and nothing listens on that port. Connection timed out means packets disappear without an answer, usually a firewall that drops. Network is unreachable means you have no route at all, not even a gateway. And Temporary failure in name resolution happens before any connection: see that article.
$ ./practice.sh
Practice this in the terminal
Open the Terminal Playground with this article’s scenario loaded. It is safe and runs in your browser.
Found this useful? Share it.
Found a mistake? Let us know at contact@ohsudo.com.