How to Test SSH Connection in Linux (Port, Service & Login)

Deepak Prasad
Tested on RHEL 10.2 — openssh-clients-9.9p1-25.el10_2.x86_64, nmap-ncat-7.92-5.el10.x86_64, nmap-7.92-5.el10.x86_64 (commands apply to modern Linux distributions)
Applies to Any Linux or Unix host with OpenSSH client tools and optional nmap / nc
Privilege Normal user for client tests; sudo or console access on the server for sshd checks
Scope Test SSH at three layers — TCP port reachability, SSH service response, and user authentication. Includes client-side and server-side checks plus a layered shell script.
Related guides Generate SSH keys
SSH config
SSH password in scripts
Short on time?Beta Get the gist of this 14-minute read in seconds, then ask follow-up questions

Use this guide when you need to know whether SSH is broken at the network, the service, or the login step — not just whether something answered on port 22.

You will test TCP reachability first, confirm that an SSH server returns host keys, then run a real non-interactive login when keys or automation are already in place. The same order applies whether you are checking a new VM, a bastion before SSH through a jump host (ProxyJump), or your own sshd from the console.


Three layers to test

An SSH connection can fail at three different stages:

  1. Network / port — Can your computer reach the server on TCP port 22 (or your custom SSH port)?
  2. SSH service — Is an SSH server actually responding on that port?
  3. Login — Can your username and authentication method successfully log in?

A successful port test does not mean SSH login works. Each command below checks one layer at a time.

  Layer 1 — TCP port reachable?
           │
           ▼
  Layer 2 — SSH service returns host keys?
           │
           ▼
  Layer 3 — User authenticates and runs a command?

Quick answer: test SSH connection

What you want to test Command What success proves
TCP port reachable nc -vz -w 5 server 22 Your computer opened a TCP connection to that port
SSH server responding ssh-keyscan -T 5 server An SSH service returned server identity keys
SSH authentication ssh -o BatchMode=yes -o ConnectTimeout=5 user@server true SSH accepted the server's identity, authentication succeeded, and the remote command ran
sshd running locally systemctl is-active sshd The sshd service is active on that server
SSH port listening locally ss -lntp | grep ':22' A program on the server has opened port 22 and is waiting for connections
IMPORTANT
An open port does not prove that SSH login works. A firewall may allow port 22 while SSH rejects your key or password, and another service could theoretically be listening on the same port.

1. Test whether SSH port 22 is reachable

Layer 1 answers a network question only: can your client open TCP to the SSH port?

Test port 22 with nc

nc (often Ncat on RHEL) opens a network connection and reports whether it completed.

On the client, probe the default SSH port with a five-second timeout:

bash
nc -vz -w 5 vm1.lab.example 22

Sample output when the port accepts TCP:

output
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to vm1.lab.example:22.
Ncat: 0 bytes sent, 0 bytes received in 0.08 seconds.

The useful flags here are:

  • -z — scan without sending application data
  • -v — print a readable result
  • -w 5 — stop after five seconds

Exit status 0 means your computer successfully opened a network connection to that port. Technically, the TCP handshake completed. It does not mean your username, key, or password is valid.

Test a custom SSH port

When sshd listens on a non-default port, pass that port to nc:

bash
nc -vz -w 5 vm1.lab.example 2222

Use the same port in ssh-keyscan -p and ssh -p later so every layer tests the same listener.

Test SSH port without Netcat

Bash can open /dev/tcp when nc is not installed. /dev/tcp/host/port is a Bash feature that asks Bash to open a TCP connection — it is not a real file on disk. The test still covers TCP only.

Try port 22 with a five-second cap:

bash
timeout 5 bash -c '</dev/tcp/vm1.lab.example/22'

When the connection succeeds, Bash exits silently. Confirm with:

bash
echo $?

Sample result:

output
0

A non-zero exit status usually means the TCP connection did not complete within the timeout. Common causes include:

  • no route or firewall block along the path
  • nothing listening on that port
  • wrong hostname or IP

Do not read exit code 0 as “SSH login works.”

Check port 22 with Nmap

Nmap adds explicit port state labels when you want more than a yes/no TCP probe.

Skip host discovery and scan SSH port 22:

bash
nmap -Pn -p 22 vm1.lab.example

Sample output when the port is open:

