Table of Contents[Hide][Show]
How to Fix SSH Connection Refused Error on Linux: Step-by-Step+−
- Step 1: The Foundation – Are You Even Knocking on the Right Door?
- Step 2: Server-Side Sleuthing – Is SSH Even Home?
- Step 3: The Configuration Crucible – /etc/ssh/sshd_config
- Step 4: The Wall of Fire – Server Firewalls (The #1 Offender)
- Step 5: The Deeper Layers – SELinux, TCP Wrappers, and Resource Limits
- Step 6: The Network Obscurities – ISP Blocks, NAT, and Gateway Firewalls
- Putting It All Together: Your Diagnostic Checklist
- Common FAQs: Fixing SSH Connection Refused on Linux
There’s a particular, sinking feeling that every Linux user, from the wide-eyed beginner to the grizzled system administrator, knows all too well. You’ve typed ssh username@your.remote.server, you hit Enter with purpose, and instead of the welcoming prompt for a password or the satisfying click of an SSH key, you’re met with that cold, terse, and utterly frustrating message:
ssh: connect to host your.remote.server port 22: Connection refused
It’s a digital door slammed in your face.
A “Connection Refused” error isn’t like a timeout, where the network might be to blame, or a permission denied, where you’ve at least made contact. A refusal is a fundamental rejection at the doorstep. It means your client knocked, the server heard it, and it consciously chose not to answer. It’s a statement of policy, not an accident.
Fixing this isn’t about a single magic command; it’s a systematic investigation, a journey through the layers of a Linux machine’s networking and security posture.
Let’s put on our detective hats and walk through this, step-by-step, from the obvious to the obscure.
How to Fix SSH Connection Refused Error on Linux: Step-by-Step
Step 1: The Foundation – Are You Even Knocking on the Right Door?
Before we dive into server configurations, we must eliminate basic client-side and network issues. This is the “is it plugged in?” phase, and skipping it is the most common mistake.
Verify the Target and Your Path
A simple typo can send your connection into the void. Double-check the hostname or IP address. Use ping to see if the host is alive and reachable at a basic ICMP level. A failed ping points to a network connectivity issue, a firewall between you and the server, or the host being down—problems distinct from SSH’s configuration.
ping -c 4 your.remote.server
No ping? The problem might be upstream of SSH.
The Port Paradox
SSH traditionally lives on port 22. But many system administrators change this to avoid the endless barrage of automated bot attacks scanning for port 22. Are you using the correct port? If the server uses port 2222, you must specify it:
ssh -p 2222 username@your.remote.server
A classic test is to use telnet or netcat to see if any service is listening on that port. If you get an immediate “Connection refused,” it confirms no SSH daemon is listening there.
nc -zv your.remote.server 22
If this fails, the issue is definitively on the server.
The Local Firewall Tango
Don’t forget your own machine! A local firewall (like ufw or firewalld on your client laptop, or a corporate desktop firewall) could be blocking outbound connections on port 22 or your custom SSH port. Check your local firewall rules.
Assuming your knock is correct and the network path is clear, the problem lies within the server itself. This is where the real investigation begins.
Step 2: Server-Side Sleuthing – Is SSH Even Home?
You need console access to the server now. If it’s a virtual machine, use your cloud provider’s “VNC console” or “serial console” feature. If it’s a physical machine in front of you, use the keyboard and monitor.
1. The Daemon Dilemma: Is sshd Running?
The SSH server is a daemon called sshd. If it’s not running, it cannot listen for connections. Check its status with systemd:
sudo systemctl status sshd # Or sometimes on older systems/debian variants: sudo systemctl status ssh
You’re looking for active (running). If it’s inactive (dead) or failed, start it:
sudo systemctl start sshd sudo systemctl enable sshd # To make it start on boot
If it fails to start, the error message from systemctl status is your next crucial clue—often a syntax error in the configuration file.
2. The Listening Test: Is sshd on the Right Port?
A running daemon doesn’t guarantee it’s listening on the network. Use ss or netstat to see all listening sockets.
sudo ss -tlnp | grep ssh # or sudo netstat -tlnp | grep ssh
You should see a line like:LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1234,fd=3))
The critical part is 0.0.0.0:22. This means sshd is listening on all network interfaces on port 22. If it says 127.0.0.1:22, that’s a problem—it’s only listening for local connections from the server itself (localhost). This is a common configuration for security, but it prevents remote access.
Step 3: The Configuration Crucible – /etc/ssh/sshd_config
If the service is running but not listening correctly, or if it’s listening but still refusing your connection, the master key lies in /etc/ssh/sshd_config. A single misconfigured directive here can cause the refusal. Always back up this file before editing.
Let’s examine the usual suspects, using sudo grep -v "^#" /etc/ssh/sshd_config | grep -v "^$" to view the active directives without comments.
The Port Directive
Port 22
This can be changed (e.g., Port 2222). If you change it, you must restart sshd and, crucially, update the server’s firewall (see next step). You can also have multiple Port lines for SSH to listen on multiple ports.
The ListenAddress Bind:
#ListenAddress 0.0.0.0 #ListenAddress ::
By default, these are commented out, meaning sshd listens on all interfaces (IPv4 0.0.0.0 and IPv6 ::). If you uncomment and specify, for example, ListenAddress 192.168.1.100, it will only listen on that specific IP address. If you’re trying to connect to the server’s other IP address, you’ll be refused.
The Host-Based Authentication Tangle
HostbasedAuthentication no IgnoreRhosts yes
These are usually fine at their defaults. Problems arise with rsh-style authentication, which is rarely used today.
The Protocol Statement (A Legacy Issue)
#Protocol 2
Modern systems should use Protocol 2 only. The deprecated Protocol 1 is insecure. If your client is set to only use an old protocol and the server is set to only use Protocol 2, a mismatch can occur.
The Grand Permission Gatekeepers
These are the most common culprits for a “refused” feel, where the connection might technically reach the daemon but is then instantly rejected based on policy.
PermitRootLogin: If set tonoorprohibit-password, and you’re trying to log in asrootdirectly with a password, you’ll be refused. Use a regular user andsudo.AllowUsers,DenyUsers,AllowGroups,DenyGroups: These are explicit allow/deny lists. IfAllowUsers bob aliceis set and you’re trying to log in ascharlie, you will be connection refused. Check these lists meticulously.PasswordAuthentication: If set tonoand you don’t have an SSH key set up correctly, your password-based attempt will be refused.PermitEmptyPasswords: Should always beno.
The MaxStartups Throttle
This limits the number of concurrent unauthenticated connections. If under heavy attack or with many simultaneous connection attempts, you might hit this limit. The default is usually safe.
After any change to /etc/ssh/sshd_config, you must reload or restart the SSH daemon:
sudo systemctl reload sshd # Preferable, as it keeps existing connections alive # or sudo systemctl restart sshd # Force a full restart
Then, immediately check the status (sudo systemctl status sshd) to ensure it restarted successfully. A syntax error will cause it to fail on restart, potentially locking you out if you’re connected via SSH. This is why testing syntax before restarting is wise:
sudo sshd -t
This command checks the config file for syntax errors without making any changes.
Step 4: The Wall of Fire – Server Firewalls (The #1 Offender)
Even a perfectly configured, running sshd can be hidden behind an impenetrable wall: the server’s firewall. This is, in my experience, the single most frequent cause of the “Connection Refused” error after a fresh install or system change.
iptables/nftables
The legacy iptables or its modern successor nftables are the kernel’s built-in firewall. Check the rules:
sudo iptables -L -n # List IPv4 rules sudo ip6tables -L -n # List IPv6 rules # For systems using nft: sudo nft list ruleset
Look for chains like INPUT or inet filter INPUT. You need a rule that allows incoming TCP traffic on your SSH port (e.g., 22). If you see a final rule REJECT all -- anywhere anywhere, ensure your ACCEPT rule for port 22 comes before it.
firewalld
Common on RHEL, CentOS, Fedora, and others. It manages nftables/iptables rules with higher-level concepts like “zones” and “services.”
sudo firewall-cmd --list-all
Check that the ssh service is listed under services: or that your custom port is in ports:. If not, add it:
sudo firewall-cmd --permanent --add-service=ssh # for port 22 # OR for a custom port (e.g., 2222): sudo firewall-cmd --permanent --add-port=2222/tcp sudo firewall-cmd --reload
UFW (Uncomplicated Firewall):
Common on Ubuntu/Debian.
sudo ufw status verbose
Ensure your SSH port is allowed. If not:
sudo ufw allow 22/tcp # or your custom port sudo ufw reload
A crucial test
As a temporary diagnostic measure, you can try disabling the firewall entirely (if safe to do so in your environment).
- For
ufw:sudo ufw disable - For
firewalld:sudo systemctl stop firewalld - For
iptables(caution):sudo iptables -F(this FLUSHES all rules, which is drastic).
Immediately test your SSH connection. If it works, you’ve found the culprit. Re-enable the firewall immediately (sudo ufw enable, sudo systemctl start firewalld) and then work on adding the correct, specific rule.
Step 5: The Deeper Layers – SELinux, TCP Wrappers, and Resource Limits
If SSH is running, configured, and the firewall is open, but you’re still refused, we must look at the deeper security and system layers.
SELinux/AppArmor
These are Mandatory Access Control (MAC) systems that enforce policies beyond standard permissions.
SELinux (RHEL/CentOS/Fedora)
It can prevent sshd from binding to non-standard ports. If you’re using a port like 2222, you must tell SELinux:
bash sudo semanage port -a -t ssh_port_t -p tcp 2222
Check for denials in the audit log:
sudo ausearch -m avc -ts recent
AppArmor (Ubuntu/SUSE)
Less likely to interfere with SSH, but check its status with sudo aa-status.
TCP Wrappers (A Legacy System)
The ancient /etc/hosts.allow and /etc/hosts.deny files can still affect services compiled with libwrap support. Check if SSH (sshd) is being denied here. A simple test is to temporarily add:
# In /etc/hosts.allow sshd: ALL
Resource Limits
In extreme cases, the server might be out of resources. Check dmesg and /var/log/syslog or /var/log/messages for kernel messages about “too many open files” or “out of memory.” The sshd process itself has file descriptor limits. Check with cat /proc/$(pidof sshd)/limits.
Step 6: The Network Obscurities – ISP Blocks, NAT, and Gateway Firewalls
For servers behind a home router or in a complex corporate/cloud environment:
- NAT/Port Forwarding: If your server is behind a home router (like a Raspberry Pi on your LAN), you must set up port forwarding on your router. It must forward external WAN traffic on port 22 to the internal IP address of your Linux server.
- Security Groups (Cloud): On AWS, Google Cloud, Azure, etc., the cloud firewall is called a Security Group or Firewall Rule. This is separate from the OS firewall. You must add an inbound rule to the instance’s security group allowing TCP traffic on your SSH port from your IP address (or
0.0.0.0/0for anywhere, though this is insecure). - ISP Blocks: Some residential ISPs block incoming connections on common server ports like 22, 80, and 25. You might need to use a non-standard port (like 2222 or 443) to circumvent this.
Putting It All Together: Your Diagnostic Checklist
Next time you face the dreaded refusal, run through this mental flow:
- Client Check: Correct host/port? Can I
ping? Is my local firewall blocking me? - Server Daemon Status: Can I get to the console? Is
sshdactive (running)? - Server Listening: Does
ss -tlnp | grep sshshow it’s listening on0.0.0.0:22(or your port)? - Server Firewall: Is
ufw,firewalld, oriptablesblocking the port? (Check this first after a fresh install!). - SSH Configuration: Are
AllowUsers,PermitRootLogin, orPasswordAuthenticationsettings rejecting me? Did I restartsshdafter changes? - Deep Security: Are SELinux/AppArmor or TCP Wrappers interfering? (Especially for custom ports).
- Network Path: Is there port forwarding (for home labs) or a cloud Security Group rule (for VPS) in place?
The “SSH Connection Refused” error is not a bug; it’s a feature.
It’s your system telling you, in no uncertain terms, that its security posture does not permit this specific access attempt.
By methodically checking each layer—from your own command line to the kernel’s netfilter rules—you transform a moment of frustration into a masterclass in understanding how Linux secures itself.
You’re not just fixing an error; you’re learning the pathways and gatekeepers of a secure system. So the next time you see that refusal, smile. The game is afoot, and you now have the map to win it.
For more help, you can visit official Ubuntu documntation.
Common FAQs: Fixing SSH Connection Refused on Linux
Got lingering questions after troubleshooting? These cover the most frequent headaches I’ve seen in forums, client tickets, and my own late-night fixes.
What causes “SSH connection refused” on Linux?
This error usually means your system is actively rejecting the connection. The most common reason is that nothing is listening on port 22 (or your custom SSH port), or a firewall is blocking the request.
Typical causes include:
- The sshd service is stopped or not installed
- Firewall rules (UFW or firewalld) don’t allow SSH
- SSH is configured to listen only on localhost
- Incorrect IP address or port
- Cloud security groups or network ACLs blocking access
In short, the server is reachable—but SSH itself isn’t.
How do I check if SSH service is running?
Start by checking the SSH daemon status:
sudo systemctl status sshd
On Ubuntu/Debian systems, the service name may be ssh instead:
sudo systemctl status ssh
If it’s not running, start and enable it:
sudo systemctl start sshd
sudo systemctl enable sshd
To confirm SSH is actually listening on the port:
sudo ss -tulnp | grep :22
No output usually means SSH isn’t bound to the port.
Why is my firewall blocking SSH connections?
On Ubuntu, UFW is often enabled without allowing SSH traffic. Check its status:
sudo ufw status verbose
If SSH isn’t listed, allow it:
sudo ufw allow ssh
sudo ufw reload
On RHEL, CentOS, or Fedora systems using firewalld:
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
Always verify SSH access before enabling a firewall—especially on remote servers.
SSH works locally but not remotely. What’s wrong?
This usually points to a misconfigured ListenAddress in the SSH config file.
Open:
sudo nano /etc/ssh/sshd_config
If you see:
ListenAddress 127.0.0.1
SSH is restricted to local connections only. Change it to:
ListenAddress 0.0.0.0
Test the configuration:
sudo sshd -t
Then restart SSH:
sudo systemctl restart sshd
Also, ping the server’s IP from your local machine to rule out basic network issues.
Can SELinux or AppArmor cause “connection refused”?
Yes—especially on RHEL, CentOS, and Fedora systems with SELinux enabled.
Check SELinux mode:
sudo getenforce
If it’s Enforcing, inspect recent SSH denials:
sudo ausearch -m avc -ts recent | grep sshd
Common fixes include enabling required SELinux booleans:
sudo setsebool -P sshd_can_read_home_dirs 1
For custom SSH ports:
sudo semanage port -a -t ssh_port_t -p tcp 2222
AppArmor can cause similar issues on Ubuntu, though it’s less common.
How do I check SSH error logs for clues?
Logs are often the fastest way to identify what’s going wrong.
For systemd-based systems:
journalctl -u sshd -f
On Debian/Ubuntu:
sudo tail -f /var/log/auth.log
On RHEL/CentOS/Fedora:
sudo tail -f /var/log/secure
Search for errors like:
bind: Address already in useMaxStartups exceededPermission denied
These messages usually point directly to the root cause.
How do I fix SSH when using a custom port (like 2222)?
First, connect using the correct port:
ssh -p 2222 user@server_ip
On the server, verify the SSH configuration:
sudo nano /etc/ssh/sshd_config
Ensure this line exists and is uncommented:
Port 2222
Update firewall rules:
sudo ufw allow 2222/tcp
Restart SSH:
sudo systemctl restart sshd
To confirm the port is open:
telnet server_ip 2222
Is Fail2Ban blocking my own IP?
It happens more often than people admit.
Check Fail2Ban status:
sudo fail2ban-client status sshd
If your IP is banned, unban it:
sudo fail2ban-client set sshd unbanip your.ip.address
To prevent future lockouts, whitelist your IP in:
/etc/fail2ban/jail.local
Under [sshd]:
ignoreip = 127.0.0.1/8 your.ip.address
SSH stopped working after reboot. Why?
This usually means SSH failed to start during boot due to a configuration error.
Validate the config file:
sudo sshd -t
If no errors appear, ensure SSH is enabled:
sudo systemctl enable sshd
Review boot-time logs:
journalctl -b -u sshd
Misconfigured ports, permissions, or missing host keys are common culprits.
How do I handle SSH issues in Docker or containers?
SSH inside containers is rarely recommended.
If you must expose SSH:
- Use port mapping:
-p 2222:22 - Ensure
openssh-serveris installed inside the container
Better alternatives:
- Use
docker execfor shell access - For Kubernetes, use
kubectl execorkubectl port-forward
These approaches are safer, simpler, and more in line with container best practices.

IngressNightmare: Critical Kubernetes Ingress-NGINX Vulnerabilities Exposed in 2025