DocsGuidesTCP tunnels

TCP tunnels

ngstone portforwards HTTP. Plenty of things you might want to reach aren't HTTP — SSH, Postgres, Redis, anything speaking its own wire protocol over a raw socket. ngstone tcp is for those: it opens a tunnel to a local TCP target and hands back an allocated public host and port instead of a URL.

Basic usage#

Point it at a local port:

$ ngstone tcp 22
tcp://amber-fox-42.example.com:14201 -> 127.0.0.1:22

Now ssh through the tunnel instead of directly:

$ ssh -p 14201 amber-fox-42.example.com

Same pattern for a database:

$ ngstone tcp 5432
tcp://amber-fox-42.example.com:14202 -> 127.0.0.1:5432
$ psql -h amber-fox-42.example.com -p 14202

The positional argument accepts either a bare port number, forwarded to 127.0.0.1:<port>, or a host:port target used as-is — useful when the service you're tunneling to isn't on the same machine as the agent.

Requesting a specific port#

Left alone, the edge assigns whatever port is free in its configured range. Ask for a specific one instead:

$ ngstone tcp db.local:5432 --remote-port 15432
--remote-port, -rintdefault: 0
Requested remote port. 0means server-assigned. If the port is outside the edge's configured range or already taken, the request is rejected.

Encryption#

The client-to-edge hop is raw pass-through

Every tunnel rides an encrypted agent-to-edge session — that part never changes. But the edge can terminate TLS for HTTP tunnels because it understands HTTP; it can't do the same for ngstone tcp, because it doesn't know what protocol is inside the bytes. The client-to-edge leg is therefore only as encrypted as the tunneled protocol makes itself. SSH self-encrypts, so ngstone tcp 22is end-to-end encrypted. Plain Postgres does not encrypt by default — a Postgres tunnel is only encrypted if you turn on Postgres's own TLS (sslmode=require or stronger).

Public exposure#

The allocated port is reachable by anyone on the internet who can reach the edge on that port — the same residual exposure as any tunnel. The edge's per-IP rate limiting and per-tunnel concurrent-connection cap apply, but they limit abuse; they don't hide the service. Don't tunnel something you wouldn't otherwise expose.

Stream lifetime#

A tunnel's stream normally lives as long as the tunnel session does. There is one internal cutoff: if a stream is half-closed in one direction (one side has finished sending) and the other direction then stays idle or keeps streaming continuously for more than 30 minutes without the remote side finishing its own half, the stream is reset. Interactive and request/response protocols — SSH sessions, database connections — keep both directions open and exchanging data, so they're unaffected.

This also isn't a promise of an infinitely idle connection: the agent's local target, the client, or the OS-level TCP stack on either end can still time out or drop an idle connection on their own, independent of the 30-minute half-closed cutoff above.

Opt-in per edge#

TCP tunnels aren't available unless the edge operator turns them on. See TCP tunnelsin the edge runbook for how that's configured.