output
Starting Nmap 7.92 ( https://nmap.org ) at 2026-09-24 11:33 IST
Nmap scan report for vm1.lab.example (192.168.56.116)
Host is up (0.00046s latency).

PORT   STATE SERVICE
22/tcp open  ssh

Nmap done: 1 IP address (1 host up) scanned in 0.21 seconds

The ssh label beside port 22 is Nmap's normal service name for that port. With nmap -Pn -p 22, that name comes from the registered port assignment — not from service-version detection. This basic scan proves the port is open, not necessarily that the process is OpenSSH. Use ssh-keyscan, an SSH banner, or nmap -sV when you want to identify the service itself.

Read the STATE column carefully:

  • open — something accepted connections on that port
  • closed — the host responded but nothing is listening on that port
  • filtered — Nmap cannot tell whether the port is open or closed because packets were dropped or blocked along the path

filtered is not a promise that “SSH works but a firewall blocks you.” It only means the scanner could not classify the port.

On a port with no listener, Nmap reports closed:

bash
nmap -Pn -p 2223 vm1.lab.example
output
PORT     STATE  SERVICE
2223/tcp closed rockwell-csp2

Install nmap from your distribution repositories when it is not already present (sudo dnf install nmap on RHEL family, sudo apt install nmap on Debian/Ubuntu).


2. Verify that an SSH server is actually responding

A successful TCP connection to port 22 does not prove OpenSSH is on the other end. Layer 2 checks whether an SSH service speaks the protocol.

ssh-keyscan talks to the service using the SSH protocol and asks it to return its server identity keys. If you receive SSH host keys, you have moved beyond a simple open-port test: an SSH service is responding.

Layer 2 still does not prove:

  • your username, password, or key is valid
  • the returned host key belongs to the server you intended to reach

Contact the server and print any keys it offers:

bash
ssh-keyscan -T 5 vm1.lab.example

Sample output:

output
# vm1.lab.example:22 SSH-2.0-OpenSSH_9.9
vm1.lab.example ssh-rsa AAAAB3NzaC1yc2E...
vm1.lab.example ecdsa-sha2-nistp256 AAAAE2VjZHNh...
vm1.lab.example ssh-ed25519 AAAAC3NzaC1lZDI1...

Read the sample output for these signals:

  • SSH host-key lines appeared (the test passed layer 2)
  • the long Base64 strings are the server's public host keys — you do not need to read them manually here
  • the # … SSH-2.0-OpenSSH_9.9 comment line shows the server advertised an SSH version string

For a custom port:

bash
ssh-keyscan -T 5 -p 2222 vm1.lab.example
NOTE
ssh-keyscan discovers host keys; it does not prove those keys are trustworthy. Verify fingerprints out of band before you trust a production server, and do not blindly pipe unknown keys into known_hosts.

3. Test actual SSH authentication

Layer 3 is a real ssh session — the only check that proves your account can log in.

BatchMode=yes disables interactive prompts such as passwords and first-time host-key confirmation. That makes it useful for scripts because the test fails instead of waiting for user input.

Scripts that must supply an account password need sshpass or Expect instead of BatchMode=yes — see pass an SSH password in a script. This connectivity test works best when the server's host key is already trusted and non-interactive authentication — usually an SSH key — is configured. See SSH key authentication for key setup.

Run a harmless remote command with tight timeouts:

bash
ssh -o BatchMode=yes -o ConnectTimeout=5 root@vm1.lab.example true

true is a harmless Linux command that does nothing and exits successfully. We use it here because we only want to prove that SSH can log in and run a command; we do not need an interactive shell.

Check the client exit status:

bash
echo $?

Sample result when login and the remote true succeed:

output
0

That single 0 means all of the following succeeded:

  • the network path to the SSH port
  • SSH accepted the server's identity (host key)
  • your authentication method
  • the remote true command

OpenSSH returns 255 when the SSH connection itself fails. When the remote command exits with another code, ssh forwards that command's status.

When authentication fails after a good network path, you see an error instead of a shell prompt:

bash
ssh -o BatchMode=yes -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new nobody@127.0.0.1 true
output
nobody@127.0.0.1: Permission denied (publickey,password).

OpenSSH reports SSH-layer failures with exit status 255:

bash
echo $?
output
255

Here SSH successfully reached the login stage, but the account could not log in — a layer-3 failure, not a dead port.


4. Check SSH from the server side

When login fails but you can still reach the server outside SSH, check sshd on the server before you keep changing client settings. Direct access might be:

  • a hypervisor or VM console
  • a cloud provider serial or browser console
  • a keyboard and monitor on the physical machine

Administrators often call this console or out-of-band access.

Is sshd running?

systemctl shows whether the unit is active:

bash
systemctl is-active sshd

Sample output on a healthy server:

output
active

For human-readable detail, use status:

bash
systemctl status sshd --no-pager
output
● sshd.service - OpenSSH server daemon
     Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; preset: enabled)
     Active: active (running) since Wed 2026-09-23 17:54:57 IST; 17h ago
   Main PID: 1251 (sshd)

