What the "SSH Connection refused" Error Means
The error ssh: connect to host <IP> port 22: Connection refused is a message from the SSH client indicating that the server actively rejected the attempt to establish a TCP connection on port 22 (or another specified port). Unlike Connection timed out (where packets are simply lost), refused is a direct response from the server's operating system kernel: "the service on this port is not available".
Symptoms:
- The command
ssh user@server_ipfails with theConnection refusederror almost instantly. - The
telnet server_ip 22utility also showsConnection refused. - Pinging (
ping) the server usually succeeds, as the problem is at the transport (TCP) layer, not the network (ICMP) layer.
Common Causes
The error originates on the server side. Primary causes include:
- The SSH service (
sshd) is not running. This is the most frequent cause. The daemon is simply not listening on any ports. - The SSH daemon is only listening on the local interface (
127.0.0.1). The configuration might specifyListenAddress 127.0.0.1, which only allows connections from the server itself. - A firewall is blocking the port. A firewall rule may be set to
REJECT(active refusal) for port 22 from your IP or for all IPs. - Another process is already using port 22. Less commonly, another service (e.g., an old
sshdor a different daemon) has occupied port 22, preventing the newsshdfrom binding to it. - Configuration restrictions in
sshd_config. Directives likeAllowUsers,DenyUsers,AllowGroups,DenyGroups, orMatchblocks can prohibit connections for your user or IP address. This might cause a refusal after the connection is established, but sometimes during the handshake phase. - SELinux/AppArmor issues. Mandatory access control systems can prevent
sshdfrom binding to a network port or accepting connections. - The server is behind NAT/load balancer, and port forwarding is not configured. The client tries to connect to a public IP, but packets never reach the internal server. Instead, the router itself may respond with
RST(reset) orICMP port unreachable.
Method 1: Check and Start the SSH Service
First, ensure the service is running.
- Check the service status:
sudo systemctl status sshd- If the status is
active (running), the service is running; proceed to the next method. - If the status is
inactive (dead)orfailed, the service is not running.
- If the status is
- Start the service:
sudo systemctl start sshd - Enable autostart (so the service starts after reboot):
sudo systemctl enable sshd - Try connecting again. If the error persists, check which port the service is listening on (Method 2).
Method 2: Check Which Port and Interface SSH is Listening On
Find out which ports and network interfaces sshd is listening on.
- Use
ssornetstat:sudo ss -tlnp | grep sshd # or sudo netstat -tlnp | grep sshd
Example output for a correct configuration:tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1234,fd=3)) tcp LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=1234,fd=4))0.0.0.0:22— listens on all IPv4 interfaces.[::]:22— listens on all IPv6 interfaces.127.0.0.1:22— listens only on the local loopback interface. External connections are impossible in this case.
- If it's only listening on
127.0.0.1, fix the configuration:- Open the SSH server configuration file:
sudo nano /etc/ssh/sshd_config- Find the line
#ListenAddress 0.0.0.0(orListenAddress ::). Uncomment it (remove the#) or add it if it's missing. Ensure there is noListenAddress 127.0.0.1line. - Save the file and restart the service:
sudo systemctl restart sshd- Check the
ssoutput again — you should now see0.0.0.0:22and/or[::]:22.
Method 3: Check and Configure the Firewall
A firewall may be blocking incoming connections to port 22.
For ufw (Default on Ubuntu/Debian)
sudo ufw status verbose
- If the status is
Status: active, check if there is a rule for22/tcp(orssh). If not, add it:sudo ufw allow ssh # or explicitly by port sudo ufw allow 22/tcp - If a rule exists but is restricted by IP (
22/tcp ALLOW IN 192.168.1.100), ensure your IP is in the list. - Reload the firewall:
sudo ufw reload.
For firewalld (RHEL/CentOS/Rocky/Fedora)
sudo firewall-cmd --list-all
- In the
services:orports:section,sshor22/tcpshould be listed. - If not, add the rule permanently:
sudo firewall-cmd --permanent --add-service=ssh # or sudo firewall-cmd --permanent --add-port=22/tcp - Apply the changes:
sudo firewall-cmd --reload.
For iptables/nftables (Base Stack)
Check the INPUT chain:
sudo iptables -L INPUT -n -v | grep 22
- Look for a rule with
REJECTorDROPfor port 22. If such a rule exists above anACCEPTrule, it blocks the traffic. - To add an accept rule at the top of the chain:
sudo iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT - Save the rules (otherwise they will be lost after reboot):
- For
iptables:sudo iptables-save | sudo tee /etc/iptables/rules.v4 - For
nftables: ensure the config in/etc/nftables.confis correct and runsudo nft -f /etc/nftables.conf.
- For
Method 4: Check SSH Server Configuration (sshd_config)
Incorrect settings in /etc/ssh/sshd_config can block access.
- Open the configuration file:
sudo nano /etc/ssh/sshd_config - Check key directives:
Port 22— ensure the port is specified correctly (if using a non-standard port, check the firewall and client connection with-p).ListenAddress— if this directive is present, it should be0.0.0.0(for IPv4) or::(for IPv6), not127.0.0.1.PermitRootLogin— if you are trying to connect as root, ensure the value isyesorprohibit-password(if using a key).PasswordAuthentication— if using a password, check that it is set toyes.AllowUsers/AllowGroups— if these directives exist, ensure your user (or group) is listed.DenyUsers/DenyGroups— ensure your user is not listed here.
- After making changes, restart the service:
sudo systemctl restart sshd- Important: Do not close your current active SSH session (if you have one) until you have tested the new configuration! Use
sudo sshd -tto check the file's syntax before restarting.
- Important: Do not close your current active SSH session (if you have one) until you have tested the new configuration! Use
Method 5: Check Network Rules, SELinux/AppArmor, and Load Balancers
Check SELinux (RHEL/CentOS/Rocky)
SELinux can prevent sshd from binding to a port.
sudo ausearch -m avc -ts recent | grep sshd
If there are denial records, try restoring the default context for port 22:
sudo semanage port -a -t ssh_port_t -p tcp 22
(Install policycoreutils-python-utils if semanage is missing).
Check AppArmor (Ubuntu/Debian)
sudo aa-status | grep sshd
If the sshd profile is in enforce mode, try switching it to complain (for diagnostics) or ensure the profile is correct:
sudo aa-complain /etc/apparmor.d/usr.sbin.sshd
sudo systemctl restart sshd
Check Load Balancer/Router
If the server is behind NAT (e.g., in a cloud or data center):
- Ensure that on the router/cloud panel (AWS Security Group, GCP Firewall, Yandex Cloud Security Group, etc.) port 22 (or your custom port) is open for your IP address or range.
- Verify the rule has priority over any "deny all" rules.
- If using a load balancer (ELB, HAProxy), ensure it is configured to pass TCP traffic on port 22 to your backend.
Prevention
- Always enable autostart for critical services:
sudo systemctl enable sshd. - Configure the firewall immediately after server deployment and add the SSH rule before putting it into production.
- Use a non-standard port for SSH (e.g., 2222). This is not a panacea against attacks but reduces the volume of automated scans. Remember to update the firewall and client command (
ssh -p 2222 user@host). - Regularly review your configuration for outdated or conflicting directives (
sshd_config, iptables/nftables rules). - Monitor SSH logs:
sudo journalctl -u sshd -fin real-time orsudo cat /var/log/auth.log(Ubuntu/Debian) /sudo cat /var/log/secure(RHEL) to track connection attempts and errors.
Additional Diagnostics
If none of the methods helped, gather information for further analysis:
sshdlogs:sudo journalctl -u sshd --since "5 min ago" | tail -50
Look for lines withConnection closedorrefused.- Network traffic (if you have console/KVM access to the server):
sudo tcpdump -i any port 22 -nn
Try connecting from the client. If you seeSYNpackets from the client but noSYN-ACKfrom the server — the problem is on the server side (service/firewall). IfSYNpackets don't arrive — the issue is with the network or load balancer. - Check for a conflicting process:
sudo lsof -i :22
Ensure the process issshd. - Check package integrity:
sudo apt update && sudo apt install --reinstall openssh-server # Debian/Ubuntu sudo yum reinstall openssh-server # RHEL/CentOS
Important: After each significant configuration change (firewall, sshd_config), restart the relevant service (sudo systemctl restart sshd or sudo systemctl restart firewalld/ufw) and test the connection from the client. Do not close your working console session until you have confirmed SSH is working.