# waste-go A modern reimagining of [WASTE](https://en.wikipedia.org/wiki/WASTE) — decentralized, friend-to-friend encrypted mesh networking with chat and file sharing. Written in Go. ## Project layout ``` waste-go/ ├── cmd/ │ ├── daemon/ The peer process — run one on each friend's machine │ └── relay/ Bootstrap/relay server — run this on your Hetzner VPS └── internal/ ├── proto/ All wire types (shared by daemon and relay) ├── crypto/ Ed25519 identity, X25519 ECDH, ChaCha20-Poly1305 ├── mesh/ Connected peer state + per-connection handler ├── ipc/ Local JSON API (UI talks to daemon here, port 17337) └── nat/ Relay client (hole-punching lives here later) ``` ## Prerequisites - Go 1.22+ → https://go.dev/dl/ - VS Code with the Go extension (`golang.go`) On first open VS Code will prompt you to install `gopls`, `dlv`, and `goimports` — accept all of them. ## Getting started ```bash # Fetch dependencies go mod tidy # Build everything (confirms it compiles) go build ./... # Terminal 1 — relay (optional for LAN testing, required across internet) go run ./cmd/relay -bind 127.0.0.1:17339 # Terminal 2 — peer A go run ./cmd/daemon -alias alice -data-dir /tmp/waste-alice -peer-port 17338 -ipc-port 17337 # Terminal 3 — peer B go run ./cmd/daemon -alias bob -data-dir /tmp/waste-bob -peer-port 17340 -ipc-port 17341 ``` Then connect B → A and send a message (netcat works fine as a quick test): ```bash # Tell peer B to connect to peer A echo '{"type":"connect","addr":"127.0.0.1:17338"}' | nc 127.0.0.1 17341 # In another terminal — subscribe to peer A's events, then send a message from B nc 127.0.0.1 17337 & echo '{"type":"send_message","room":"general","body":"hello from bob"}' | nc 127.0.0.1 17341 ``` **On Windows** — use PowerShell's built-in TCP client instead of `nc`: ```powershell # Open a connection to peer B's IPC port and keep it open $c = [System.Net.Sockets.TcpClient]::new('127.0.0.1', 17341) $w = [System.IO.StreamWriter]::new($c.GetStream()); $w.AutoFlush = $true # Tell peer B to connect to peer A $w.WriteLine('{"type":"connect","addr":"127.0.0.1:17338"}') # Send a chat message from B $w.WriteLine('{"type":"send_message","room":"general","body":"hello from bob"}') # In a separate terminal — subscribe to peer A's events $r = [System.Net.Sockets.TcpClient]::new('127.0.0.1', 17337) $reader = [System.IO.StreamReader]::new($r.GetStream()) while ($true) { $reader.ReadLine() } ``` Keep `$c` / `$w` in scope for the session; closing them disconnects the peer. ## Deploying the relay on your Hetzner VPS ```bash GOOS=linux GOARCH=amd64 go build -o bin/waste-relay ./cmd/relay scp bin/waste-relay user@your-vps:~/ # On the VPS ./waste-relay -bind 0.0.0.0:17339 ``` Then start daemons with `-relay your-vps-ip:17339` and they'll register and be able to find each other across NAT. ## IPC protocol (plain JSON over TCP) Everything is newline-delimited JSON. You can test with `nc 127.0.0.1 17337`. **Commands you send:** ```jsonc {"type":"connect","addr":"1.2.3.4:17338"} {"type":"send_message","room":"general","body":"hi"} {"type":"get_state"} ``` **Events the daemon pushes:** ```jsonc {"type":"state_snapshot","local_peer":{...},"connected_peers":[...]} {"type":"peer_connected","peer":{...}} {"type":"message_received","message":{"from":"...","body":"hi","room":"general"}} {"type":"peer_disconnected","peer_id":"..."} ``` ## Crypto choices | Purpose | Algorithm | Notes | |---|---|---| | Identity | Ed25519 | Fast, small keys, standard | | Key exchange | X25519 ECDH | Per-session ephemeral keys | | Symmetric | ChaCha20-Poly1305 | No AES-NI needed, authenticated | | Hashing | SHA-256 | File integrity | Replaces WASTE's original Blowfish/PCBC (broken cipher mode) + RSA. ## Roadmap - [ ] UDP hole-punching (STUN) in `internal/nat` - [ ] Invite file format (`.waste-invite`) — share a keypair + address hint - [ ] Peer gossip → auto-connect to friends-of-friends - [ ] File transfer - [ ] Message persistence (SQLite via `modernc.org/sqlite`) - [ ] Tauri or simple web UI consuming the IPC port