Bitdoze Logo

How to Check Remote Ports Using the nc Command in Linux

Learn how to check if remote ports are open using the nc (netcat) command in Linux. Covers TCP/UDP testing, port ranges, timeouts, and scripting patterns.

DragosDragos10 min read
How to Check Remote Ports Using the nc Command in Linux

Need to know if a port is open on a remote server? The nc (netcat) command is the fastest way to find out. One command, instant answer. No browser, no GUI, no heavy tools required.

This guide covers how to check remote ports with nc on Linux, including TCP and UDP testing, port ranges, timeouts for scripts, and common gotchas across different netcat implementations.

Related guides:

What is nc (netcat)?

nc is a command-line utility that reads and writes data across network connections using TCP or UDP. People call it the “Swiss army knife” of networking because it can do a lot: port scanning, file transfers, banner grabbing, and acting as a simple client or server.

The original netcat was written by Hobbit in 1995. Since then, several implementations have appeared, and they behave differently:

Implementation Default on Package name Notes
netcat-openbsd Debian, Ubuntu netcat-openbsd Supports -z, IPv6, proxies
ncat (from Nmap) CentOS, RHEL, Fedora nmap-ncat Supports -z (since nmap 7.25), SSL
netcat-traditional (legacy) netcat-traditional Older, fewer features

Most examples in this guide work with all three, but if something behaves unexpectedly, check which version you’re running:

nc -h 2>&1 | head -1
# or
which nc && ls -l $(which nc)

Install nc on Linux

nc might already be installed. If not:

Debian / Ubuntu:

sudo apt install netcat-openbsd

Note: On Ubuntu 24.04+, netcat is a virtual package. Installing netcat-openbsd explicitly is the cleanest approach.

CentOS / RHEL / Fedora:

sudo dnf install nmap-ncat

Arch Linux:

sudo pacman -S openbsd-netcat

macOS:

nc comes preinstalled (BSD netcat). It works for basic port checking.

Check if a single TCP port is open

The basic syntax for checking a remote port:

nc -zv <host> <port>

Flags explained:

  • -z: scan only, don’t send any data after connecting
  • -v: verbose output (shows success/failure messages)

Example: check if SMTP is reachable on Gmail:

nc -zv smtp.gmail.com 587
Connection to smtp.gmail.com port 587 [tcp/submission] succeeded!

Example: check a port that’s closed:

nc -zv smtp.gmail.com 5555
nc: connectx to smtp.gmail.com port 5555 (tcp) failed: Connection refused

Example: check SSH on your VPS:

nc -zv 192.168.1.100 22
Connection to 192.168.1.100 port 22 [tcp/ssh] succeeded!

Reading the output

nc gives you three possible outcomes:

