server: Go skeleton — control plane, UDP data plane, Docker + systemd modes
Pure stdlib. Implements the spec's core: enrollment (single-use tokens), profile (SPKI pin, only real capabilities advertised), sessions with the §2.4 HKDF-SHA256 key schedule; UDP data plane with the 32-byte ELT1 header, 4-byte HMAC gate, 1024-wide anti-replay window, ECHO_RESP with observation block, TIMESYNC, and the §3.4 anti-amplification cap. Wire format has tests (roundtrip + silent-drop cases); enroll→profile→session smoke-tested live. Modes: container (autodetect /.dockerenv|/run/.containerenv|cgroup, or --docker/ECHOLOT_DOCKER=1; config via ECHOLOT_* env; distroless image; network_mode host required — Docker NAT would falsify observed sources) and native (--install-systemd/--uninstall-systemd with a hardened unit, opt-in --self-update from Gitea releases; refused in containers). CI: tests on any server/ push; server-v* tags build+push the image to the Gitea registry and attach linux amd64/arm64 binaries + SHA256SUMS to a release — the artifact self-update consumes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ee66648e3c
commit
8a80026d49
@@ -0,0 +1,67 @@
|
||||
# echolot-server
|
||||
|
||||
The probe server ([spec](../docs/probe-protocol.md)). Pure Go, stdlib only, GPL-3.0-or-later.
|
||||
|
||||
**Skeleton status:** control plane (enroll / profile / sessions with the spec's HKDF key
|
||||
schedule), UDP data plane (ECHO with observation block, TIMESYNC, HMAC gate, anti-replay,
|
||||
anti-amplification — wire format covered by tests). Not yet: TCP/TLS echo, STUN, canary DNS,
|
||||
actions, observations API, admin UI beyond token minting.
|
||||
|
||||
## Run in Docker (config via env)
|
||||
|
||||
```sh
|
||||
docker compose up -d # see compose.yaml — network_mode: host is required
|
||||
```
|
||||
|
||||
Host networking is not negotiable: behind Docker NAT the server would observe the proxy's
|
||||
source addresses and TTLs instead of the client's — falsifying exactly what it measures.
|
||||
Container mode is autodetected (`/.dockerenv` etc.); `--docker` / `ECHOLOT_DOCKER=1` forces it.
|
||||
In this mode systemd install and self-update are refused — update by pulling a new image tag.
|
||||
|
||||
## Run native (systemd)
|
||||
|
||||
```sh
|
||||
go build -o /usr/local/bin/echolot-server ./cmd/echolot-server
|
||||
sudo /usr/local/bin/echolot-server --install-systemd # writes unit, enables, starts
|
||||
sudo /usr/local/bin/echolot-server --uninstall-systemd
|
||||
```
|
||||
|
||||
Config precedence: flags > `ECHOLOT_*` env > defaults. Every flag has an env twin
|
||||
(`--udp-listen` ↔ `ECHOLOT_UDP_LISTEN`).
|
||||
|
||||
### Self-update (opt-in, native only)
|
||||
|
||||
```sh
|
||||
echolot-server --self-update \
|
||||
--self-update-api https://git.example.net/api/v1/repos/owner/repo
|
||||
```
|
||||
|
||||
Fetches the newest `server-v*` release asset for this OS/arch and atomically replaces the
|
||||
binary; systemd's `Restart=` brings up the new version. Run it from a systemd timer for
|
||||
unattended updates. TODO before enabling anywhere untrusted: signature verification of the
|
||||
downloaded asset.
|
||||
|
||||
## First contact
|
||||
|
||||
```sh
|
||||
# 1. mint an enrollment token (admin listener is loopback-only)
|
||||
curl -s -X POST 'http://127.0.0.1:8444/admin/enroll-tokens?note=phone'
|
||||
# 2. device enrolls with it (normally via the echolot:// QR code)
|
||||
curl -sk -X POST https://<host>:8443/v1/enroll -H 'Authorization: Bearer <token>'
|
||||
# 3. device fetches its profile
|
||||
curl -sk https://<host>:8443/v1/profile -H 'Authorization: Bearer <credential>'
|
||||
```
|
||||
|
||||
The SPKI pin clients must verify is logged at startup (`pin-sha256`).
|
||||
|
||||
## Development
|
||||
|
||||
```sh
|
||||
go test ./... # includes wire-format tests for the UDP data plane
|
||||
go vet ./...
|
||||
```
|
||||
|
||||
CI (`.gitea/workflows/build-server.yml`): tests on every push touching `server/`;
|
||||
tagging `server-v1.2.3` builds + pushes the container image to the Gitea registry and
|
||||
attaches static linux amd64/arm64 binaries (+ SHA256SUMS) to a release — the same
|
||||
artifacts `--self-update` consumes.
|
||||
Reference in New Issue
Block a user