How to Fix SSH Connection Refused Error: A Complete Troubleshooting Guide
You’ve just brewed your coffee, sat down at your desk, and opened your terminal to deploy a critical hotfix. You type your standard SSH command, hit Enter, and instead of the comforting blink of a remote cursor, you’re greeted with the dreaded message:
ssh: connect to host 203.0.113.50 port 22: Connection refused
If you are searching for exactly how to fix ssh connection refused error, you are in the right place. As a senior developer who has managed hundreds of Linux servers over the years, I can tell you that this error is a rite of passage. It is also incredibly frustrating when you are under pressure.
The “Connection refused” error is the server’s way of telling you, “I hear you knocking at the door, but nobody is home.” Technically speaking, the remote machine received your connection request, but there is no application listening on the target port (usually port 22) to accept it, or a firewall is actively rejecting the connection.
In this comprehensive guide, we are going to perform a deep root cause analysis, walk through step-by-step solutions starting from the most common culprits to the obscure edge cases, and establish preventative measures to ensure you never get locked out of your infrastructure again.
Understanding the Root Cause: Refused vs. Timed Out
Before we start fixing things, it is crucial to understand why this happens. When dealing with SSH issues, you typically encounter two distinct errors:
- Connection timed out: This usually means your traffic is silently dropped by a firewall, or the server is entirely offline/unreachable.
- Connection refused: This means the server is online and reachable, but the TCP handshake is actively rejected.
When you see “Connection refused,” it almost always boils down to one of these three scenarios:
* The SSH daemon (sshd) is not running on the remote server.
* The SSH daemon is running, but it is listening on a non-standard port.
* A local or network firewall is intercepting the request and returning a TCP RST (reset) packet.
With that foundational knowledge, let’s roll up our sleeves and start troubleshooting.
Step 1: Verify the SSH Daemon Status
The most common reason for a refused connection is simply that the SSH service is not running. This frequently happens after an automated server reboot, a failed system update, or a manual misconfiguration.
To check this, you need to access the server. If you are locked out via SSH, you will need to use your cloud provider’s web-based console (e.g., AWS EC2 Serial Console, DigitalOcean Droplet Console, or Google Cloud Shell). If it’s a local machine, plug in a monitor and keyboard.
Once you have terminal access to the server, check the status of the SSH service.
On systemd-based systems (Ubuntu, Debian, CentOS, RHEL)
sudo systemctl status sshd
If the service is inactive or failed, you will see output indicating its state. To start the service and ensure it starts automatically on future reboots, run:
sudo systemctl start sshd
sudo systemctl enable sshd
On older SysVinit systems
While rare in 2026, if you are maintaining legacy systems, the commands will look like this:
sudo service ssh status
sudo service ssh start
Dealing with sshd Startup Failures
Sometimes, sshd refuses to start due to a syntax error in your configuration file. If systemctl status sshd shows a failed state, you can validate your configuration file for syntax errors using this command:
sudo sshd -t
If there is a misconfiguration in /etc/ssh/sshd_config, this command will output the exact line number causing the issue (e.g., a missing quotation mark or an invalid directive). Fix the error, and then start the service.
Step 2: Check the Listening Port
By default, SSH listens on TCP port 22. However, many system administrators change the default port to mitigate automated bot scans and brute-force attacks. If the server is expecting traffic on port 2222, but you are knocking on port 22, the connection will be actively refused.
First, verify what port sshd is actually listening on.
Using the ss command
The modern standard for inspecting network sockets is ss. Run this on the remote server:
sudo ss -tulpn | grep sshd
Look closely at the output. You want to see the Local Address:Port column. If it says 0.0.0.0:22, it’s listening on port 22 across all IPv4 interfaces. If you see something like 0.0.0.0:2222, your server is configured to use port 2222.
Using netstat (Legacy)
If ss isn’t available, you can fall back to netstat:
sudo netstat -tulpn | grep sshd
Fixing the Port Mismatch
If you discover the server is listening on a non-standard port, you have two options. You can update your local SSH command to target the correct port:
ssh -p 2222 username@203.0.113.50
Or, you can change the server back to port 22 (or whatever port you prefer) by editing the configuration file.
sudo nano /etc/ssh/sshd_config
Find the line that says Port 2222 (or whatever the non-standard port is), change it to Port 22, save the file, and restart the daemon:
sudo systemctl restart sshd
Personal Anecdote: I once spent two hours tearing my hair out over a “Connection refused” error on a legacy server, only to realize a junior admin had pushed a configuration management script that silently changed the SSH port to 22222. Running ss -tulpn immediately revealed my blind spot.
Step 3: Diagnose Local and Network Firewalls
If the sshd service is running and listening on the correct port, but you are still getting the “Connection refused” error, a firewall is likely blocking the traffic.
iptables / UFW (Ubuntu/Debian)
If the server uses UFW (Uncomplicated Firewall), check its status:
sudo ufw status
If it is active and port 22 is not listed as allowed, you need to add a rule:
sudo ufw allow 22/tcp
sudo ufw reload
If the system uses raw iptables, you can view the current rules:
sudo iptables -L -n -v
Look for a DROP or REJECT rule targeting port 22. To insert a rule allowing SSH traffic before the reject rule, use:
sudo iptables -I INPUT -p tcp --dport 22 -j ACCEPT
(Note: Remember that iptables changes are ephemeral unless saved using iptables-persistent or a similar mechanism).
Firewalld (CentOS / RHEL / Fedora)
Many enterprise Linux distributions use firewalld. You can check its status and allowed services with:
sudo firewall-cmd --state
sudo firewall-cmd --list-all
If ssh is not listed under services, add it permanently and reload the firewall:
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
Cloud Provider Security Groups
This is a massive gotcha for modern developers. If you are hosting your infrastructure on AWS, Google Cloud, Azure, or DigitalOcean, the Linux OS firewall might be perfectly fine, but a cloud-level firewall (like an AWS Security Group) could be blocking the traffic.
- Log into your cloud provider’s dashboard.
- Navigate to the instance or droplet’s network settings.
- Check the Inbound Rules (or Security Groups).
- Ensure there is a rule allowing TCP traffic on port 22 from your current IP address (or
0.0.0.0/0if you are allowing global access, though IP restriction is safer).
Step 4: Resolve Interface and IP Binding Issues
Sometimes, the SSH daemon is running, and the port is correct, but sshd is listening on the wrong network interface.
Let’s refer back to the output of sudo ss -tulpn | grep sshd.
0.0.0.0:22: The daemon is listening on all available IPv4 interfaces. This is standard.127.0.0.1:22: The daemon is only listening on the local loopback interface. You can SSH into the machine from the machine itself, but external requests will be refused.
If your output shows 127.0.0.1:22, you need to update the ListenAddress directive in your SSH configuration.
Open the config file:
sudo nano /etc/ssh/sshd_config
Look for the ListenAddress lines. It might look like this:
ListenAddress 127.0.0.1
To fix the issue, you can either comment out the line entirely (which defaults to listening on all interfaces, 0.0.0.0) or explicitly set it to the server’s public IP address.
#ListenAddress 0.0.0.0
ListenAddress 203.0.113.50
Save the file and restart the service:
sudo systemctl restart sshd
Step 5: Investigate TCP Wrappers (hosts.allow and hosts.deny)
While largely superseded by modern firewalls, TCP Wrappers are still present on many Linux distributions and can silently refuse SSH connections. TCP Wrappers use two files: /etc/hosts.allow and /etc/hosts.deny.
When an incoming connection is made, the system checks hosts.allow first. If it finds a matching rule, it allows the connection. If not, it checks hosts.deny. If it finds a matching rule there, it blocks the connection.
Check the deny file on your remote server:
cat /etc/hosts.deny
Look for lines involving sshd. You might see something aggressive like:
sshd: ALL
If this rule exists, and there is no corresponding allow rule in /etc/hosts.allow for your specific IP address, your connection will be refused.
The Fix: Modify /etc/hosts.allow to whitelist your IP address, or comment out the sshd: ALL line in /etc/hosts.deny.
To whitelist your IP in /etc/hosts.allow:
sudo nano /etc/hosts.allow
Add a line like this:
sshd: 198.51.100.20
(Replace 198.51.100.20 with your actual local public IP address).
Step 6: Check IPv4 vs IPv6 Mismatches
In the modern internet landscape, many networks prioritize IPv6. However, your server might only have sshd configured to listen on IPv4 interfaces (or vice versa).
If your local machine is trying to connect to an IPv6 address, but the server’s sshd is only