socat

package module
v1.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: MIT Imports: 0 Imported by: 0

README

socat (Go)

A Go implementation of socat: a multipurpose relay for moving data between files, sockets, processes, and other endpoints.

CI codecov Go

The command line and address syntax follow classic socat except for the documented differences below. The project supports Linux, macOS, and Windows. DTLS is 1.3-only. WebSocket, QUIC, and HTTP/2 and HTTP/3 CONNECT are Go-specific.

Build

Go 1.27 or newer is required.

make build

Without make:

go build -o socat ./cmd/socat
go build -o filan ./cmd/filan
go build -o procan ./cmd/procan

Usage

socat [options] <address> <address>
socat -V | -h | -hh | -hhh

Each address has the form TYPE:parameters,option=value,.... Use - for standard input and output.

  • socat -h lists available address types.
  • socat -hh lists supported options.
  • socat -hhh also lists aliases and termios names.

Common flags include -d, -v, -x, -b, -t, -T, -u/-U, -4/-6/-0, and --statistics. On Linux and macOS, -ly and -lm send logs to syslog.

The command output is the authoritative feature list for the current platform.

Examples

Connect standard input and output to a TCP service:

printf 'GET / HTTP/1.0\r\nHost: 127.0.0.1\r\n\r\n' |
  ./socat - TCP4:127.0.0.1:80

Publish a Unix socket over TCP:

./socat TCP4-LISTEN:5432,reuseaddr,fork \
  UNIX-CONNECT:/var/run/postgresql/.s.PGSQL.5432

Expose a TCP service through a Unix socket:

./socat UNIX-LISTEN:/tmp/app.sock,fork,unlink-early,mode=600 \
  TCP4:127.0.0.1:8080

Run an interactive program on a pseudo-terminal:

./socat -,pty,cfmakeraw EXEC:'python3 -i',setsid,stderr

Address types

The following groups summarize the implemented address families. Run socat -h for the exact names and aliases available on your platform.

Group Address types
Standard streams and descriptors STDIO, STDIN, STDOUT, STDERR, FD; ACCEPT-FD on Linux and macOS
Files and local I/O OPEN, CREATE, GOPEN, PIPE, FIFO, ECHO, SOCKETPAIR, TEXT, STALL, PTY
IP networking TCP connect/listen, UDP connect/listen/send/receive/datagram, raw IP; generic SOCKET on Linux and macOS
Local networking Unix stream/datagram sockets on Linux and macOS; Linux abstract sockets
Processes EXEC, SYSTEM, SHELL
Encryption and proxies TLS, DTLS 1.3, HTTP CONNECT, SOCKS4/4A/5, SOCKS5 BIND
Go extensions WebSocket (WS/WSS), QUIC, HTTP/2 and HTTP/3 CONNECT
Linux networking SCTP, VSOCK, TUN/TAP, AF_PACKET INTERFACE, POSIX message queues

Common forms include:

TCP4:host:port                 TCP4-LISTEN:port
UDP4:host:port                 UDP4-RECVFROM:port
UNIX-CONNECT:path              UNIX-LISTEN:path
TLS:host:port                  TLS-LISTEN:port
DTLS-CLIENT:host:port          DTLS-SERVER:port
WS:host:port                   WSS-LISTEN:port
QUIC:host:port                 QUIC-LISTEN:port
EXEC:command                   SYSTEM:shell-command

OPENSSL-* and SSL-* remain aliases for the corresponding TLS and DTLS addresses. QUIC is a byte stream over one bidirectional QUIC stream; it is not HTTP/3. On Linux and macOS, SOCKET-* takes a packed sockaddr, so you can connect or listen on families other than TCP and UDP. UDP-LISTEN,fork keeps a session per peer.

Options

Address options are written after the address parameters:

TCP4-LISTEN:8080,reuseaddr,fork,bind=127.0.0.1

Major option groups include:

  • listener and socket configuration, timeouts, retry, and peer filters;
  • file modes, ownership, locking, seeking, truncation, and unlink behavior;
  • process descriptors, PTYs, signals, working directories, and terminal flags;
  • IPv4/IPv6, multicast, ancillary data, TUN, and interface settings;
  • TLS certificates, verification, protocol versions, ciphers, and SNI;
  • proxy, SOCKS, WebSocket, QUIC, and namespace settings;
  • transfer conversions such as cr, crnl, ignoreeof, and readbytes.

Options are advertised only where they are implemented. Unsupported platform/address combinations are rejected rather than silently ignored. Use socat -hh instead of this README as the complete option reference.

