Fix "connect: No route to host" When Connecting to a Remote Server

intermediate🌐 Networking2026-03-24| Linux (Ubuntu, CentOS, RHEL, Debian) β€” affects SSH, curl, wget, TCP clients

Error Message

connect: No route to host
#networking#routing#firewall#iptables

What's happening

You run ssh user@192.168.1.50 or curl http://10.0.0.5:8080 and get hit with:

connect: No route to host

This error is distinct from two common lookalikes. Connection refused means the service is up but actively rejecting you. Connection timed out means packets are silently dropped somewhere. "No route to host" is different β€” the network stack quit early, either because it has no path to the target, or because something on the way sent back an ICMP "host unreachable" message.

Four things cause this most often: a firewall REJECT rule, a missing or wrong entry in the routing table, the target host being completely down, or a misconfigured network interface.

Debug process

Step 1 β€” Is the host even reachable?

Start at the IP level before touching anything else:

# ICMP ping
ping -c 4 192.168.1.50

# If ping is blocked, try TCP on a known-open port
nc -zv 192.168.1.50 22
nc -zv 192.168.1.50 80

Ping succeeds but TCP fails? The problem is port-specific β€” skip to Step 3. Both fail? The host is unreachable at the IP level β€” keep reading.

Step 2 β€” Check the routing table

ip route get 192.168.1.50

A healthy output looks like this:

192.168.1.50 via 192.168.1.1 dev eth0 src 192.168.1.100 uid 1000

If you see RTNETLINK answers: Network is unreachable instead, your machine has no route to that subnet. Dump the full table:

ip route show
# or
netstat -rn

Look for a default gateway entry (0.0.0.0/0 or default). Missing one? Add it:

# Temporary default gateway
ip route add default via 192.168.1.1 dev eth0

# Or a specific route to just the target subnet
ip route add 10.0.0.0/24 via 192.168.1.1 dev eth0

Step 3 β€” Check firewall rules on both machines

Nine times out of ten, this is it. On the target server, run:

# iptables
sudo iptables -L -n -v

# nftables (newer distros)
sudo nft list ruleset

# firewalld (CentOS/RHEL)
sudo firewall-cmd --list-all

A REJECT rule β€” not DROP β€” triggers an immediate No route to host on the client. The giveaway in iptables output looks like:

REJECT  tcp  --  0.0.0.0/0  0.0.0.0/0  tcp dpt:22  reject-with icmp-host-prohibited

To open the port:

# iptables: allow SSH
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# firewalld: open permanently
sudo firewall-cmd --permanent --add-port=22/tcp
sudo firewall-cmd --reload

# UFW (Ubuntu)
sudo ufw allow 22/tcp

Step 4 β€” Check if the interface is up

ip link show
ip addr show

An interface showing state DOWN needs to be brought up:

sudo ip link set eth0 up

Also double-check the assigned IP and subnet mask. A wrong prefix β€” say /25 instead of /24 β€” quietly cuts your reachable range in half, making half the local subnet look unreachable.

Step 5 β€” Traceroute to find where it breaks

traceroute 192.168.1.50
# or on older systems
tracert 192.168.1.50

Watch for where hops stop responding. That's your culprit β€” either a broken route or a firewall eating the traffic.

Common fixes

Fix 1 β€” The remote firewall has a REJECT rule

On CentOS/RHEL systems running firewalld (default since RHEL 7), every port is blocked until you explicitly open it. That's the default zone policy:

# Open the port you need
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

# Confirm it's open
sudo firewall-cmd --list-ports

Fix 2 β€” Default gateway vanished after reboot

Minimal installs and freshly reconfigured servers sometimes lose their default route on reboot. The temporary ip route add command won't survive a restart β€” make it permanent:

# Ubuntu/Debian β€” edit netplan
sudo nano /etc/netplan/00-installer-config.yaml
# Add under the interface:
#   routes:
#     - to: default
#       via: 192.168.1.1
sudo netplan apply

# CentOS/RHEL β€” edit ifcfg file
sudo nano /etc/sysconfig/network-scripts/ifcfg-eth0
# Add: GATEWAY=192.168.1.1
sudo systemctl restart NetworkManager

Fix 3 β€” Wrong subnet mask (CIDR mismatch)

An interface configured as 192.168.1.100/25 can only reach hosts in 192.168.1.1–126. Anything from .128 onward looks unreachable, even though it's on the same physical switch. Check your actual prefix:

ip addr show eth0
# inet 192.168.1.100/25 β†’ usable hosts: 192.168.1.1 to 192.168.1.126

Not sure what your CIDR should cover? Plug the IP and prefix into ToolCraft's Subnet Calculator β€” it shows the exact host range, broadcast address, and network address immediately, no signup required.

Fix 4 β€” SELinux blocking the connection

RHEL/CentOS adds another layer. SELinux can silently interfere without surfacing an obvious error. Check the audit log first:

sudo ausearch -m avc -ts recent
sudo sealert -a /var/log/audit/audit.log

If SELinux is blocking the connection, fix the label or policy. Disabling SELinux entirely is tempting but wrong β€” it removes protection across the whole system.

Verify the fix

# Confirm TCP connection works
nc -zv 192.168.1.50 22
# Expected: Connection to 192.168.1.50 22 port [tcp/ssh] succeeded!

# Then retry the original command
ssh user@192.168.1.50
curl -v http://192.168.1.50:8080/health

nc succeeds but your app still fails? Good news: the network is fine. The problem shifted to the application layer β€” wrong credentials, TLS mismatch, or a bad hostname. That's a much narrower problem to solve.

Key takeaways

  • "No route to host" almost always means a REJECT firewall rule or a missing route β€” not a dead host (that shows as a timeout).
  • Check both ends: your local routing table and the remote server's firewall rules.
  • On CentOS/RHEL, firewalld blocks everything by default since RHEL 7. New ports must be explicitly opened with firewall-cmd --permanent.
  • After any reboot or network reconfiguration, run ip route show to confirm the default gateway survived.
  • Use nc -zv host port for quick TCP port checks β€” it's faster than debugging your application first and eliminates network as a variable.

Related Error Notes