feat(map): add cache-first Cesium gateway and AMD egress
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# DC AMD Proxy
|
||||
|
||||
Полный воспроизводимый install/recovery/migration-контракт находится в
|
||||
[`OPERATIONS.md`](./OPERATIONS.md). Этот README фиксирует краткую runtime-модель;
|
||||
операционные изменения должны одновременно обновлять runbook.
|
||||
|
||||
`dc-amd-proxy` is the dedicated, controllable boundary between NODE.DC Map
|
||||
Gateway and the adjacent AMD VPN machine. It is deliberately independent from
|
||||
the historic `proxy-contur` service.
|
||||
|
||||
After pairing it has no direct Cesium egress: every approved Cesium/Bing
|
||||
request is tunnelled through the authenticated AMD connector
|
||||
(`172.22.0.183:8791`). The NAS always addresses this stable LAN endpoint;
|
||||
the AMD host alone owns its changing VPN exit.
|
||||
|
||||
This is a single restricted transport path, not a per-tile relay chain. The
|
||||
NAS keeps a small, bounded pool of HTTP/1.1 TLS tunnels per approved upstream
|
||||
host, so adjacent tile requests reuse the existing `NAS → AMD → VPN` channel.
|
||||
The pool is limited to eight active and four idle sockets per host by default;
|
||||
it cannot become a general-purpose proxy or consume an unbounded amount of the
|
||||
workstation's network resources.
|
||||
|
||||
`/status` exposes only safe operational counters: active/idle/queued sockets
|
||||
per approved origin, the retained peak queue, logical/in-flight/terminal
|
||||
requests, tunnels opened, reused sockets, bounded retries, complete and partial
|
||||
response bytes, separate queue/CONNECT+TLS/TTFB/retry/total timing, body-stream
|
||||
failures, client aborts, and the last short error code. Every accepted egress
|
||||
request is accounted exactly once even when the browser disconnects while it
|
||||
is queued, connecting, following a redirect, waiting for headers, or retrying.
|
||||
The status never contains an Ion token, connector token, full URL, or query
|
||||
parameters.
|
||||
|
||||
An upstream `Authorization` header is retained only across same-origin
|
||||
redirects. A redirect from the Cesium API origin to an assets or Bing origin
|
||||
is followed only after that header is removed, so an API/master bearer cannot
|
||||
cross provider credential boundaries.
|
||||
|
||||
Only an idempotent `GET`/`HEAD` that loses an already reused keep-alive socket
|
||||
is retried, once. The failed reused-socket attempt and the terminal retry
|
||||
attempt are logged separately with numeric transport timings and no URL or
|
||||
credential fields. A response body that makes no progress for 30 seconds is
|
||||
terminated and counted as a stream failure, so a stalled VPN connection cannot
|
||||
occupy one of the eight per-origin sockets forever. These limits are local to
|
||||
Cesium egress and do not modify routing or connectivity of the AMD workstation.
|
||||
|
||||
## Pairing and operational state
|
||||
|
||||
The active service has an explicitly narrow first-pair contract:
|
||||
|
||||
- `POST /api/pair` accepts exactly one connector access token and only from
|
||||
the configured AMD LAN source address;
|
||||
- the AMD operator invokes a supplied local script; it reads the token inside
|
||||
the AMD installation and sends it without printing it or putting it in chat;
|
||||
- the NAS writes the paired value only to its private runtime directory, never
|
||||
to `.env`, SMB inbox, a deploy artifact, browser code, or logs;
|
||||
- the Map Gateway fetch contract (`/proxy/cesium/fetch`) remains private to
|
||||
the NAS LAN address and still requires the runner-synchronised map egress
|
||||
token;
|
||||
- the service follows only the fixed Cesium Ion/Bing host allowlist and cannot
|
||||
fall back to direct NAS Internet egress.
|
||||
|
||||
## Deployment order
|
||||
|
||||
1. Deploy this service and confirm `/healthz` reports `awaiting_pair`.
|
||||
Map Gateway remains on its existing egress during this step.
|
||||
2. On AMD, run the supplied one-time pairing script. It sends the locally-held
|
||||
connector secret directly to the NAS and reports no secret value.
|
||||
3. Verify the private Map Gateway request through this service.
|
||||
4. Apply the separate, minimal Map Gateway switch patch. It changes only its
|
||||
private egress hostname from the historical service to `dc-amd-proxy`.
|
||||
|
||||
The initial 001 deployment was intentionally inert. It is superseded by this
|
||||
active configuration; it did not alter NAS routing, the NAS VPN/Tailscale
|
||||
configuration, or the Windows workstation's VPN configuration.
|
||||
|
||||
## Why host networking is narrow here
|
||||
|
||||
Synology's Docker published-port proxy replaces the caller address before it
|
||||
reaches a bridged container. That makes a strict one-time AMD source-address
|
||||
check impossible. This service therefore uses the host network namespace but
|
||||
binds its own HTTP listener only to `172.22.0.222:8790`; it is not bound to all
|
||||
NAS interfaces. No host route, VPN, DNS, Tailscale setting or firewall rule is
|
||||
changed. The forwarding code still has one hard-coded outbound path only:
|
||||
the authenticated AMD connector.
|
||||
Reference in New Issue
Block a user