What's Actually Happening

When SSH hangs silently for about 30 seconds before showing "Connection timed out", the server isn't rejecting your connection - it's simply not responding at all. This is fundamentally different from "Connection refused", which happens instantly.

The timeout means packets are being dropped somewhere between your machine and the SSH daemon. No response, no rejection, just silence.

The Error You'll See

bash
$ ssh user@192.168.1.100
# ... 30 seconds of nothing ...
ssh: connect to host 192.168.1.100 port 22: Connection timed out

No password prompt, no banner, no "connection refused". Just a long pause followed by timeout.

Why This Happens

A timeout (as opposed to "connection refused") usually means one of these:

  1. 1.Server firewall is dropping packets - Most common. iptables, UFW, firewalld, or a cloud security group has a DROP rule for port 22
  2. 2.Network routing issue - Your packets aren't reaching the server, or return packets aren't reaching you
  3. 3.Server is completely offline - Not just the SSH service, but the entire machine is down or unreachable

Step 1: Check if the Server is Reachable

First, see if you can ping it:

bash
ping -c 3 192.168.1.100

If ping times out too, the server or network is down. If ping works but SSH doesn't, you know the machine is up but something is specifically blocking port 22.

Step 2: Test if Port 22 is Open

Use netcat to test the port without attempting SSH:

bash
nc -zv 192.168.1.100 22 -w 5

If this times out, port 22 is being filtered. If you get "Connection refused", the port is closed but reachable. If you get "succeeded", the port is open and SSH should work - check if sshd is running.

Step 3: Check iptables on the Server

If you have console or out-of-band access to the server:

```bash # Check current iptables rules sudo iptables -L INPUT -n --line-numbers

# Look specifically for port 22 rules sudo iptables -L INPUT -n | grep 22 ```

You might see something like:

bash
DROP       tcp  --  anywhere             anywhere             tcp dpt:ssh

If there's a DROP rule for port 22 before any ACCEPT rule, that's your problem.

Step 4: Temporarily Allow SSH

If you found a blocking rule, you can insert an ACCEPT rule at the top:

bash
# Insert rule at position 1 to allow SSH
sudo iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT

Now try connecting again. If it works, you've confirmed the firewall was the issue.

Step 5: Make the Rule Permanent

The iptables rule above won't survive a reboot. For Ubuntu/Debian:

```bash # Save iptables rules sudo netfilter-persistent save

# Or for UFW users sudo ufw allow 22/tcp sudo ufw reload ```

For RHEL/CentOS:

```bash # Using firewalld sudo firewall-cmd --permanent --add-service=ssh sudo firewall-cmd --reload

# Or save iptables directly sudo service iptables save ```

Cloud Provider Firewalls

If your server is on AWS, Azure, GCP, or similar, check the security group or network security group:

  1. 1.AWS EC2: Check the security group inbound rules
  2. 2.Azure VM: Check the network security group (NSG)
  3. 3.GCP Compute: Check the VPC firewall rules
  4. 4.DigitalOcean: Check the cloud firewalls

Ensure there's an inbound rule allowing TCP port 22 from your IP address or from 0.0.0.0/0 if you want SSH open to all.

Verify the Fix

Test the connection with verbose output:

bash
ssh -v user@192.168.1.100

You should see:

bash
debug1: Connecting to 192.168.1.100 [192.168.1.100] port 22.
debug1: Connection established.
debug1: Remote protocol version 2.0, remote software version OpenSSH_8.9

"Connection established" means the firewall is no longer blocking you.