active (running) means the daemon is up. If the unit is inactive or failed, start or fix sshd before retesting from the client.

Which address and port is listening?

ss lists sockets without guessing from config files alone:

bash
ss -lntp | grep sshd

Typical listener lines:

output
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1251,fd=7))
LISTEN 0 128    [::]:22    [::]:* users:(("sshd",pid=1251,fd=8))

0.0.0.0:22 and [::]:22 mean a program on the server has opened port 22 and is waiting for connections on all interfaces. A ListenAddress restriction would show a specific IP instead.

Settings sshd is actually using

Included config snippets can override what you expect from /etc/ssh/sshd_config. Dump the settings sshd is actually using after reading all configuration files:

bash
sshd -T | grep -E '^(port|listenaddress|passwordauthentication|pubkeyauthentication)'

Sample lines:

output
port 22
listenaddress [::]:22
listenaddress 0.0.0.0:22
pubkeyauthentication yes
passwordauthentication yes

Use this when clients reach port 22 but authentication methods do not match what you expect — for example keys disabled while you only have a pubkey. See OpenSSH authentication methods for PasswordAuthentication, PubkeyAuthentication, and related sshd_config options.


5. Test SSH when the host is new

The layer-3 login test above assumes the server's host key is already trusted. On a brand-new host, SSH may stop and ask you to confirm the host key — which BatchMode=yes treats as a failure.

Do not make these options your default:

bash
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null

They disable host-identity checks and belong only in tightly controlled automation where you accept that risk.

For disposable lab hosts, modern OpenSSH supports trust-on-first-use without ignoring future key changes. You can also set StrictHostKeyChecking accept-new in SSH config for a specific host alias:

bash
ssh -o StrictHostKeyChecking=accept-new -o BatchMode=yes -o ConnectTimeout=5 root@vm1.lab.example true

accept-new stores a previously unknown host key automatically but still refuses a host whose stored key changed. For permanent systems, compare the fingerprint from ssh-keyscan or the server console against what ssh shows on first connect, then keep known_hosts under change control.


6. Debug an SSH connection with verbose output

When port 22 is open and ssh-keyscan works but login still fails, verbose client output shows which stage stopped.

Start with -v for readable diagnostic output. If you need more detail, increase it to -vv or -vvv:

bash
ssh -v root@vm1.lab.example

Verbosity levels:

  • -v — basic debug
  • -vv — more detail
  • -vvv — maximum client debug

For a stubborn failure, rerun with the highest level:

bash
ssh -vvv root@vm1.lab.example

Watch the transcript for the failure point along this path:

  TCP connection
       │
       ▼
  SSH version exchange
       │
       ▼
  key exchange
       │
       ▼
  checking that this is the expected SSH server (host-key verification)
       │
       ▼
  user authentication (login)
       │
       ▼
  session / remote command

Common messages map to layers:

Message Usual meaning
Connection refused Nothing is listening on that IP/port
Connection timed out Routing, firewall, or silent drop along the path
No route to host The client cannot reach the destination network or host, or a network device or firewall returned an unreachable response — see fix SSH no route to host for routing and firewall checks
Permission denied (publickey) Network OK and SSH reached the login stage; authentication failed
Host key verification failed SSH rejected the server identity rather than failing network connectivity — see fix invalid SSH host key length when the message mentions key size

StrictHostKeyChecking=accept-new is safer for first connect than StrictHostKeyChecking=no because it still protects you when a stored key changes.

ping can help with basic network diagnosis, but a failed ping does not prove SSH is unreachable — many servers and firewalls block ICMP while SSH on port 22 still works. Your direct TCP tests in layer 1 are the better check for this workflow.


Shell script to test SSH connection

One script can report which layer failed instead of maintaining separate wrappers for nc, Nmap, and Bash.

