Skip to main content

HTTP, TCP, and UDP tunneling

Most tunneling tools only handle HTTP. raba handles all three, from the same client and the same server, because the underlying mechanism is protocol-agnostic: the Client opens one persistent, TLS-wrapped TCP connection to the Server and multiplexes every tunneled connection over it as a sequence of framed messages (StreamOpen/StreamData/StreamClose), tagged with a protocol byte (Http / Tcp / Udp) and a stream_id. HTTP, TCP, and UDP share almost identical plumbing — UDP is the one exception, being connectionless.

HTTP

raba http 3000
  • Routed by subdomain — raba http 3000 --subdomain myapp (or an auto-generated one) makes your local server reachable at https://myapp.<your-domain>.
  • Byte-level forwarding: the server never parses your HTTP request or response bodies. It reads just enough of the request line to find the Host header (to know which project to route to), then forwards everything else — headers, body, whatever — as raw bytes. See Byte-level forwarding & privacy for why this matters.

TCP

raba tcp 5432
  • Gets a dedicated public port instead of subdomain routing — there's no Host header in raw TCP to route by, so each TCP project gets its own listener on its own port, allocated automatically from a configured range.
  • Useful for anything that isn't HTTP: a database, a game server, an SSH endpoint, a custom protocol.

UDP

raba udp 51820
  • Same dedicated-port model as TCP, but UDP is connectionless, so raba tracks lightweight "pseudo-sessions" — a (peer_ip, peer_port) pair gets a stream_id for the duration of activity, then gets cleaned up automatically by a background reaper once it's been idle past a configurable timeout (default ~30s).

Domains and TLS — what's automatic, what's on you

Coming from ngrok or Cloudflare Tunnel? Here's the honest comparison, since this is the part that differs most:

  • raba is self-hosted, not a hosted service. There's no free shared *.raba.io-style subdomain like ngrok's default tier gives you — you run your own raba instance (a single Docker image, or a direct systemd install), and you need a real domain you control pointed at it. That's the tradeoff for owning your own infrastructure instead of depending on a third-party relay.
  • TLS is fully automatic once that's set up, though — not something you configure per tunnel, and not something you manage with certbot by hand. Point a domain at your instance, and raba issues and renews Let's Encrypt certificates for it automatically via ACME DNS-01, including per-team custom domains (see Teams and custom domains for exactly how that works, including why raba never needs your DNS provider's credentials). Every raba http project gets HTTPS for free the moment its domain is verified — you never touch a certificate.
  • Every project needs a subdomain (auto-generated if you don't pick one — see raba http), routed under whichever domain your team is using. TCP/UDP projects skip the subdomain and get a dedicated port instead, since there's no Host header to route by.

So: more upfront setup than "no signup, instant random URL," in exchange for owning the whole stack — your data, your domain, your server, nothing routed through someone else's relay.

One tunnel, one persistent connection

Regardless of protocol, everything flows over the same TCP connection between your machine and the server — opening a new tunneled HTTP request or TCP connection doesn't open a new connection to the server, it just adds a new logical stream to the existing one. This keeps connection overhead low even under many concurrent tunneled connections, and means a single raba http 3000 process can serve as many simultaneous visitors as your local server can handle.