What Does a "Connection Refused" Error Mean
The Connection Refused error (code ECONNREFUSED) occurs when a client (e.g., curl, telnet, a browser) attempts to establish a TCP connection with a server, but the server actively rejects the request. This happens if there is no process listening for incoming connections on the specified port, or if a firewall is configured to block it. Typical messages:
curl: (7) Failed to connect to example.com port 80: Connection refused
telnet: Unable to connect to remote host: Connection refused
ssh: connect to host 192.168.1.1 port 22: Connection refused
Unlike Connection timed out, in this case, the host is reachable, but the port is "closed" from the perspective of the TCP stack.
Common Causes
The Connection Refused error is usually caused by one of the following:
- Service is not running — the target program (e.g., web server, SSH daemon) is not active.
- Service is listening on a different port or interface — the service configuration binds only to
127.0.0.1(localhost), while the client connects from an external IP. - Firewall is blocking the port —
iptables,nftables,ufw, orfirewalldrules prohibit incoming connections on the port. - Port is already in use by another process — another service is using the same port, preventing the new one from binding to it.
- Errors in configuration files — incorrect parameters in service files (e.g.,
nginx.conf,sshd_config). - SELinux or AppArmor restrictions — security policies prohibit the service from listening on the port or accepting connections.
- Kernel network settings — for example,
net.ipv4.ip_forwardis disabled when routing is required.
Troubleshooting Steps
Step 1: Check and Start the Service
Begin by verifying if the required service is running. For example, for an Apache web server:
systemctl status apache2 # For Ubuntu/Debian
systemctl status httpd # For CentOS/RHEL
If the service is inactive, start it:
sudo systemctl start apache2
To enable the service to start automatically on boot:
sudo systemctl enable apache2
⚠️ Important: Replace
apache2with your service's name (e.g.,nginx,sshd,postgresql).
Step 2: Check Which Port and Interface the Service is Listening On
Sometimes the service is running but only listens on 127.0.0.1, not on all interfaces (0.0.0.0). Check using ss:
sudo ss -tuln | grep :<port>
For example, for port 80:
sudo ss -tuln | grep :80
The output should show LISTEN and an address. If it shows 127.0.0.1:80 or ::1:80, the service is only available locally. Modify the service configuration to listen on 0.0.0.0:<port> or a specific external IP.
For Nginx, check /etc/nginx/sites-enabled/default or /etc/nginx/nginx.conf:
listen 80 default_server;
listen [::]:80 default_server;
# Ensure there is no "listen 127.0.0.1:80"
After making changes, restart the service:
sudo systemctl restart nginx
Step 3: Configure the Firewall
A firewall may be blocking incoming connections. Check its status:
For ufw (Ubuntu/Debian):
sudo ufw status verbose
If the port is closed, allow it:
sudo ufw allow <port>/tcp
For firewalld (CentOS/RHEL/Fedora):
sudo firewall-cmd --list-all
Add the port:
sudo firewall-cmd --add-port=<port>/tcp --permanent
sudo firewall-cmd --reload
For iptables (universal):
sudo iptables -L -n -v | grep <port>
If there is a DROP rule, delete or modify it:
sudo iptables -D INPUT -p tcp --dport <port> -j DROP
To save rules after a reboot, use iptables-persistent or nftables.
Step 4: Check if the Port is Already in Use
If the port is already occupied, a new service cannot bind to it, and clients will receive a Connection Refused. Find the process:
sudo lsof -i :<port>
or
sudo ss -tulpn | grep :<port>
Example output:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 1234 root 6u IPv4 123456 0t0 TCP *:http (LISTEN)
If the process is not yours, stop it or change your service's port.
Step 5: Check SELinux/AppArmor
On distributions with SELinux (CentOS, RHEL, Fedora), policies may block access. Check the logs:
sudo ausearch -m avc -ts recent
If there are entries related to the port, adjust the policy. For a quick test, temporarily disable SELinux (not for production!):
sudo setenforce 0
If the problem disappears, you need to create a proper SELinux module.
For AppArmor (Ubuntu, Debian), check the profiles:
sudo aa-status
If the service is in enforce mode, try switching it to complain mode for testing:
sudo aa-complain /etc/apparmor.d/usr.sbin.<service>
Prevention
To avoid Connection Refused errors in the future:
- Regularly check the status of critical services using
systemctl is-active <service>or monitoring systems (Zabbix, Prometheus). - Configure interface binding correctly — use
0.0.0.0for public services unless restriction is required. - Audit firewall rules after network changes. Use
ufw status numberedoriptables-savefor backups. - Maintain configuration logs — track changes in service files (e.g., via Git).
- Test changes in an isolated environment before applying them to production.
- Keep systems and packages updated — older versions may contain bugs in the network stack.