anistark / anistark/wasmrun

enhancement: integrate wasmnet to give browser WASM real network access

Abierto
#99 0 comentarios 0 reacciones 0 asignados Ver en GitHub
documentation enhancement
Lenguaje dominante
Rust
Estrellas
48
Forks
4
Merge medio
20 h 13 min
PR fusionados (30 d)
11

Descripción

## Summary

wasmrun OS mode runs WASM in the browser, where raw TCP/UDP sockets are impossible. wasmnet is a server side proxy that bridges WASI socket calls to real TCP/UDP/TLS over WebSocket (optionally WebTransport). This issue tracks wiring wasmnet into wasmrun so WASI socket syscalls in browser run programs reach the network, gated by policy. wasmnet itself is feature complete and published (crate `wasmnet` 0.1.4 on crates.io, npm `wasmnet` 0.1.4); all remaining work is on the wasmrun side.

```
Browser WASM (ui/) --WebSocket--> wasmnet server --TCP/UDP/TLS--> Internet
```

## Current state

wasmrun:
- OS server is `tiny_http` based with no WebSocket support yet; the `/ws` route is an explicit TODO returning "WebSocket not implemented yet": https://github.com/anistark/wasmrun/blob/e501d880770ca688c031f5943eb820e660be7625/src/runtime/os_server.rs#L328
- Browser WASI shim lives at https://github.com/anistark/wasmrun/blob/e501d880770ca688c031f5943eb820e660be7625/ui/src/wasi/wasmrun_wasi_impl.js (plus `.d.ts`); socket syscalls are not wired to any transport.
- Browser WASM is launched by https://github.com/anistark/wasmrun/blob/e501d880770ca688c031f5943eb820e660be7625/ui/src/os/WasmRunner.ts
- A bore tunnel client already exists for public exposure, wired into the OS server tunnel API: https://github.com/anistark/wasmrun/blob/e501d880770ca688c031f5943eb820e660be7625/src/runtime/os_server.rs#L459
- Existing network docs: https://github.com/anistark/wasmrun/blob/e501d880770ca688c031f5943eb820e660be7625/docs/docs/os/network-isolation.md

wasmnet (already implemented, for reference):
- Server API `Server::builder()`, `listen_with_shutdown()`, `handle_ws_upgrade(stream, policy)`: https://github.com/anistark/wasmnet/blob/22de4a1ea8fe03f1473282cd42dbb3c136dfc7e3/src/lib.rs#L279
- Protocol `Request` / `Event` enums: https://github.com/anistark/wasmnet/blob/22de4a1ea8fe03f1473282cd42dbb3c136dfc7e3/src/protocol.rs#L5
- Browser `WasmnetClient` (`connect`/`connectTls`/`connectUdp`/`bind`/`listen`/`send`/`sendTo`/`resolve`/`close`, `onData`/`onDataFrom`/`onClose`/`onAccept`): https://github.com/anistark/wasmnet/blob/22de4a1ea8fe03f1473282cd42dbb3c136dfc7e3/client/wasmnet-client.d.ts#L37

## Design decisions

1. Transport and port. The OS server uses tiny_http (synchronous, no upgrade path), while wasmnet's `handle_ws_upgrade()` expects a tokio `TcpStream`, so embedding on the same port is not straightforward. Recommended first cut: run `wasmnet::Server` on its own dedicated tokio port via `listen_with_shutdown()` and have the browser connect to `ws://:`, with the OS UI advertising that port. Revisit single port multiplexing later if wanted.
2. Policy source. Read `[os.network]` from `wasmrun.toml` and map it to wasmnet `PolicyConfig` (`allow`, `deny`, `bind_ports`, `max_connections`, `max_bandwidth_mbps`, `connection_timeout_secs`). This is the one item wasmnet deliberately left to the host. Default to wasmnet's safe policy (blocks RFC1918, loopback, link local) when unset.
3. WASI flavor. Map the socket syscalls present in the shim (`sock_open`/`sock_connect`/`sock_bind`/`sock_listen`/`sock_accept`/`sock_recv`/`sock_send`/`sock_shutdown`, per preview1 vs WASIX/preview2) onto client methods. recv is push based in wasmnet (server emits `data` events), so the shim buffers inbound bytes and drains them on `sock_recv`.
4. Lifecycle. Start and stop the wasmnet server with the OS server, and surface its status in the OS UI next to the existing tunnel status.
5. bore. Ports bound via wasmnet `bind`/`listen` can be exposed through the existing bore tunnel with no bore changes.

