eleven / messenger Public

Clone
git clone https://amadan.net/eleven/messenger

Plain git — no account needed to clone.

Download

Download this file

1// Package tunnel is the "try Eleven in one command" transport: an outbound
2// reverse tunnel that gives a locally-running instance a public
3// https://try-<slug>.<domain> address, with no inbound ports, no DNS step, and
4// no certificate work (the router's wildcard cert already covers the domain).
5//
6// The shape is deliberately simple — two WebSocket flavours and zero clever
7// framing — so it stays understandable and maintainable by a human with an
8// afternoon (CLAUDE.md: built to outlive AI):
9//
10// - One CONTROL connection per tunnel: the client dials
11// wss://<gateway>/api/tunnel/register and holds it open. The gateway
12// assigns the slug, registers the route, and later writes small JSON
13// "dial" messages down it when the public side needs a connection.
14// - One DATA connection per backend connection: for each "dial" the client
15// opens wss://<gateway>/api/tunnel/conn/<id>, and both ends treat that
16// WebSocket as a plain byte pipe (websocket.NetConn) — the gateway's
17// reverse proxy speaks ordinary HTTP/1.1 through it to the client's local
18// instance, which is what makes WebSockets (the chat!) work through the
19// tunnel unmodified.
20//
21// The server stays blind here exactly as everywhere else: what crosses the
22// tunnel is the same TLS-stripped HTTP the router already fronts for every
23// instance — message bodies are ciphertext before they ever reach it.
24package tunnel
25
26// ControlMsg is every message that crosses a control connection, in either
27// direction. Type discriminates:
28//
29// client → gateway: "hello" (opens the exchange; Version is informative)
30// gateway → client: "ready" (Host is the assigned public hostname)
31// gateway → client: "dial" (open a data connection for ID)
32// gateway → client: "error" (human-readable refusal, then close)
33type ControlMsg struct {
34 Type string `json:"type"`
35 Version string `json:"version,omitempty"`
36 Host string `json:"host,omitempty"`
37 ID string `json:"id,omitempty"`
38 Error string `json:"error,omitempty"`
39 // Relay mode (docs/relay-mode.md): a client claiming a stable hostname
40 // sends hello with Mode "relay"; the gateway answers with a "challenge"
41 // carrying Nonce, and the client proves its keypair with a "claim"
42 // carrying PubKey + Sig over the nonce. Absent Mode means a trial —
43 // exactly the original flow, so older clients are unaffected.
44 Mode string `json:"mode,omitempty"`
45 Nonce string `json:"nonce,omitempty"`
46 PubKey string `json:"pubkey,omitempty"`
47 Sig string `json:"sig,omitempty"`
48}
49
50// slugAlphabet is lowercase and unambiguous (no 0/o, 1/l/i) — these end up in
51// hostnames people read out loud.
52const slugAlphabet = "abcdefghjkmnpqrstvwxyz23456789"
53