A minimal C utility that bridges stdio to a TCP or UDP socket. Designed
primarily as an SSH ProxyCommand but useful anywhere you need to tunnel a
byte stream over a network connection.
stdio-proxy [-v] tcp|udp:host:port
| Flag | Description |
|---|---|
-v |
Verbose — log connection events to stderr |
# SSH through an arbitrary TCP host
ssh -o ProxyCommand='stdio-proxy tcp:%h:%p' user@host
# Forward stdin/stdout over UDP
stdio-proxy udp:dns.server:53stdin ──▶ stdio-proxy ──▶ socket ──▶ remote
stdout ◀── stdio-proxy ◀── socket ◀── remote
A single poll(2) loop multiplexes both directions without threads.
When stdin reaches EOF, shutdown(SHUT_WR) sends a TCP half-close (FIN)
so the remote server sees end-of-input without the connection being torn
down, allowing any pending server response to still arrive.
Handles SIGINT/SIGTERM by shutting the socket down cleanly.
Requires GCC and a POSIX libc. Static linking requires glibc-static
(RHEL/AlmaLinux: dnf install glibc-static from the CRB repo) or
musl-libc-static.
# Dynamic binary (development)
gcc -std=c11 -O2 -o stdio-proxy stdio-proxy.c
# Static binary (default make target)
make
# Static binary via musl (no NSS quirks)
make CC=musl-gcc # or: make static-muslThe Makefile auto-detects the host architecture and selects the
appropriate generic baseline (-march=x86-64 / -march=armv8-a).
Requires Go in PATH (uses the project's existing module).
make test
# or from the repo root:
go test -v ./test/The test suite compiles a debug binary, then runs 19 integration tests covering argument validation, TCP send/receive, bidirectional echo, TCP half-close, large payloads, and signal handling.