All posts

Your sandbox can now serve requests

A sandbox that can answer inbound connections without opening ports, and without routing every byte through a central proxy. How Tailcat NAT traversal works, and how it compares with frp and ngrok.

A workspace usually reaches out. It clones a repository, installs a package, calls an API, pushes a branch. Almost everything an agent does is outbound.

But a lot of real development is inbound. A dev server you want to open in a browser. A webhook receiver. A local API you want to hit from a test harness. That is the part a sandbox has never done well, because a sandbox has no public address, no open ports, and — like most machines — sits behind NAT.

We're changing that. Your BoxCompute sandbox can now serve requests as a server. You pick the ports it answers on, for a short, scoped window, and it accepts connections without a single firewall rule or public IP on your side. Under the hood it is powered by Tailcat, the open-source connectivity library from the Tailscale team.

A sandbox is a client, not a server

NAT — network address translation — is the reason most of your devices can share one public IP and still reach the internet. But NAT is a one-way door: outbound requests get mapped and answered, while inbound requests have no way to find the machine behind the router. A machine behind NAT is easy to call from, hard to call to.

A sandbox inherits exactly this problem. It runs on shared infrastructure behind its own network boundary, with no public IP and no inbound ports. That is a feature for isolation: nothing on the internet can knock on your sandbox's door. But it also means the sandbox cannot be a server — until now.

There are two families of answers when you want to reach a machine with no public address:

  • Central relay. The machine dials out to a relay server that does have a public address, and the relay forwards traffic back in. This is how frp, ngrok, and Cloudflare Tunnel all work.
  • NAT traversal. The two machines cooperate to open a direct path between themselves, using a lightweight rendezvous server only to introduce them, then getting it out of the way. This is what Tailcat does.

The difference matters. With a relay, every request and every response passes through a machine in the middle. With NAT traversal, the relay is involved only for the handshake and then drops out — traffic flows straight from you to the sandbox.

Youbehind NATDERP relayrendezvous onlyRelay serverevery byte passes throughYour sandboxbehind NAT
Both sides first meet through a DERP relay, then punch a hole through NAT and keep talking directly. The relay is out of the data path — no middle box paying for, or reading, your traffic.

How Tailcat opens a direct path

Tailcat embeds Tailscale's data plane: WireGuard for end-to-end encryption, and magicsock for NAT traversal, with DERP relays as the rendezvous channel and the relay of last resort. There is no Tailscale account, no control plane to run, and no root access needed — it is a userspace library that never touches your routing table or DNS.

The handshake happens in five steps:

  1. The sandbox starts a listener. It generates a WireGuard keypair, connects to a DERP relay, and produces a short, opaque address that encodes its public key and relay region.
  2. You connect with that address. Your side parses the address, generates its own keypair, and connects to the same relay.
  3. They introduce themselves. A small "meow" message travels through the relay carrying your node key, and each side adds the other as a WireGuard peer.
  4. The tunnel comes up. The WireGuard handshake completes — initially routed through the relay — and encrypted traffic can flow.
  5. NAT traversal upgrades the path. In parallel, each side advertises its UDP endpoints to the other through the relay, then both run Tailscale's NAT-traversal machinery to punch a hole and open a direct peer-to-peer path. The relay drops out of the data path.

The two paths sit side by side, and only the control plane ever talks to the API:

CONTROL PLANE — authorizes, then steps awayDATA PLANE — carries the bytesYouclientSandbox APIauthorizessigned · scoped · short-lived grantYouclientSandboxserverWireGuard + NAT traversal(DERP only for the initial handshake)provisions the endpoint

Two ideas are worth underlining. First, the API that authorizes the connection never carries the traffic — once access is granted, the bytes travel end-to-end between you and the sandbox. Second, because the address is a capability, not a name: whoever holds it can dial the sandbox, and when it expires, the door closes. No DNS record, no public URL, no standing open port.

Why Tailcat instead of frp, ngrok, or Cloudflare Tunnel

The relay model works — frp and ngrok are genuinely useful tools. The question is what you want the middle of your connection to be.

The table below summarizes the difference; on a narrow screen it scrolls sideways so the columns keep their width.

