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) | ncat | socat | |
|---|---|---|---|
| TLS client and server | — | --ssl | OPENSSL: |
| Client certificates | — | --ssl-cert/--ssl-key | cert=, cafile= |
| Certificate verification | — | --ssl-verify | verify=1 |
| Multiple clients | -k, serial | -k, concurrent | fork |
| Access control | — | --allow/--deny | range=, tcpwrap= |
| SOCKS4/5 and HTTP proxy | -x -X | --proxy-type | PROXY:, SOCKS4: |
| Run a command per connection | -e on some forks | -e, --sh-exec | EXEC:, SYSTEM: |
| Unix sockets | -U | -U | UNIX-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 default | Often | With Nmap | Rarely |
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
| Option | Effect |
|---|---|
--ssl | Wrap the connection in TLS |
--ssl-cert FILE | PEM certificate for listen mode |
--ssl-key FILE | PEM private key for listen mode |
--ssl-verify | Verify the peer chain and hostname, implies a trustfile |
--ssl-trustfile FILE | PEM CAs to trust |
--ssl-ciphers LIST | OpenSSL cipher list string |
--ssl-servername NAME | SNI value, independent of the connect address |
--ssl-alpn LIST | Comma 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"
-eand--sh-execon a listener hand a remote client a process on your machine. On a shared or internet-facing host, always pair them with--allowand--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
| Address | What it is |
|---|---|
- or STDIO | Standard in and out |
TCP:host:port | Outbound TCP, TCP4: / TCP6: to force a family |
TCP-LISTEN:port | Inbound TCP |
UDP:host:port, UDP-LISTEN:port | Same for UDP |
UNIX-CONNECT:/path, UNIX-LISTEN:/path | Unix domain sockets |
OPENSSL:host:port, OPENSSL-LISTEN:port | TLS versions of the above |
EXEC:"cmd", SYSTEM:"cmd" | A process, argv style or via a shell |
OPEN:/path, CREATE:/path | A regular file |
PIPE:/path | A named FIFO |
PTY | A pseudo-terminal |
/dev/ttyUSB0,raw,b115200 | A serial port |
PROXY:proxy:host:port, SOCKS4A:... | Through a proxy |
| Option | Effect |
|---|---|
fork | New child per connection, the one you always want on a listener |
reuseaddr | Rebind without waiting out TIME_WAIT |
bind=addr | Bind to a specific local address |
range=10.0.0.0/8 | Only accept from this range |
su=nobody | Drop privileges after binding |
crlf | Translate line endings, needed for HTTP by hand |
verify=0 | Skip 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
| Need | Command |
|---|---|
| Probe a TLS port interactively | ncat --ssl host 443 |
| Inspect the certificate chain | openssl s_client -connect host:443 -servername host |
| Serve TLS with your own cert | ncat -lk 8443 --ssl --ssl-cert c.pem --ssl-key k.pem |
| Restrict who may connect | ncat -lk 9000 --allow 10.0.0.0/8 |
| Relay two hosts behind NAT | ncat --broker -lk 9000 |
| Long-lived TCP port forward | socat TCP-LISTEN:8080,fork,reuseaddr TCP:host:80 |
| UDP port forward | socat UDP-LISTEN:514,fork UDP:host:514 |
| Unix socket over TCP | socat TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/x.sock |
| Serial port over TCP | socat TCP-LISTEN:4000,fork /dev/ttyUSB0,raw,b115200 |
| Watch the bytes on the wire | socat -x -v ... |
| A tunnel that must stay up | ssh -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.