Linux Error: Connection refused — Cause, Fix, and Troubleshooting Guide
How to fix the Linux 'Connection refused' error (ECONNREFUSED): diagnose closed ports, dead services, wrong bind address and firewalls with ss, curl and nc.
- #linux
- #troubleshooting
- #networking
Summary
Connection refused is the errno ECONNREFUSED (111): the packet reached the target host, but nothing was listening on that port, so the kernel replied with a TCP RST. Crucially the host is reachable — DNS resolved and routing worked — the service is the problem. This makes it fast (an immediate rejection, not a timeout) and distinct from Connection timed out, where packets are silently dropped.
Common Symptoms
curl/nc/ a client library returnsConnection refusedimmediately, with no delay.- The app connects fine to other ports on the same host but not this one.
ping <host>succeeds; only the specific TCP/UDP port is refused.- Works from
localhostbut not from another machine (a bind-address issue).
Most Likely Causes of the ‘Connection refused’ Error
- The service is not running — it crashed, failed to start, or was never started.
- Service bound to
127.0.0.1only — it listens on loopback, so remote clients get refused. - Wrong port — the client targets a port the server does not listen on.
- Service still starting / not yet listening — race on boot or during a deploy.
- Firewall REJECT rule (as opposed to DROP) — an explicit reject returns an RST that looks like refused.
- Proxy/loadbalancer with no healthy backend returning a refusal.
Quick Triage
# Reproduce and confirm it is instant (refused, not timeout)
curl -v http://<host>:<port>/
nc -vz <host> <port>
# Is anything listening on that port locally?
ss -tulpn | grep ':<port>'
# Is the service even up?
systemctl status <service>
Diagnostic Commands
# What is listening, on which address, and which PID (ss; use -tulpn)
ss -tulpn | grep ':<port>'
# RHEL/older hosts without ss:
sudo netstat -tulpn | grep ':<port>'
# Service state and recent crash logs
systemctl status <service>
journalctl -u <service> --since "15 min ago" -n 50
# Probe the port from a client, verbosely
nc -vz <host> <port>
curl -v http://<host>:<port>/
# DNS + routing are fine for 'refused', but confirm you hit the right host
getent hosts <host>
ip route get <host-ip>
# Firewall rules that could REJECT
sudo iptables -S | grep -i reject
sudo nft list ruleset 2>/dev/null | grep -i reject
sudo firewall-cmd --list-all # RHEL/Rocky firewalld
If ss -tulpn shows the service bound to 127.0.0.1:<port>, remote clients will always be refused even though local curl works.
Fix / Remediation
-
Start (or restart) the service:
sudo systemctl start <service> systemctl status <service> ss -tulpn | grep ':<port>' -
Fix the bind address so it listens on all interfaces (or the intended one). Change the app config from
127.0.0.1to0.0.0.0(or the specific IP), e.g. nginxlisten 0.0.0.0:8080;, then restart:sudo systemctl restart <service> ss -tulpn | grep ':<port>' # confirm 0.0.0.0:<port> or the LAN IPWarning: Binding a service to
0.0.0.0exposes it on every interface. Make sure a firewall or security group restricts who can reach it before exposing management or database ports publicly. -
Correct the client’s target port if
ssshows the service on a different port than the client uses. -
Fix a REJECT firewall rule (Ubuntu ufw / RHEL firewalld):
sudo ufw allow <port>/tcp # Ubuntu/Debian sudo firewall-cmd --add-port=<port>/tcp --permanent && sudo firewall-cmd --reload # RHEL/Rocky -
Add startup ordering/health gating if the refusal is a boot race — make dependents wait for the port to be listening.
Validation
ss -tulpn | grep ':<port>' # service listening on the right address
nc -vz <host> <port> # succeeds
curl -sS -o /dev/null -w '%{http_code}\n' http://<host>:<port>/
Prevention
- Health-check the actual listening port (not just the process) and alert when it stops accepting connections.
- Make bind addresses explicit in config and reviewed — loopback-only binds are a common regression.
- Add client-side retries with backoff so brief restarts do not fail requests hard.
- Use systemd
After=/readiness gates so dependents start only once the port is up.
Related Errors
- Connection timed out
- No route to host
- Network is unreachable
- Cannot assign requested address
- Kubernetes: connection refused in cluster
Final Notes
Connection refused means “I reached the host but nobody answered on that port” — an RST, not a drop — so focus on the service, its bind address, and the port, not on routing or DNS. ss -tulpn plus systemctl status resolves the vast majority of cases in under a minute.
Want faster Linux incident response? Use DevOps AI Toolkit to turn production errors into clear diagnostics, remediation steps, and reusable runbooks.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.