Networking
A guest has no network unless the site asks for one, and then its only way out is the visitor's own browser.
HTTP, HTTPS and WebSockets
With --network fetch (or snowglobe.network="fetch"), the guest gets a network
card and DHCP, and every request it makes leaves as the page's own browser request. Its connections to
ports 80 and 443 end inside the machine:
- HTTP requests become a
fetch(). - HTTPS is terminated in the machine with a certificate signed by a CA made fresh for
each build, which the guest trusts, and replayed with
fetch("https://…"). Nothing else should trust that CA: its key ships with the site. - WebSockets open a browser
WebSocketto the same URL.
The browser's rules still apply. HTTP(S) only reaches servers that allow CORS (others answer with a 502 that says so), UDP goes nowhere, and other TCP only through a tunnel.
Other TCP: tunnels
A page can't open raw TCP, so a connection to a database or any port but 80 and 443 is refused unless
the site names it as a tunnel. --tunnel HOST:PORT=URL carries every connection to
HOST:PORT over a WebSocket to URL, as binary messages: what websockify, websocat
and Neon's wsproxy speak.
websocat --binary ws-l:0.0.0.0:6543 tcp:127.0.0.1:5432 # next to Postgres
snowglobe build ./my-app --network fetch --tunnel db.internal:5432=wss://db-proxy.example.com/
Credentials
Whatever the guest knows ships with the site: a password in its environment is in the snapshot, for every visitor.
Instead, put {token} in the tunnel URL and name a token endpoint with
--tunnel-token URL. The page asks it for a fresh token on every connection (natively, once
per boot), and a gateway behind the tunnel checks the token and holds the real credentials. A token only
replaces the password: what it opens is whatever the gateway lets any visitor do.
Builds and snowglobe run refuse loopback and private addresses, so a guest can't reach the
host's own services. --allow-private lets them, for a tunnel endpoint on your own machine
while developing.