netcat — The Swiss Army Knife of Networking
netcat (nc) is the most flexible network tool ever made. It reads and writes TCP and UDP. That’s it. From that simplicity comes endless utility — testing ports, debugging protocols, transferring files, running quick servers, pulling banners. Every networking person knows it.
Test if a port is open
# Verbose, just check port
nc -zv example.com 443
# Connection to example.com 443 port [tcp/https] succeeded!
# Multiple ports at once
nc -zv example.com 22 80 443
# UDP (less reliable, no real handshake)
nc -zuv example.com 53
This replaces awkward telnet probes and is faster than nmap for “just check this one port.”
Grab a service banner
nc example.com 80 <<< "HEAD / HTTP/1.0"
# HTTP/1.1 200 OK
# Server: nginx/1.18.0
# ...
nc smtp.gmail.com 25
# 220 smtp.gmail.com ESMTP ...
# (then you can manually issue SMTP commands)
nc example.com 22
# SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4
# Tells you exactly what SSH version is running
Quick file transfer
# On receiver
nc -l 9999 > received_file.tar.gz
# On sender
cat file.tar.gz | nc receiver-ip 9999
# With progress bar (using pv)
pv file.tar.gz | nc receiver-ip 9999
Perfect for one-off transfers when SCP isn’t available or fast enough.
Spin up a quick HTTP server
# Reply with a fixed page
while true; do
echo -e "HTTP/1.1 200 OKrnContent-Length: 13rnrnHello, world!" | nc -l 8000
done
# Test with curl from another shell
curl http://localhost:8000
Listen mode (-l) — receive connections
# Listen on TCP 9000, print whatever comes in
nc -l 9000
# UDP listen
nc -lu 9000
# Allow multiple connections (-k keeps it open after first connection closes)
nc -lk 9000
Chat between two machines
# On server
nc -l 5555
# On client
nc server-ip 5555
# Whatever each types appears on the other
Test UDP services
# DNS query (very crudely)
echo "test" | nc -u 8.8.8.8 53
# Send a syslog message
echo "<14>test message" | nc -u syslog-server 514
# StatsD metric
echo "myapp.requests:1|c" | nc -u localhost 8125
Two flavors: nc, ncat, OpenBSD nc, GNU netcat
Several implementations exist with slightly different flags. The big differences:
- OpenBSD nc (the most common on Linux now) — has -z (zero I/O for port testing), no shell execution by default
- GNU netcat — older, has the controversial
-eflag - ncat (from nmap project) — modern, supports SSL, IPv6, multiple connections, proxying
Check which you have:
nc -h 2>&1 | head -3
which nc
ls -l /usr/bin/nc # often a symlink showing which implementation
ncat (the upgraded version)
# SSL/TLS support
ncat --ssl example.com 443
# Listen with SSL (needs cert)
ncat --ssl --ssl-cert cert.pem --ssl-key key.pem -l 4443
# IPv6
ncat -6 example.com 443
# Proxy
ncat --proxy proxy.example.com:8080 example.com 80
Common debugging recipes
“Is this firewall rule actually blocking what I think?”
# From "blocked" side
nc -zv allowed-side ALLOWED_PORT # should succeed
nc -zv allowed-side BLOCKED_PORT # should fail / time out
“Test a custom protocol”
# Send arbitrary bytes
echo -ne 'x01x02x03x04' | nc target 9999
# Pipe in a request file
nc target 80 < my-http-request.txt
“Quickly relay traffic between two ports”
# Forward TCP 8080 to TCP 80 on backend
mkfifo backpipe
nc -l 8080 0<backpipe | nc backend 80 >backpipe
“Check what’s listening on which port”
# Easier with ss, but if all you have is nc:
for port in 22 80 443 8080 5432; do
nc -zv localhost $port 2>&1 | grep -E "succeeded|refused"
done
Security note
Some old netcat versions had -e to execute a program (giving the connecting party a shell). This is a backdoor by design. Modern Linux distros ship the OpenBSD version which removed -e for security. If you see -e /bin/bash in scripts or attacker tools, that’s why it’s a red flag.
What to learn next
That covers the diagnostic tools. Next big section: cloud and modern networking — VPCs, CDNs, service mesh, modern load balancing patterns. Up next on the roadmap.