TailcatfrpngrokCloudflare Tunnel
Data pathDirect P2P when possible; DERP relay as fallbackAlways through your frps serverAlways through ngrok's cloudAlways through Cloudflare's edge
NAT traversalYes — STUN + UDP hole-punchingNoNoNo
You run the relay?Optional (own DERP), or Tailscale's rate-limited DERPYes — you run frps on a public serverNo — managedNo — managed
Control planeNone — metadata exchanged out of bandSelf-hostedManaged SaaSManaged SaaS
Best forPrivate, scoped access to one specific machineSelf-hosted public exposureInstant public URLPublic web apps, DDoS-protected ingress

Latency and bandwidth are the visible difference. On a relay, every packet pays for two legs — client to relay, relay to sandbox — and the relay's bandwidth is the ceiling. On a direct path, the relay is out of the picture after the handshake, so latency collapses to the direct route and no shared middle box meters your traffic.

Data exposure is the less visible difference. A relay is, by construction, in the middle of your plaintext unless you add your own end-to-end encryption. Tailcat encrypts with WireGuard between the two endpoints, and the relay only ever sees ciphertext it cannot read.

Being behind NAT stops being an obstacle. This is the part that made us choose Tailcat. Both the sandbox and your machine can be behind private networks — the hole-punching still finds a direct path in the common case. With a relay, the answer to "no public address" is always "route everything through a public box"; with Tailcat it is "let the two sides talk to each other."

None of this makes frp, ngrok, or Cloudflare Tunnel wrong. If you want a stable public URL that the whole internet can reach, with public TLS and edge protection, a tunnel is the right tool. We wanted something different: a private, capability-gated, direct connection to your sandbox. That is a different shape of connectivity, and Tailcat is the library built for it.

The honest tradeoffs

  • Direct P2P is usually possible, not always. Hard or symmetric NAT can defeat hole-punching. When that happens, traffic falls back to the DERP relay — encrypted end-to-end either way, but relayed rather than direct.
  • A Tailcat address is a token, not a URL. There is no sandbox-123.example.com to share with a colleague or bookmark. The address is scoped, expiring, and meant to be handed to one client.
  • There is no public TLS edge. If you need to serve the open internet with a certificate, a CDN, and DDoS protection, that is Cloudflare Tunnel or ngrok territory, not Tailcat's.
  • The relay matters, so choose it deliberately. The public DERP fleet Tailscale runs is rate-limited; production deployments bring their own relay. The direct path is the product, and the relay is the safety net.

We think that trade is the right one for a sandbox. The point is not to publish your sandbox to the world — it is to let you reach your sandbox as if it were the next machine on your desk, without anyone in between.

Powered by the Tailscale team

A word of thanks. We did not build the hard part of this. Tailcat is open source (BSD-3-Clause), released by Tailscale as — in their words — "Tailscale without Tailscale, by Tailscale." It packages the genuinely hard problems of peer-to-peer networking — WireGuard encryption, STUN-based endpoint discovery, UDP hole-punching, and DERP relaying — into a small library anyone can embed.

The name is a nod to netcat: a tool for moving bytes between two machines, but with Tailscale's encryption and NAT traversal underneath. We're grateful to the Tailscale team for opening up that data plane to the community. It turned what would have been months of networking infrastructure into a component we could integrate, and it lets our sandboxes inherit years of battle-tested NAT traversal for free.

What this unlocks

For an agent, being able to serve changes what a workspace is. A dev server that a human can refresh in a browser while the agent keeps working. A webhook that a CI system can post to mid-task. A local service that a colleague can curl. The sandbox stops being a box that only talks outward, and starts behaving like a machine you can actually develop against.

This is rolling out as an early preview, starting with selected TCP ports on short-lived, signed grants. We're starting deliberately narrow — chosen ports, bounded lifetimes, no general inbound access — because connectivity is the one capability you want to open carefully. As it matures, the same transport can carry more of the workflows a full machine is expected to support.

A sandbox that can serve is a sandbox that finally behaves like a server. We think that's a big step for agent workspaces — and we're glad to build it on the Tailscale team's work.

Further reading

Back to the blog