Save this as test-ssh-layers.sh:

bash
#!/bin/bash

host="$1"
user="$2"
port="${3:-22}"

if [[ -z "$host" || -z "$user" ]]; then
    echo "Usage: $0 <host> <user> [port]"
    exit 2
fi

echo "1. Testing TCP port $port..."

if ! nc -z -w 5 "$host" "$port"; then
    echo "FAIL: TCP port $port is not reachable"
    exit 1
fi

echo "PASS: TCP port is reachable"

echo "2. Testing SSH service..."

if ! ssh-keyscan -T 5 -p "$port" "$host" >/dev/null 2>&1; then
    echo "FAIL: No SSH host key received"
    exit 1
fi

echo "PASS: SSH service responded"

echo "3. Testing SSH authentication..."

if ssh -p "$port" -o BatchMode=yes -o ConnectTimeout=5 "$user@$host" true; then
    echo "PASS: SSH login works"
else
    echo "FAIL: SSH service is reachable but authentication/session failed"
    exit 1
fi

Run it against a host where your key is already trusted:

bash
chmod +x test-ssh-layers.sh
./test-ssh-layers.sh vm1.lab.example root 22

Sample success:

output
1. Testing TCP port 22...
PASS: TCP port is reachable
2. Testing SSH service...
PASS: SSH service responded
3. Testing SSH authentication...
PASS: SSH login works

The script assumes:

  • the server's host key is already trusted in known_hosts; for disposable or new lab hosts you may choose to add StrictHostKeyChecking=accept-new
  • non-interactive authentication is configured
  • nc and ssh-keyscan are installed on the client

SSH connection test: common results

Result Network SSH service Authentication
nc fails Problem Unknown Not tested
nc works, ssh-keyscan fails TCP reachable SSH problem or wrong service Not tested
ssh-keyscan works, Permission denied Working Working Failed
ssh … true returns 0 Working Working Working

Use the table to decide what to fix next:

  • row one (nc fails) — firewall, routing, or wrong IP/port
  • row two (ssh-keyscan fails) — sshd not running, wrong service on the port, or SSH blocked after TCP connects
  • row three (Permission denied) — keys, password, account, or sshd authentication policy

Summary

SSH troubleshooting is faster when you separate TCP reachability, SSH protocol response, and user login. A green nc or /dev/tcp test only proves that your computer opened a network connection to the port you scanned — not that OpenSSH is there or that your account can log in.

ssh-keyscan answers whether an SSH service returned server identity keys without logging in. A real ssh -o BatchMode=yes … true test is the definitive layer-3 check — the same proof you need before automation, scp, or a jump host path.

When login fails and you control the server, check systemctl is-active sshd, listeners with ss -lntp, and the settings sshd is actually using with sshd -T. For new hosts, use accept-new instead of disabling host-key checks. When the failure stage is unclear, ssh -vvv shows whether you are fighting the network, the server identity, or the account.

Work through port → SSH service → login in order and you will not mistake an open port 22 for a working login.


References


Frequently Asked Questions

Does an open port 22 mean SSH works?

No. It proves only that a TCP connection to port 22 completed. Authentication can still fail, or a non-SSH service could be bound to that port.

How do I test SSH without logging into an interactive shell?

Run a harmless remote command such as true:

bash
ssh user@server true

For automation, add -o BatchMode=yes -o ConnectTimeout=5 so the client fails instead of waiting on a password or host-key prompt.

Does ssh -T test SSH connectivity?

Not by itself. -T only disables pseudo-terminal allocation. Success or failure still depends on the normal SSH handshake and authentication.

How do I test an SSH server without knowing a username or password?

Use ssh-keyscan -T 5 server. It confirms that an SSH service responded with host keys but does not test user authentication.

How do I test a non-standard SSH port?

Pass the same port to every tool:

bash
nc -vz server 2222
ssh-keyscan -p 2222 server
ssh -p 2222 user@server true
Finished reading?Beta Get the key takeaways in seconds, then ask follow-up questions
Omer Cakmak

Linux Administrator

Highly skilled at managing Debian, Ubuntu, CentOS, Oracle Linux, and Red Hat servers. Proficient in bash scripting, Ansible, and AWX central server management, he handles server operations on OpenStack, KVM, Proxmox, and VMware.

  • Debian
  • Ubuntu
  • Linux
  • Red Hat Enterprise Linux
  • Shell Script
  • System Administration