When attempting to establish a secure shell session, receiving the error ssh: connect to host 192.0.2.1 port 22: Connection refused means the target server’s operating system actively rejected the TCP SYN packet. Unlike a timeout (which indicates dropped packets along the route or a silent drop firewall), a “Connection refused” error confirms network reachability but signifies that no service is listening on port 22 or an active packet reject rule was encountered.
Quick Answer
If you have console/terminal access (via web VNC or cloud provider rescue console):
# 1. Check if the OpenSSH server daemon is running
sudo systemctl status ssh || sudo systemctl status sshd
# 2. If inactive or stopped, start and enable it
sudo systemctl enable --now ssh || sudo systemctl enable --now sshd
# 3. Verify which port and IP addresses SSH is actually listening on
sudo ss -tulpn | grep sshd
# 4. If listening on a custom port (e.g. 2222), connect specifying the port:
# ssh -p 2222 username@your-server-ip
If you are locked out completely, access your hosting provider’s web console (AWS EC2 Serial Console / Instance Connect, DigitalOcean Droplet Console, Linode Lish, or Proxmox NoVNC) to run these commands directly on the server.
Symptoms
- Terminal returns:
ssh: connect to host <host_ip_or_domain> port 22: Connection refusedimmediately upon execution. - SFTP and SCP connections fail with
Connection closed by remote hostorConnection refused. - Automated deployment tools (Ansible, GitHub Actions, Terraform, Jenkins) fail during the SSH handshake phase.
- Ping/ICMP requests to the server succeed with normal latency, but SSH fails immediately.
- Connecting with verbose mode (
ssh -vvv user@server) stalls right at:debug1: Connecting to 192.0.2.1 [192.0.2.1] port 22. debug1: connect to address 192.0.2.1 port 22: Connection refused ssh: connect to host 192.0.2.1 port 22: Connection refused
Common Causes
| Root Cause | Description | Typical Environment |
|---|---|---|
| SSH Daemon is Inactive/Crashed | The sshd or ssh systemd unit is stopped or failed due to configuration syntax errors or memory exhaustion. | Newly deployed VPS, crashed servers |
| Custom SSH Port Configured | The server was hardened to listen on an alternate port (e.g., 2222, 50222), but the client attempted default port 22. | Production hardened servers |
| Local Firewall Reject Policy | UFW, firewalld, or nftables is configured with a REJECT target instead of ACCEPT or DROP. | Debian/Ubuntu (ufw), RHEL/Rocky (firewalld) |
| Fail2ban or CSF IP Jail | An automated intrusion prevention system banned your client IP after multiple failed login attempts. | Web hosting nodes, public-facing servers |
| OpenSSH Server Not Installed | A minimal OS template (such as minimal Docker images or bare-metal netinst) does not include openssh-server. | Minimal OS installations, containers |
| Cloud Provider Security Groups | Upstream edge firewalls (AWS Security Group, GCP VPC rules, Azure NSG) reject or misroute incoming traffic on port 22. | Cloud environments |
Before You Start
- Verify Server Power State: Check your cloud dashboard to ensure the VM instance is not in an inactive, restarting, or suspended state.
- Confirm Target IP: Ensure you are connecting to the correct public IP or updated DNS record (
dig +short yourdomain.com). - Locate Out-of-Band Console: If you are locked out of SSH, log in to your provider’s control panel (AWS, Hetzner Cloud Console, OVH KVM, Vultr View Console) before performing network changes.
Step-by-Step Diagnostic Procedures
Step 1: Diagnose from the Client Side
Before touching the server, run verbose diagnostics from your local terminal to isolate where the connection drops:
# Test with maximum verbosity
ssh -vvv -p 22 admin@192.0.2.1
Next, test socket availability using nc (Netcat) or nmap:
# Test TCP connection to port 22
nc -zv -w 5 192.0.2.1 22
# Or using nmap to inspect the port state
nmap -p 22 192.0.2.1
Output Interpretation:
Connection refused: The packet reached the host or firewall, but the kernel or firewall sent an immediateTCP RST(Reset) packet. The daemon is either not running or the port is mismatched.Connection timed out: The packet was silently dropped by a network router, AWS Security Group, or a DROP firewall rule.OpenorConnected to 192.0.2.1: Port 22 is reachable; the refusal might be transient or IP-specific.
Step 2: Check SSH Daemon Status on the Server
Connect via your provider’s web console or VNC terminal and check if the OpenSSH server process is active:
# On Ubuntu / Debian:
sudo systemctl status ssh
# On CentOS / RHEL / Rocky Linux / AlmaLinux / Fedora:
sudo systemctl status sshd
Expected Healthy Output:
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2026-09-18 10:14:22 UTC; 4h ago
Main PID: 1248 (sshd)
Tasks: 1 (limit: 4613)
Memory: 6.2M
If the status is inactive (dead) or failed, continue to the safe fixes below.
Step 3: Verify the Listening Port and Bind Address
Verify which port sshd is bound to:
sudo ss -tulpn | grep ssh
Expected Output Analysis:
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1248,fd=3)): Normal. Listening on all IPv4 interfaces on port 22.LISTEN 0 128 127.0.0.1:22 0.0.0.0:*: Problem. SSH is only listening on localhost, unreachable from the external network.LISTEN 0 128 0.0.0.0:2222 0.0.0.0:*: Problem. SSH is listening on custom port2222, not22.- Empty output: SSH daemon is not running at all.
Step 4: Check Local Server Firewall Rules
On Ubuntu / Debian (UFW):
sudo ufw status verbose
If UFW is active and does not list port 22 or OpenSSH as ALLOW IN, incoming traffic will be blocked.
On RHEL / AlmaLinux / CentOS (firewalld):
sudo firewall-cmd --list-all
Ensure services: ssh or the custom port is included under the active zone (e.g., public).
Inspect Raw iptables/nftables:
sudo iptables -L INPUT -v -n --line-numbers | grep -E '22|dpt:22|REJECT|DROP'
Step 5: Check Fail2ban and Security Logs
Check if your workstation’s IP has been jailed by Fail2ban due to past failed authentication attempts:
# Check status of the sshd jail
sudo fail2ban-client status sshd
Review the authentication logs to confirm whether the service received the connection attempt:
# Ubuntu / Debian:
sudo grep -i "sshd" /var/log/auth.log | tail -n 30
# RHEL / CentOS / Rocky Linux:
sudo grep -i "sshd" /var/log/secure | tail -n 30
# Or via journalctl:
sudo journalctl -u ssh -u sshd -n 50 --no-pager
Safe Fixes
Fix 1: Start, Enable, and Test OpenSSH Daemon
If the SSH daemon is inactive or crashed, test the configuration syntax before restarting to prevent silent launch crashes:
# Test configuration syntax for syntax errors
sudo sshd -t
# If no errors are returned, start and enable the service
# For Ubuntu/Debian:
sudo systemctl enable --now ssh
sudo systemctl restart ssh
# For RHEL / CentOS / AlmaLinux:
sudo systemctl enable --now sshd
sudo systemctl restart sshd
Warning: If
sshd -treturns syntax errors (such as invalid directives or missing host keys), fix the flagged lines in/etc/ssh/sshd_configor/etc/ssh/sshd_config.d/*.confbefore restarting.
Fix 2: Correct Listening Port or Bind Interface
If sshd was modified to bind only to localhost or a non-standard port:
-
Open the primary SSH configuration file:
sudo nano /etc/ssh/sshd_config -
Review and adjust these key directives:
# Ensure Port is 22 (or note your chosen custom port) Port 22 # Ensure ListenAddress listens on all interfaces (0.0.0.0 for IPv4, :: for IPv6) ListenAddress 0.0.0.0 ListenAddress :: -
If using modern Ubuntu (22.10+ / 24.04+) with
systemd-socket-activatedSSH, check socket configuration overrides:sudo systemctl status ssh.socket # If systemd manages the socket: sudo systemctl daemon-reload sudo systemctl restart ssh.socket -
Test and restart:
sudo sshd -t && sudo systemctl restart ssh
Fix 3: Open Port 22 in Host Firewalls
Using UFW (Ubuntu / Debian):
# Allow standard SSH
sudo ufw allow 22/tcp comment "OpenSSH"
sudo ufw reload
sudo ufw status
Using Firewalld (CentOS / RHEL / Rocky / AlmaLinux):
# Allow SSH service permanently
sudo firewall-cmd --permanent --add-service=ssh
# If using a custom port, e.g. 2222:
# sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
Using iptables (Direct):
# Insert ACCEPT rule at top of INPUT chain
sudo iptables -I INPUT 1 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
Fix 4: Unban Your Client IP from Fail2ban
If your workstation was banned by Fail2ban:
# Find your current public IP (from your client):
curl -4 https://icanhazip.com
# On the server, check if the IP is in the banned list:
sudo fail2ban-client status sshd
# Unban the IP:
sudo fail2ban-client set sshd unbanip <YOUR_CLIENT_IP>
# (Optional) Whitelist your office/home IP permanently in /etc/fail2ban/jail.local:
# ignoreip = 127.0.0.1/8 ::1 <YOUR_CLIENT_IP>/32
Fix 5: Cloud Provider Inbound Security Rules
If local server settings are correct but connections still fail, check your cloud provider’s network security configuration:
- AWS EC2: Verify the Security Group attached to the instance has an inbound rule:
- Type:
SSH| Protocol:TCP| Port Range:22| Source:My IPor designated VPN CIDR. - Check Network ACLs (NACLs) to ensure inbound and outbound ephemeral ports (1024–65535) are allowed.
- Type:
- DigitalOcean: Navigate to Networking > Firewalls and verify an inbound rule permits TCP port 22.
- Google Cloud (GCP): Check VPC Network > Firewall rules for a rule with
tcp:22targeting your instance tag. - Hetzner / Linode: Inspect cloud firewall profiles applied to the server instance.
Verification
Run these verification tests from your local machine to confirm resolution:
# 1. Test socket handshake
nc -zv -w 3 192.0.2.1 22
# 2. Test SSH banner response
curl -v telnet://192.0.2.1:22
# Expected banner response:
# SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.7
# 3. Establish login session with verbose timing:
ssh -v user@192.0.2.1
Common Mistakes
- Editing
/etc/ssh/sshd_configwithout checking/etc/ssh/sshd_config.d/: On modern Linux distributions (Ubuntu 22.04+, Debian 12+, RHEL 9), modular configuration files in/etc/ssh/sshd_config.d/*.confoverride directives in the main file. - Changing Port without Updating Firewall: Changing
Port 2222insshd_configand restarting before allowing2222/tcpin UFW or AWS Security Groups locks out SSH access immediately. - Disabling SSH without Starting New Session: Always keep an active, open SSH session running in one terminal while testing modifications in another terminal.
- Confusing Connection Refused with Connection Timed Out:
- Connection refused: Packet arrived at the host; port is closed or actively rejected.
- Connection timed out: Packet never reached the host or was dropped without a response.
Prevention Checklist
- Maintain an emergency out-of-band console access method (e.g. AWS EC2 Instance Connect / Hetzner VNC / Proxmox Shell).
- Add your static management IP address or VPN subnet to
ignoreipin/etc/fail2ban/jail.local. - Always validate syntax with
sudo sshd -tprior to executingsystemctl restart sshd. - Enable system monitoring for the
ssh.servicedaemon with automatic service restart policies in systemd (Restart=on-failure). - Document custom SSH ports in your team’s internal infrastructure configuration registry.
Quick Command Reference
| Task | Command |
|---|---|
| Check SSH Status | sudo systemctl status ssh (Ubuntu/Debian) or sshd (RHEL/CentOS) |
| Start & Enable SSH | sudo systemctl enable --now ssh (or sshd) |
| Verify Listening Ports | sudo ss -tulpn | grep ssh |
| Validate SSH Config | sudo sshd -t |
| Allow in UFW | sudo ufw allow 22/tcp && sudo ufw reload |
| Allow in Firewalld | sudo firewall-cmd --permanent --add-service=ssh && sudo firewall-cmd --reload |
| Check Fail2ban Bans | sudo fail2ban-client status sshd |
| Unban Client IP | sudo fail2ban-client set sshd unbanip <IP> |
| Check SSH Journal Logs | sudo journalctl -u ssh -n 30 --no-pager |
Technical FAQs
Why do I get “Connection refused” when Ping works?
Ping uses the ICMP protocol (Echo Request/Echo Reply), which operates at the network layer (OSI Layer 3) and is handled directly by the Linux kernel. SSH operates over TCP on port 22 (OSI Layer 4/Layer 7). A successful ping indicates network reachability, but the “Connection refused” response indicates that no process is accepting connections on TCP port 22 or an active firewall rule responded with a TCP RST.
How do I recover if I locked myself out and changed the SSH port?
Log into your cloud hosting provider’s management console and open the web-based emergency terminal:
- AWS: Use EC2 Serial Console or EC2 Instance Connect.
- DigitalOcean: Use the Recovery Console / Droplet Console.
- Hetzner / Linode / Vultr: Open the web VNC / Lish console.
Once inside, verify
sudo ss -tulpn | grep sshto see the actual port, update your firewall rules, or restore port 22 in/etc/ssh/sshd_config.
Why does Ubuntu 22.10+ / 24.04 say SSH is not running even though connections work?
Ubuntu 22.10 and newer introduced systemd socket activation for OpenSSH (ssh.socket). Instead of sshd running continuously in the background, systemd listens on port 22 and spawns the ssh@.service instance on demand when an incoming connection arrives. Check sudo systemctl status ssh.socket instead of ssh.service.
Can SELinux cause SSH Connection Refused?
Yes. If you change the SSH port to a non-standard port (e.g., 2222) on CentOS, RHEL, Rocky Linux, or Fedora without notifying SELinux, SELinux will prevent sshd from binding to the socket. To fix this, run:
sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo systemctl restart sshd