AWS EC2 Connection Refused: How to Fix It Fast (2026 Guide)
If you are reading this, chances are you just tried to SSH into your instance or curl an endpoint, and your terminal rudely greeted you with the dreaded Connection refused error.
As developers, we’ve all been there. You spin up a fresh Amazon EC2 instance, try to connect, and suddenly hit a brick wall. If you are searching for aws ec2 connection refused how to fix, you are in the right place.
In this comprehensive troubleshooting guide, we are going to tear down this error from the ground up. We will look at root cause analysis, step-by-step solutions starting from the most common culprits to the absolute edge cases, and provide you with copy-paste-ready commands to get your server back online.
Let’s dive in and get you unblocked.
Understanding “Connection Refused” vs. “Connection Timed Out”
Before we start fixing things, we need to understand what the error actually means. This is the most crucial step in root cause analysis.
When you see Connection timed out, it usually means your network packet reached the EC2 instance, but a firewall (like an AWS Security Group) silently dropped it. The server essentially ignores you.
However, Connection refused is a completely different beast.
A “Connection refused” error means your network packet successfully reached the EC2 instance, but the instance’s Operating System actively rejected it. The server literally sent a packet back saying: “I am here, but I am not listening on the port you are trying to access.”
The standard error messages look like this:
* ssh: connect to host ec2-xx-xx-xx-xx.compute-1.amazonaws.com port 22: Connection refused
* curl: (7) Failed to connect to localhost port 80: Connection refused
Understanding this distinction immediately narrows down our troubleshooting. If the connection is actively refused, we know the AWS network routing is fundamentally working, and we need to focus on what is happening inside the operating system or the hypervisor layer.
Root Cause Analysis: Why Does AWS EC2 Throw This Error?
There are three primary reasons your EC2 instance will actively refuse a connection:
- The Service is Dead or Misconfigured: The daemon you are trying to reach (e.g.,
sshdfor SSH,nginxfor web traffic) has crashed, failed to start on boot, or doesn’t exist on the instance. - The Service is Listening on the Wrong Interface: Your application or SSH daemon is listening strictly on
127.0.0.1(localhost) instead of0.0.0.0(all network interfaces), meaning it will ignore any traffic coming from the outside internet. - Local OS Firewall Interference: The application is running and listening correctly, but a host-level firewall (like
iptables,UFW, orfirewalld) is intercepting the traffic and actively rejecting it.
Now, let’s walk through the step-by-step solutions to fix these exact scenarios, starting with the most common.
Step 1: Verify the Target Service is Actually Running
If you are trying to SSH into the instance and getting refused on Port 22, the sshd service is either dead or misconfigured. If you are trying to reach a web app on Port 80 or 8080, that specific application has crashed.
How to Regain Access When SSH is Refused
If your SSH connection is refused, you cannot just log in to fix it. You have two modern options (up-to-date for 2026) to regain access:
Option A: Use AWS Systems Manager (SSM) Session Manager
If your instance has the SSM Agent installed and an IAM role attached with the AmazonSSMManagedInstanceCore policy, you can bypass SSH entirely.
- Go to the AWS Console > EC2 > Instances.
- Select your instance.
- Click the Connect button at the top right.
- Choose the Session Manager tab and click Connect.
This opens a terminal in your browser, completely bypassing Port 22 and local OS firewalls.
Option B: Use EC2 Instance Connect
If SSM isn’t available, try EC2 Instance Connect. From the same Connect screen in the AWS Console, choose the EC2 Instance Connect tab and connect. This pushes a temporary SSH key to the instance for a short window.
Fixing the SSH Daemon (sshd)
Once you are inside the instance via SSM or Instance Connect, check your SSH service.
Run this command for Ubuntu/Debian:
sudo systemctl status ssh
Run this command for Amazon Linux 2023 / RHEL:
sudo systemctl status sshd
If the status says inactive (dead) or failed, you need to restart it:
sudo systemctl restart sshd
If it fails to start, view the logs to see why:
sudo journalctl -u sshd -e
Common culprit: A syntax error in /etc/ssh/sshd_config. If you recently edited this file and missed a semicolon or tabbed incorrectly, sshd will crash on startup.
Step 2: Check Service Binding (The 127.0.0.1 Trap)
This is the single most common mistake I see junior developers make when deploying web applications to EC2.
You write a Python Flask app, a Node.js Express server, or a React development server. You run it locally and it works perfectly. You deploy it to EC2, open the AWS Security Group to the world, and hit the public IP. Result: Connection refused.
Why? Because by default, many development frameworks bind exclusively to localhost (127.0.0.1) for security reasons.
How to Check What is Listening
Log into your instance and run the ss (Socket Statistics) command or netstat:
sudo ss -tulpn
(Note: ss is the modern replacement for netstat and is pre-installed on Amazon Linux 2023 and modern Ubuntu builds).
Look at the output under the Local Address:Port column.
The Bad Configuration:
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
tcp LISTEN 0 128 127.0.0.1:8080 0.0.0.0:*
If you see 127.0.0.1:8080, your app is only accepting traffic from inside the server itself. External traffic will be actively refused by the OS.
The Good Configuration:
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:*
If you see 0.0.0.0:8080 (or [::]:8080 for IPv6), your app is correctly listening on all network interfaces.
How to Fix the Binding
You need to update your application’s start command to bind to 0.0.0.0.
Node.js (Express / React Dev Server):
// Instead of app.listen(3000)
app.listen(3000, '0.0.0.0', () => {
console.log('Server running on all interfaces');
});
Or via CLI: npm run dev -- --host 0.0.0.0
Python (Flask / FastAPI):
# Flask
flask run --host=0.0.0.0
# Uvicorn (FastAPI)
uvicorn main:app --host 0.0.0.0 --port 8000
Step 3: Investigate OS-Level Firewalls
If the AWS Security Group is open, and your application is running and bound to 0.0.0.0, but you are still getting “Connection refused”, a local OS firewall is the likely culprit.
Host-level firewalls are stateful packet inspectors. If they are configured to block a port, they will often send a TCP RST (Reset) packet back to the client, which your terminal interprets as “Connection refused.”
Check UFW (Ubuntu / Debian)
If you are running Ubuntu 24.04 LTS, Uncomplicated Firewall (UFW) might be enabled by default or accidentally turned on during setup.
Check the status:
sudo ufw status
If it says Status: active and you don’t see your port (e.g., 80, 443, 22) allowed, you need to open it:
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw reload
Check Firewalld (Amazon Linux / RHEL / CentOS)
Amazon Linux 2023 and RHEL distributions typically use firewalld.
Check if it’s running:
sudo firewall-cmd --state
If it returns running, check which ports are explicitly open:
sudo firewall-cmd --list-ports
To open a port (e.g., port 80) permanently:
sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
sudo firewall-cmd --reload
Check IPTables (Legacy / Edge Case)
Sometimes, older Docker installations or legacy security scripts leave residual iptables rules that reject traffic.
To check your active iptables rules:
sudo iptables -L -n -v
Look for REJECT rules targeting your specific port. If you find a blocking rule, you can flush the rules (CAUTION: Only do this if you know what you are doing, as it will drop all custom rules):
sudo iptables -F
Step 4: Resolve Resource Exhaustion (CPU and RAM)
This is an edge case that stumps even experienced developers. Your application and SSH daemon are perfectly configured, but you still get random “Connection refused” errors, especially under heavy load.
The Root Cause: Resource Exhaustion.
When an EC2 instance (especially a t2.micro or t3.nano) runs out of RAM, the Linux Out-Of-Memory (OOM) Killer kicks in.