netcat (nc) reads and writes raw data over TCP or UDP connections. It’s called the “Swiss army knife” of networking. For server admins, it’s the quickest way to answer “is this port reachable?”, to fake a service while testing a firewall, or to move a file between two servers.

Versions

There are several netcat implementations with slightly different flags:

  • OpenBSD netcat (netcat-openbsd) is the default on Debian and Ubuntu. Used in this guide.
  • Ncat (from nmap) is the default on RHEL-family systems (nmap-ncat). Most examples work, with some flag differences.
  • Traditional netcat is old. Avoid it.
sudo apt install netcat-openbsd     # Debian/Ubuntu
sudo dnf install nmap-ncat          # RHEL family

Test whether a port is open

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

nc -zv db.internal 5432
nc -zv -w 3 example.com 443         # 3-second timeout
nc -zv 203.0.113.10 20-25           # a port range
  • -z — just check, send no data.
  • -v — verbose: say whether it succeeded.
  • -w 3 — timeout in seconds.

Results:

  • succeeded → reachable, and something is listening.
  • Connection refused → reachable, but nothing listens on that port. Check the service and its bind address.
  • timed out → a firewall is dropping packets somewhere, or the host is down.

This is the fastest check when an app says “can’t connect to database”. Test from the app server to the database host and port.

UDP (less reliable, because UDP has no handshake):

nc -zvu 203.0.113.10 51820

Listen on a port (fake a service)

Is the firewall open, before the real service is even installed? Start a listener on the server:

nc -lv 8080            # OpenBSD nc: listen on port 8080
# ncat: ncat -lv 8080

Then from outside, run nc -zv server-ip 8080. If the listener prints a connection, the path through all firewalls works. Stop the listener with Ctrl+C.

Ports below 1024 need root.

Talk to services by hand

HTTP:

printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' | nc example.com 80

This shows raw response headers. For HTTPS, use openssl s_client -connect example.com:443 instead, because nc doesn’t do TLS. See openssl commands.

SMTP, to check whether outbound port 25 is reachable and see the server banner:

nc -v mx.example.com 25
# 220 mx.example.com ESMTP Postfix
QUIT

Redis:

printf 'PING\r\n' | nc -q1 127.0.0.1 6379
# +PONG

Transfer a file between servers

On the receiving server:

nc -l 9000 > backup.tar.gz

On the sending server:

nc -N receiver-ip 9000 < backup.tar.gz

-N closes the connection at end of file (OpenBSD nc). Check integrity afterwards with sha256sum on both sides.

A whole directory, compressed on the fly:

# receiver
nc -l 9000 | tar -xzf -
# sender
tar -czf - /var/www/site | nc -N receiver-ip 9000

This is unencrypted and unauthenticated. Only use it on private networks or tunnels, and close the port afterwards. Over the internet, use rsync or scp over SSH. See rsync and scp.

Simple port scan

nc -zv -w1 203.0.113.10 1-1024 2>&1 | grep succeeded

For anything beyond a quick check, use nmap.

Chat between two machines

# machine A
nc -l 5000
# machine B
nc A-ip 5000

Whatever you type appears on the other side. It’s a fun way to show that a network path works in both directions.

Alternatives when nc isn’t installed

Bash can open TCP connections itself:

timeout 3 bash -c '</dev/tcp/db.internal/5432' && echo open || echo closed

curl -v telnet://host:port also works as a quick connectivity test.

Quick reference

Task Command
Is TCP port open? nc -zv host port
With timeout nc -zv -w 3 host port
UDP check nc -zvu host port
Listen nc -lv port
Raw HTTP printf 'GET / HTTP/1.1\r\nHost: x\r\n\r\n' | nc host 80
Receive file nc -l 9000 > file
Send file nc -N host 9000 < file
No nc available bash -c '</dev/tcp/host/port'

Related: check open ports and tcpdump.

  • Networking
  • Linux
  • Troubleshooting