TLS and QUIC

TLS listeners require a certificate. verify=1 is the default; clients use the system trust store unless cafile= or capath= is supplied.

# Create a test certificate with an ECDSA P-256 key.
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
  -sha256 -days 365 -nodes -keyout server.key -out server.crt \
  -subj "/CN=server.example" -addext "subjectAltName=DNS:server.example"

# Publish a local TCP service over TLS.
./socat TLS-LISTEN:8443,reuseaddr,fork,cert=server.crt,key=server.key,verify=0 \
  TCP4:127.0.0.1:8080

# Connect to it and verify the server certificate.
./socat TCP4-LISTEN:8080,reuseaddr,fork,bind=127.0.0.1 \
  TLS:server.example:8443,cafile=server.crt,verify=1

verify=0 disables certificate trust and name checks. On a listener it also disables client-certificate verification.

QUIC uses TLS 1.3 and otherwise accepts the same certificate and verification options:

./socat QUIC-LISTEN:4433,reuseaddr,fork,cert=server.crt,key=server.key,verify=0 \
  TCP4:127.0.0.1:8080

The default QUIC ALPN is socat. Use alpn= when both endpoints require a different value.

DTLS 1.3

DTLS encrypts UDP without making delivery reliable or ordered. OPENSSL-DTLS-CLIENT / OPENSSL-DTLS-SERVER (aliases DTLS-CLIENT / DTLS-SERVER) accept the usual certificate, bind, retry and peer-filter options. Both ends verify peers by default, so the server requires a trusted client certificate.

./socat -T 30 DTLS-SERVER:4433,cert=server.pem,key=server.key,cafile=ca.pem,fork PIPE
./socat -T 30 - DTLS-CLIENT:localhost:4433,cert=client.pem,key=client.key,cafile=ca.pem
  • dtls-mtu sets the maximum UDP payload (default 1200; range 256–65507). Byte-stream peers work with the default 8192-byte transfer buffer: writes split into fitting records and short reads retain tails, separately per direction. Datagram and unknown peers stay strict: oversized writes fail and small reads truncate. Size -b and the peer's records accordingly.
  • CID and RFC 9853 path validation are negotiated by default. New addresses must pass the server's peer filters. dtls-migration=0 disables both. alpn=protocol optionally selects one application protocol.
  • MTU confirmation and upward discovery default on for dedicated clients with migration enabled, successful unfragmented-send setup and negotiated CID/RRC. Search starts after the final handshake flight is acknowledged and stays within dtls-mtu (default 1200). dtls-unfragmented-probes=0 disables discovery; listeners ignore this option. ICMP Packet Too Big messages are not used. Datagram writes are never retried. Byte-stream chunks are split again and retried only after a definite too-large rejection before transmission, with zero bytes written and a smaller size limit. Timeouts, partial writes and ambiguous errors are not retried.
  • handshake-timeout caps negotiation at 30 seconds by default; zero removes that deadline, but protocol retry limits remain. so-rcvtimeo / rcvtimeo adds a handshake receive-wait limit (zero or omission disables it). Received fragments, ACKs and retransmissions restart that wait. Expiry ends the connection attempt, subject to retry / forever.
  • After negotiation, receive timeouts remain retryable. Use -T to bound an idle transfer; close alerts can be lost. Use ordinary EXEC, since EXEC,nofork cannot inherit a plaintext DTLS descriptor.
  • Only DTLS 1.3 is negotiated, regardless of a lower min-version; max-version below 1.3 is rejected. cipher / ciphers keeps its TLS 1.2 meaning and does not select DTLS 1.3 suites.

Go supplies cryptographic and certificate-policy updates; new algorithms still require DTLS wire integration. Include the adapted Pion MIT license, quic-go MIT license, and attribution when redistributing that code.

Intentional differences from classic socat

