Networking

The virtual network stack — interfaces, sockets, DNS, ports — and how in-VM HTTP servers work.

Each box has a NetworkStack — a virtual network with interfaces, sockets, routes, and a DNS resolver — plus a portRegistry on the kernel that maps a port number to a request handler. Together they let programs inside the VM listen, connect, and serve as if they were on a real machine, without any real sockets.

Listening and serving

When a program creates an HTTP server through the http shim and calls listen(port), the server registers a VirtualRequestHandler for that port on the kernel. Anything that can produce a VirtualRequest — the service worker, a tunnel, or an in-VM client — reaches the server by looking up its port.

// inside the VM
const http = require("http");
http.createServer((req, res) => res.end("hi")).listen(3000);

Now port 3000 is in the registry, and a browser preview at `/_sw/<boxId>/3000/` (or a tunnel) can hit it.

Sockets, DNS, and routes

The NetworkStack models the lower layers too:

  • Interfaces & routes — a loopback and virtual interfaces, inspectable with the ifconfig, ip, route, and netstat commands.
  • DNS — a resolver seeded from /etc/hosts (loaded at boot). host queries it; the network layer uses it to resolve names.
  • Socketsnet/tls sockets for programs that speak raw TCP rather than HTTP.

The ports command lists what's currently listening, and forward / unforward manage port forwards.

Reaching the outside world

A browser tab can't make arbitrary cross-origin requests, so outbound HTTP from inside the VM is routed through a CORS proxy for hosts that don't send CORS headers (for example api.expo.dev, which create-expo-app calls). The Node layer injects a proxying fetch into each module and serves require("fetch-nodeshim") from the same stack, so a package's networking is transparently proxied. See Tunnelling for the proxy and relay.

The curl command

curl is built in and speaks to both in-VM servers and (via the proxy) the outside world — useful for testing a dev server from the shell:

curl http://localhost:3000
curl -H "Accept-Encoding: identity" http://localhost:8081/index.bundle

Note

The virtual network is per-box. Two boxes don't share ports or sockets — which is exactly what you want when running many isolated sandboxes in one process.