Output Meaning
Connection to <host> <port> port [tcp/*] succeeded! Port is open, service is listening
Connection refused Port is closed or nothing is listening
Operation timed out Firewall is dropping packets, or host is unreachable

“Connection refused” and “timed out” are different problems. Refused means the server actively rejected the connection (port closed). Timed out means you never got a response at all (firewall blocking, wrong IP, or network issue). This distinction matters when troubleshooting.

Check a range of ports

You can scan multiple ports in one command using a hyphen:

nc -zv <host> <start>-<end>

Example: scan ports 585 through 590:

nc -zv smtp.gmail.com 585-590
nc: connectx to smtp.gmail.com port 585 (tcp) failed: Connection refused
nc: connectx to smtp.gmail.com port 586 (tcp) failed: Connection refused
Connection to smtp.gmail.com port 587 [tcp/submission] succeeded!
nc: connectx to smtp.gmail.com port 588 (tcp) failed: Connection refused
nc: connectx to smtp.gmail.com port 589 (tcp) failed: Connection refused
nc: connectx to smtp.gmail.com port 590 (tcp) failed: Connection refused

Filter for only open ports:

nc -zv smtp.gmail.com 585-590 2>&1 | grep succeeded
Connection to smtp.gmail.com port 587 [tcp/submission] succeeded!

This is useful when scanning a bunch of ports and you only care about the ones that are open.

Set a connection timeout with -w

By default, nc waits a long time before giving up on a connection attempt. For scripts and automation, you almost always want to set a timeout:

nc -zv -w 3 <host> <port>

The -w 3 flag tells nc to give up after 3 seconds if the connection hasn’t been established. Without it, a blocked port can hang for 30+ seconds (the OS TCP timeout).

Skip DNS resolution with -n:

If you’re passing an IP address, add -n to skip DNS lookups. This speeds up scans significantly:

nc -zvn -w 3 192.168.1.100 22

Check UDP ports

Use the -u flag to test UDP ports:

nc -zuv <host> <port>

Example: check DNS (UDP port 53):

nc -zuv 8.8.8.8 53

Important caveat: UDP is connectionless. Unlike TCP, there’s no handshake, so nc sends a packet and has no way to confirm it arrived. You might see “succeeded” even if nothing is listening, or you might see no output at all.

For reliable UDP testing, combine nc with tcpdump on the target machine, or use protocol-specific tools like dig for DNS or iperf3 for throughput.

Use nc in scripts

A common pattern is waiting for a service to become available before running something else. This comes up in Docker Compose setups, CI/CD pipelines, and deployment scripts:

#!/bin/bash
HOST=db.example.com
PORT=5432

echo "Waiting for $HOST:$PORT..."
until nc -z -w 2 "$HOST" "$PORT" 2>/dev/null; do
  sleep 1
done
echo "Port $PORT is open. Continuing..."

This loop checks the port every second until it’s reachable, then proceeds. The 2>/dev/null suppresses the verbose output so your logs stay clean.

Check multiple ports in a loop:

for port in 80 443 8080; do
  if nc -z -w 2 example.com "$port" 2>/dev/null; then
    echo "Port $port: OPEN"
  else
    echo "Port $port: CLOSED"
  fi
done

Beyond port checking, nc can grab service banners, the text a server sends when you first connect. This tells you what software and version is running:

nc -v smtp.gmail.com 25
220 smtp.gmail.com ESMTP ...

Similarly for HTTP:

printf "HEAD / HTTP/1.1\r\nHost: example.com\r\n\r\n" | nc example.com 80

This sends a minimal HTTP request and shows you the raw response headers. Useful for debugging web servers, reverse proxies, or load balancers without curl’s overhead.

Troubleshooting

Problem Likely cause What to try
Connection refused Port closed, no service listening Verify service is running on the target (ss -tlnp on the target host)
Operation timed out Firewall dropping packets, wrong IP ping the host first, check firewall rules (iptables -L, ufw status)
No route to host Network routing issue Check subnet, gateway, VPN connectivity
nc -z says “invalid option” Old ncat version without -z support Update nmap-ncat or use nc --send-only </dev/null <host> <port> as a workaround
Output is silent Connection succeeded but no banner The service doesn’t send a greeting. Use -v to confirm connection status
UDP shows “succeeded” but service isn’t responding UDP is connectionless Use tcpdump or protocol-specific tools to verify

nc vs other port-checking tools

nc isn’t the only way to check ports. Here’s how it compares:

Tool Best for Installed by default? Notes
nc Quick single-port checks, scripts Often yes Lightweight, fast, no dependencies
nmap Scanning many ports, service detection No Overkill for a single port check
curl Testing HTTP/HTTPS endpoints Usually yes Only works for web protocols
telnet Interactive TCP testing Being phased out No UDP support, no -z equivalent
ss / netstat Checking local listening ports Yes Only works for ports on the machine you’re on

For checking a remote port from the command line, nc hits the sweet spot: it’s fast, works for both TCP and UDP, and is available on almost every Linux system.

Conclusion

The nc command is the quickest way to check if a remote port is reachable from a Linux terminal. The core command is nc -zv <host> <port>. Add -w for timeouts in scripts and -u for UDP testing.

Just remember: different Linux distros ship different netcat implementations, and they don’t all support the same flags. If nc -zv behaves strangely, check which version you’re running. On modern systems (Ubuntu 22.04+, RHEL 8+, Fedora), the -z flag works out of the box with the default netcat package.