Netcat Cheatsheet

ncat and socat

Use this Netcat reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Why go past nc at all

Plain netcat has no TLS, no access control, no proxy support worth the name, and fork behaviour that varies by variant. Ncat and socat both fix that, in different directions.

nc (OpenBSD)ncatsocat
TLS client and server—--sslOPENSSL:
Client certificates—--ssl-cert/--ssl-keycert=, cafile=
Certificate verification—--ssl-verifyverify=1
Multiple clients-k, serial-k, concurrentfork
Access control—--allow/--denyrange=, tcpwrap=
SOCKS4/5 and HTTP proxy-x -X--proxy-typePROXY:, SOCKS4:
Run a command per connection-e on some forks-e, --sh-execEXEC:, SYSTEM:
Unix sockets-U-UUNIX-CONNECT:, UNIX-LISTEN:
Pseudo-terminals——PTY
Serial ports, files, FIFOs——Yes, any address type
Chat / broker relay—--chat, --broker—
Traffic hex dump——-x, -v
Installed by defaultOftenWith NmapRarely

Reach for ncat when you want netcat with TLS. Reach for socat when you need to glue two different kinds of endpoint together, or when you need it to survive more than one connection.

Ncat over TLS

--ssl is the whole feature. It works in both client and listen mode.

# TLS client, the ncat equivalent of openssl s_client
ncat --ssl example.com 443
ncat --ssl --ssl-verify --ssl-trustfile ca.crt example.com 443
ncat --ssl --ssl-servername example.com 203.0.113.10 443
ncat --ssl --ssl-alpn h2 example.com 443

# TLS listener with your own certificate
ncat -lk 8443 --ssl --ssl-cert cert.pem --ssl-key key.pem

# TLS listener with a throwaway self-signed cert generated on the spot
ncat -lk 8443 --ssl
OptionEffect
--sslWrap the connection in TLS
--ssl-cert FILEPEM certificate for listen mode
--ssl-key FILEPEM private key for listen mode
--ssl-verifyVerify the peer chain and hostname, implies a trustfile
--ssl-trustfile FILEPEM CAs to trust
--ssl-ciphers LISTOpenSSL cipher list string
--ssl-servername NAMESNI value, independent of the connect address
--ssl-alpn LISTComma separated ALPN protocols

--ssl alone does not verify anything. Without --ssl-verify ncat accepts any certificate, which is fine for probing and wrong for a tunnel you rely on.

Ncat exec, access control, and relays

# run a command per connection, argv style, no shell
ncat -lk 8080 -e /usr/local/bin/handler

# run it through /bin/sh, so pipes and redirection work
ncat -lk 8080 --sh-exec "cat /etc/motd"

# only these sources may connect
ncat -lk 9000 --allow 10.0.0.0/8
ncat -lk 9000 --allowfile allowed.txt --deny 10.0.0.99

# chat server, every client sees every message
ncat -lk 9000 --chat

# broker, connect two hosts that cannot reach each other directly
ncat --broker -lk 9000

--allow and --deny take hosts, CIDR ranges, and comma separated lists. --allow is a whitelist, so anything not listed is refused.

Combine TLS with exec for an encrypted one-off endpoint:

ncat -lk 8443 --ssl --ssl-cert cert.pem --ssl-key key.pem \
  --sh-exec "date -u"

-e and --sh-exec on a listener hand a remote client a process on your machine. On a shared or internet-facing host, always pair them with --allow and --ssl.

socat addresses

socat takes exactly two addresses and pumps bytes between them. Everything is a combination of address type plus comma separated options.