Compatibility is checked against the latest classic socat release and current master from the official repository. Public address and option spellings are audited automatically. The scorecard tracks the classic test.sh suite.

  • fork sessions use goroutines rather than worker processes.
  • On macOS, UDP-LISTEN,fork,shut-down keeps connected child sockets because shutdown() requires one. Concurrent peers can therefore have datagrams delivered to another child and dropped; the default shut-null path uses the shared-socket peer dispatcher instead. Windows rejects UDP-LISTEN,fork,shut-down because fork sessions share the listen socket.
  • Unknown options, malformed values, and unsupported combinations fail explicitly instead of becoming no-ops.
  • -s is accepted as a compatibility no-op; error handling is unchanged and does not continue after otherwise non-fatal errors.
  • DNS overrides use a per-address resolver and never mutate process-global resolver state.
  • ai-v4mapped is off unless requested, matching classic runtime behavior rather than the man-page default. Go dials mapped results as IPv4.
  • handshake-timeout separately limits TLS, DTLS, WebSocket, proxy, SOCKS, and QUIC negotiation.
  • WebSocket, QUIC, and HTTP/2 and HTTP/3 CONNECT are Go-specific extensions.
  • DTLS endpoints split byte-stream input into records that fit dtls-mtu and retain record tails for byte-stream output. Datagram input stays strict. This is an endpoint policy; classic's documented interface asks users to size DTLS transfers with -b.
  • TLS listeners fail immediately when cert= is missing.
  • TLS peer names use VerifyHostname; empty commonname= skips only the name check, and capath= loads every parseable certificate file rather than only OpenSSL hash-named entries.
  • Child descriptor remapping happens in the child, so a failed EXEC cannot leave the parent process partially remapped.
  • Omitted setpgid, setpgid=0, and setpgid=1 all create a new process group as documented.
  • end-close[=<bool>] and the close alias accept omission, 0, and 1 as documented. Classic C rejects explicit =0 and =1 despite the man page.
  • Lock files and unlink-on-close paths are removed only if they still refer to the object created by this process.
  • Boolean unlink options honor =0; they do not delete merely because the option was present.
  • ACCEPT-FD supports fork, range, sourceport, lowport, and tcpwrap matching classic runtime behavior despite the narrower man page. It is Linux/macOS only.
  • TUN,retrieve-vlan is rejected instead of succeeding without restoring VLAN tags; retrieve-vlan is supported on Linux INTERFACE addresses.
  • Windows rejects simultaneously enabled binary and text modes instead of relying on an unspecified conversion order.
  • Windows uses the Winsock provider's listen queue size and rejects explicit backlog= because Winsock cannot change it after Go creates the listener.
  • Generic ioctl request and integer values outside their 32-bit range are rejected instead of wrapping into a different operation.
  • Multicast membership rejects unresolved interface names instead of falling back to an unintended interface.
  • On macOS, SIGILL follows the Go runtime's fatal-signal behavior rather than the classic caught-signal exit code.

Unsupported names are omitted from help and rejected if used. They are not silently emulated with a different protocol.

Feature Status
DCCP and UDP-Lite Not supported. Both were removed from modern Linux kernels and have no native macOS or Windows equivalent.
GNU readline address Not implemented.
DTLS 1.0/1.2 Rejected. DTLS endpoints support only DTLS 1.3, with AES-GCM or ChaCha20-Poly1305 and RSA, ECDSA, Ed25519, or ML-DSA certificates.
DSA, SSLv3, and weak TLS ciphers Rejected; use current TLS versions and RSA, ECDSA, Ed25519, or ML-DSA keys.
OpenSSL engines, FIPS mode, EGD, pseudo-random mode, custom DH parameters, and fragment controls Enabling these features is rejected where Go's TLS stack has no equivalent.
Process-wide setuid, setgid, chroot, and substuser options Not implemented because changing credentials or root from a goroutine would affect every session. They require process isolation.
Process-global libc resolver flags Not implemented. res-nsaddr and res-usevc are supported per address.
Read-only, obsolete, or structurally unsafe socket options Rejected rather than advertised as setters. This includes get-only socket state and options that require structures the classic integer syntax cannot represent safely.
ipv6-recverr Not advertised because the documented interface is ip-recverr (IP_RECVERR). IPV6_RECVERR is not documented in socat.yo.
udp-ignore-peerport Not implemented because classic documents the name but does not expose or implement it. UDP datagram receive behavior follows the working classic implementation.

Go's TLS defaults also intentionally keep TLS compression disabled. The accepted openssl-compress=none spelling can be used by compatible command lines; enabling compression is rejected.

Environment

The main classic environment inputs are supported, including SOCAT_DEFAULT_LISTEN_IP, SOCAT_PREFERRED_RESOLVE_IP, SOCAT_MAIN_WAIT, SOCAT_TRANSFER_WAIT, and SOCAT_FORK_WAIT.

Child processes receive SOCAT_* connection metadata. TLS metadata is exposed as SOCAT_TLS_*, with SOCAT_OPENSSL_* aliases for compatible scripts.

Testing

