From cae3c009908c3abf93b6daca4b2ddc5613e6e7e8 Mon Sep 17 00:00:00 2001 From: mrambossek Date: Thu, 30 Jul 2026 16:54:52 +0200 Subject: [PATCH] =?UTF-8?q?server:=20document=20deployment=20requirements?= =?UTF-8?q?=20=E2=80=94=20no=20proxy,=20no=2080/443,=20and=20why?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ports table, host-IP/second-IP/canary-zone requirements, and the two protocol properties (SPKI pinning, observed-source fidelity) that a reverse proxy would break. Coexists with traefik by never touching its ports. Co-Authored-By: Claude Opus 5 --- server/README.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/server/README.md b/server/README.md index 0a3ae73..216fda3 100644 --- a/server/README.md +++ b/server/README.md @@ -7,6 +7,44 @@ schedule), UDP data plane (ECHO with observation block, TIMESYNC, HMAC gate, ant anti-amplification — wire format covered by tests). Not yet: TCP/TLS echo, STUN, canary DNS, actions, observations API, admin UI beyond token minting. +## Deployment requirements + +**No reverse proxy, no 80/443 — by design.** Traefik/nginx on the same host are fine; this +server never touches their ports, and putting it *behind* them would break two protocol +properties: + +- Clients trust the control plane **only** via the SPKI pin from enrollment (self-signed is + first-class). A proxy terminates TLS with its own rotating ACME cert → pins break. The pin + model exists so no real certificate is ever needed. +- On the data plane, **the observed source address/port/TTL/DSCP *is* the measurement**. Any + proxy or NAT layer (including Docker's) substitutes its own — hence host networking. + +What a target host actually needs: + +| Port | Proto | Purpose | Notes | +|---|---|---|---| +| 8443 | tcp | control plane (pinned HTTPS) | any port — it travels in the enrollment QR + profile | +| 8442 | udp | UDP probe data plane | any port, profile-driven | +| 8441 | tcp | TCP/TLS echo | any port (not yet implemented) | +| 3478 | udp | STUN | keep standard: vanilla RFC 5389 for tool interop; rarely contended | +| 8444 | tcp | admin | loopback-only by design — reach via SSH tunnel | + +All configurable via `ECHOLOT_*_LISTEN`. Plus: + +1. **A public IP on the host** (v4, ideally also v6 — v6 topology issues are half of what + clients want to measure). Behind NAT, plain port-forwards work. +2. **Second IP (optional):** full RFC 5780 NAT-behavior discovery (`stun-5780`) needs an + alternate reply address; without it the profile advertises `stun-basic` and clients degrade + gracefully. +3. **Delegated DNS subzone (optional, later):** the `canary-dns` capability needs port 53 on + some IP + an NS delegation (mind systemd-resolved on 127.0.0.53). Absent → capability simply + not advertised. +4. **Outbound freedom** for connect-back / delayed-echo actions — no extra inbound ports; + generated traffic goes only to the session's observed source. + +Deliberately out of scope here: an echo listener on 443 (to detect port-based egress filtering) +— that genuinely needs 443 and belongs on a dedicated IP, not on a host running a reverse proxy. + ## Run in Docker (config via env) ```sh