socat <address1> <address2>
socat - TCP:example.com:80              # stdio to a TCP socket
socat READLINE TCP:example.com:80       # with line editing and history
socat TCP-LISTEN:8080,fork,reuseaddr TCP:backend.internal:80
AddressWhat it is
- or STDIOStandard in and out
TCP:host:portOutbound TCP, TCP4: / TCP6: to force a family
TCP-LISTEN:portInbound TCP
UDP:host:port, UDP-LISTEN:portSame for UDP
UNIX-CONNECT:/path, UNIX-LISTEN:/pathUnix domain sockets
OPENSSL:host:port, OPENSSL-LISTEN:portTLS versions of the above
EXEC:"cmd", SYSTEM:"cmd"A process, argv style or via a shell
OPEN:/path, CREATE:/pathA regular file
PIPE:/pathA named FIFO
PTYA pseudo-terminal
/dev/ttyUSB0,raw,b115200A serial port
PROXY:proxy:host:port, SOCKS4A:...Through a proxy
OptionEffect
forkNew child per connection, the one you always want on a listener
reuseaddrRebind without waiting out TIME_WAIT
bind=addrBind to a specific local address
range=10.0.0.0/8Only accept from this range
su=nobodyDrop privileges after binding
crlfTranslate line endings, needed for HTTP by hand
verify=0Skip TLS certificate verification
cert=, key=, cafile=TLS material

socat recipes

# persistent TCP forward, the canonical use
socat TCP-LISTEN:8080,fork,reuseaddr TCP:backend.internal:80

# UDP forward, which netcat cannot do reliably
socat UDP-LISTEN:5514,fork UDP:collector.internal:514

# expose a Unix socket over TCP (Docker, Postgres, a dev server)
socat TCP-LISTEN:2375,fork,reuseaddr UNIX-CONNECT:/var/run/docker.sock

# the reverse: a local Unix socket fronting a remote TCP service
socat UNIX-LISTEN:/tmp/pg.sock,fork TCP:db.internal:5432

# TLS terminator in front of a plaintext backend
socat OPENSSL-LISTEN:8443,fork,reuseaddr,cert=cert.pem,key=key.pem \
  TCP:127.0.0.1:8080

# TLS client, verification on
socat - OPENSSL:example.com:443,cafile=/etc/ssl/certs/ca-certificates.crt

# serial console over the network
socat TCP-LISTEN:4000,fork,reuseaddr /dev/ttyUSB0,raw,b115200

# a real interactive shell, unlike nc -e which gives no job control
socat TCP-LISTEN:9000,reuseaddr EXEC:'bash -li',pty,stderr,setsid,sigint,sane

# see every byte in both directions, in hex
socat -x -v TCP-LISTEN:8080,fork,reuseaddr TCP:backend:80

-d -d adds connection level logging, -x hex dumps the traffic, and -v mirrors it to stderr. socat -V prints the compiled-in feature list, which is how you tell whether OPENSSL: is available in a given build.

Picking one

NeedCommand
Probe a TLS port interactivelyncat --ssl host 443
Inspect the certificate chainopenssl s_client -connect host:443 -servername host
Serve TLS with your own certncat -lk 8443 --ssl --ssl-cert c.pem --ssl-key k.pem
Restrict who may connectncat -lk 9000 --allow 10.0.0.0/8
Relay two hosts behind NATncat --broker -lk 9000
Long-lived TCP port forwardsocat TCP-LISTEN:8080,fork,reuseaddr TCP:host:80
UDP port forwardsocat UDP-LISTEN:514,fork UDP:host:514
Unix socket over TCPsocat TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/x.sock
Serial port over TCPsocat TCP-LISTEN:4000,fork /dev/ttyUSB0,raw,b115200
Watch the bytes on the wiresocat -x -v ...
A tunnel that must stay upssh -L, stunnel, or a real proxy

Gotchas

- Forget fork and socat serves exactly one connection, then exits. This is the single most common socat surprise. - Forget reuseaddr and a restart fails with Address already in use for up to a couple of minutes. - socat address options are comma separated with no spaces. A stray space makes socat read the rest as a third address and it errors out with a usage line. - ncat --ssl without --ssl-verify trusts anything, including a self-signed certificate from an attacker. - ncat -lk --ssl with no --ssl-cert generates a fresh self-signed certificate each start, so clients that pin or verify will fail after every restart. - Neither tool is a substitute for a supervised tunnel. Both die on an unhandled error and neither reconnects. Run them under systemd, supervisord, or a retry loop if they matter. - socat needs crlf for hand-typed HTTP, and crlf on a binary stream corrupts it. Never set it on anything that is not line oriented text.