## Protocol spec

Single WebSocket connection, JSON messages with base64 payloads, binary framing auto negotiated. Requests: connect, connect_tls, connect_udp, bind, listen, send, send_to, close, resolve. Events: connected, data, data_from, listening, udp_bound, accepted, closed, error, denied, resolved. Authoritative source: protocol.rs linked above.

## Function specs

Server side (Rust, in wasmrun):
- Construct: `wasmnet::Server::builder().host(h).port(p).policy_config(cfg).build()?`
- Run under the existing tokio runtime: `server.listen_with_shutdown(rx).await`, shutdown via a oneshot tied to the OS server lifecycle.
- Policy: parse wasmrun.toml `[os.network]` into `PolicyConfig`, pass via `.policy_config()`, fall back to the default safe policy.

Browser side (TS/JS, in ui/):
- `const client = new WasmnetClient(`ws://${host}:${port}`); await client.ready();`
- In `ui/src/wasi/wasmrun_wasi_impl.js`, socket import handlers call client methods, keep an fd to socket id map, and maintain a per fd receive buffer fed by `onData`. Example mapping:
- sock_connect(fd, addr, port): id = await client.connect(addr, port); fdMap.set(fd, id)
- sock_send(fd, iovs): client.send(fdMap.get(fd), bytes)
- sock_recv(fd, iovs): drain bytes buffered from onData
- sock_accept: client.bind + client.listen + onAccept
- close(fd): client.close(fdMap.get(fd))

## Affected surfaces

- `src/runtime/os_server.rs`: start/stop the wasmnet server with the OS lifecycle and expose its port/status (replaces or complements the `/ws` TODO).
- `src/config/*` and a small mapping module: parse `[os.network]` and build `PolicyConfig`.
- `ui/src/wasi/wasmrun_wasi_impl.js` and `.d.ts`: wire socket syscalls to `WasmnetClient`.
- `ui/src/os/WasmRunner.ts`: instantiate the client and await ready before running.
- `ui/src/components/os/*`: optional network status entry.
- `Cargo.toml`: add the `wasmnet` crate; `ui/package.json`: add the `wasmnet` npm package.
- `docs/docs/os/network-isolation.md`: document the bridge and policy mapping.

## Proposed phasing

- [ ] Phase 0: add wasmnet (crate + npm) deps; start/stop a dedicated wasmnet port with the OS server.
- [ ] Phase 1: wire outbound TCP (sock_connect/sock_send/sock_recv/close) in the shim; end to end test a WASI HTTP GET.
- [ ] Phase 2: policy from wasmrun.toml `[os.network]` mapped to PolicyConfig; default safe policy; deny path returns EACCES to WASM.
- [ ] Phase 3: TLS (connect_tls), UDP (connect_udp/send_to), DNS (resolve).
- [ ] Phase 4: inbound bind/listen/accept (port export) plus bore exposure of bound ports.
- [ ] Phase 5: OS UI status and docs.

## References

- wasmnet repo: https://github.com/anistark/wasmnet (crate `wasmnet` 0.1.4, npm `wasmnet` 0.1.4)
- wasmnet server API, protocol, and browser client: permalinks above
- wasmrun `/ws` TODO, WASI shim, WasmRunner, tunnel API, network docs: permalinks above

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.