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 athttps://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
Hostheader (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
Hostheader 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 astream_idfor 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
certbotby 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). Everyraba httpproject 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 noHostheader 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.