nc

Updated

September 4, 2026

Overview

nc (netcat) is a Swiss-army TCP/UDP tool: open connections, listen for inbound sockets, scan ports simply, and pipe data across the network. Ubuntu typically ships OpenBSD netcat as nc / netcat (openbsd-netcat package family; classic netcat-traditional may also be available). Flag details differ slightly between implementations — check nc -h on your host.

Syntax

nc [options] host port
nc -l [options] port
command | nc host port
nc host port < file

Common Options (OpenBSD nc on Ubuntu)

Option Description
-l Listen mode
-p port Local port (with -l, often just nc -l port)
-u UDP
-v Verbose
-z Scan mode: no data, just connect
-w secs Connect/idle timeout
-n Numeric only (no DNS)
-k Keep listening after client disconnect (where supported)
-s addr Source address
-q secs Quit after EOF on stdin after delay
-4 / -6 IPv4 / IPv6 only

Safety

  • Listening services with nc -l bind whatever you tell them — do not expose on public interfaces unless intended; combine with firewall rules.
  • “Shell over netcat” patterns are classic attack/persistence techniques. Use only on systems you own, with authorization, for legitimate recovery labs.
  • -z port scans against machines you do not operate may violate policy.

Examples with Explanations

Test if a TCP port is open

nc -vz example.com 443
nc -vz -w 3 10.0.0.10 22

Verbose zero-I/O connect is the operator’s quick “is something listening?” check.

HTTP GET by hand

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

Useful when debugging virtual hosts or seeing raw headers without curl.

TLS is not built into classic nc

# Prefer:
openssl s_client -connect example.com:443 -servername example.com
# or curl -v https://...

Plain nc speaks TCP bytes; it does not negotiate TLS for you.

Simple file transfer (lab / trusted LAN)

Receiver:

nc -l 9000 > received.tgz

Sender:

nc -w 3 receiver.example.com 9000 < payload.tgz

Prefer scp/rsync for anything real (auth, encryption, integrity).

Listen and show inbound banner/data

nc -lvk 9000

Connect from another host: nc host 9000 and type lines.

UDP probe

nc -u -vz -w 2 10.0.0.10 53

UDP “success” is weaker than TCP — lack of ICMP unreachable may still print as open/filtered depending on version.

Port range scan (light)

nc -vz 10.0.0.10 20-25

For serious inventory use nmap; nc is fine for a handful of ports.

Pipe program output to a remote listener

# listener:
nc -l 7000 | tar xzf -
# sender:
tar czf - ./project | nc -w 3 host 7000

Bind to a specific local address

nc -l -s 127.0.0.1 8080

Localhost-only listeners reduce accidental exposure.

Chatty timeout for scripts

if nc -z -w 2 db.internal 5432; then
  echo db-port-open
else
  echo db-port-closed
fi

Understanding Output

  • Connect success (OpenBSD nc): often Connection to host port [tcp/*] succeeded! with -v/-z.
  • Failure: connection refused (nothing listening / RST), timed out (filtered or blackholed), name resolution errors.
  • In connected mode, stdin goes to the socket and socket data goes to stdout — making nc a network pipe.

Notes & Pitfalls

  • Implementation flags differ. Scripts written for netcat-traditional (-e exec) will not match OpenBSD nc. On Ubuntu, update-alternatives or package choice can change behavior — verify with nc -h and readlink -f $(command -v nc).
  • Exit codes for -z are useful in bash if nc -z ...; then but confirm on your variant.
  • Listening without -k usually exits after one client (OpenBSD). Plan for that in demos.
  • IPv6 addresses need careful syntax; prefer -6 and explicit addresses when debugging dual-stack.
  • For HTTP(S) health checks, curl -fsS -o /dev/null -w '%{http_code}\n' is usually better than raw nc.

Additional Resources

  • man nc
  • man ncat (Nmap’s netcat, if installed as separate tool)