← Back to all posts

Connection Refused vs Timed Out: What to Check Next

Interpret a failed TCP connection as evidence about one attempt, then check the listener, route and filtering without guessing the cause.

A yellow network connector paused in front of an empty socket on a blue server

curl fails to reach a service. One attempt reports connection refused; another waits and reports a timeout. Those messages narrow the investigation, but neither names the broken component by itself.

For a TCP connection on Linux, connect(2) describes ECONNREFUSED as finding no listener at the remote address for a stream socket, and ETIMEDOUT as a connection attempt that timed out. A firewall can also actively reject traffic, and a timeout can result from several different missing responses or delays. Record the exact target, port and vantage point before turning either message into a diagnosis.

Reproduce a refusal without changing firewall rules

Use a port you have checked is unused, then ask for a local TCP connection:

curl -v --connect-timeout 3 http://127.0.0.1:18081/

If nothing is listening on 127.0.0.1:18081, the usual result is an immediate refusal. If a process already owns that port, choose another unused port instead. Start a temporary service in one terminal and retry from another:

mkdir -p /tmp/connection-demo
printf 'connection-demo\n' > /tmp/connection-demo/index.html
python3 -m http.server 18081 --bind 127.0.0.1 --directory /tmp/connection-demo
curl -fsS --connect-timeout 3 http://127.0.0.1:18081/

The second request should return connection-demo. Stop the server with Ctrl-C. This is a controlled listener/no-listener comparison, not a recipe for manufacturing a timeout. A timeout exercise requires a known network policy or unreachable path, and blindly picking an Internet address can produce a different error.

Investigate an actual failure in order

  1. Preserve the failing request. Write down the hostname or IP, numeric port, protocol, client machine and time. A request to localhost always refers to the client’s own environment; it may be the wrong machine when the client is a container or remote shell.
  2. Check the destination and listener. On the intended Linux server, ss -ltn shows listening TCP sockets. Compare the local address and port with what the client requested. A service bound only to 127.0.0.1 does not accept a connection to its LAN address. The bind-address experiment isolates this condition.
  3. Check the path from the failing client. On Linux, ip route get SERVER_IP reveals the selected route for an IP destination; the ip-route(8) manual describes what that query returns. Then repeat the connection attempt from the same client. A successful test on the server itself does not verify the remote path.
  4. Check filtering and application response separately. Firewall policy, network isolation and intermediate devices can prevent a connection even with a listener present. If TCP connects but HTTP fails or returns the wrong body, move to the application and its logs rather than continuing to debug port reachability.
Observation from the failing client Supported inference Avoid concluding
Immediate refusal This specific TCP connect attempt was rejected or had no accepting listener The whole server is down
Connect timeout The attempt did not complete before the client’s deadline A firewall is definitely dropping packets
TCP connects, HTTP fails The transport path to a listener worked The application is healthy

If you need another viewpoint, a single-port Nmap TCP connect scan against a system you control can classify what that scanner sees. Treat its open, closed or filtered state as another observation from a named location, not a replacement for the failing client’s request.