make check              # platform policy, lint, security, unit, and e2e tests
make test               # formatting and unit tests
make e2e                # local end-to-end tests
make test-netns-docker  # privileged Linux namespace and raw-IP tests
make classic-parity     # native Go vs official release and reviewed master
make update-scorecard   # Linux: refresh committed privileged-Docker results

make check does not contact repo.or.cz. make classic-parity syncs the official repository into a gitignored working directory.

Focused raw-IP suites live in internal/xio/privileged (Linux and macOS) and e2e/privileged (macOS). They need the privileged build tag and fail without root. Ordinary go test excludes them.

sudo "$(command -v go)" test -race -count=1 -tags=privileged ./internal/xio/privileged
go build ./cmd/socat
sudo env SOCAT="$PWD/socat" "$(command -v go)" test -count=1 -tags=e2e,privileged ./e2e/privileged

Classic test.sh results: testdata/scorecard/README.md. On Linux with Docker, make update-scorecard refreshes the privileged baselines.

Examples and benchmarks

  • Docker Compose lab: TLS, QUIC, WSS, HTTP, and SOCKS examples (make lab).
  • Benchmarks: optional loopback comparisons with classic socat (make bench).
  • go run ./scripts/fuzzall: local parser and protocol fuzz campaigns.

Repository layout

cmd/                  socat, filan, and procan commands
internal/parse/       address and option parsing
internal/xio/         endpoint implementations
internal/relay/       transfer engine
e2e/                  end-to-end tests
examples/lab/         container examples
testdata/scorecard/   classic compatibility results
testdata/bench/       benchmark snapshots

License

MIT. See LICENSE.

This is an independent reimplementation and does not copy classic socat's C sources.

Documentation

Index

Constants

View Source
const Version = "1.0.3"

Version is the release version of this Go socat implementation.

Variables

This section is empty.

Functions

This section is empty.

Types

This section is empty.

Directories

Path Synopsis
cmd
filan command
filan — file descriptor analyzer.
filan — file descriptor analyzer.
procan command
socat command
internal
cli
Package cli implements the socat command-line interface.
Package cli implements the socat command-line interface.
dtls13
Package dtls13 implements the DTLS 1.3 protocol over datagrams.
Package dtls13 implements the DTLS 1.3 protocol over datagrams.
filan
Package filan formats detailed file-descriptor reports.
Package filan formats detailed file-descriptor reports.
logx
Package logx provides severity-based logging compatible with classic socat -d levels.
Package logx provides severity-based logging compatible with classic socat -d levels.
outbuf
Package outbuf builds text and writes it once so help/report printers do not ignore a fmt.Fprint error on every line.
Package outbuf builds text and writes it once so help/report printers do not ignore a fmt.Fprint error on every line.
parse
Package parse implements address specification parsing.
Package parse implements address specification parsing.
relay
Package relay implements bidirectional data transfer between two streams.
Package relay implements bidirectional data transfer between two streams.
testcert
Package testcert generates throwaway CAs and leaf certificates for tests.
Package testcert generates throwaway CAs and leaf certificates for tests.
xio
SOCKET address data uses quoted strings with C-style escapes ("path\0"), hex segments (xHHHH), and single-character forms ('c').
SOCKET address data uses quoted strings with C-style escapes ("path\0"), hex segments (xHHHH), and single-character forms ('c').
xio/all
Package all imports every address opener so xio.Register init runs.
Package all imports every address opener so xio.Register init runs.
xio/dtlsopen
Package dtlsopen implements authenticated DTLS 1.3 datagram endpoints.
Package dtlsopen implements authenticated DTLS 1.3 datagram endpoints.
xio/quicopen
Package quicopen implements raw QUIC byte relay (RFC 9000) connect and listen.
Package quicopen implements raw QUIC byte relay (RFC 9000) connect and listen.
xio/tlsopen
TLS endpoints via crypto/tls — not OpenSSL/CGO.
TLS endpoints via crypto/tls — not OpenSSL/CGO.
xio/wsopen
Package wsopen implements WS / WSS connect and listen.
Package wsopen implements WS / WSS connect and listen.
scripts
benchclient command
Command benchclient supports scripts/bench.py (TCP / TLS / QUIC / DTLS).
Command benchclient supports scripts/bench.py (TCP / TLS / QUIC / DTLS).
fuzzall command
Command fuzzall runs native Go fuzz targets one at a time.
Command fuzzall runs native Go fuzz targets one at a time.
gooscheck command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL