Files
swarm-house/docs/05-network-security.md
T
eSlider 5f6fd8462c
CI & Release / Verify simulator (push) Skipped
CI & Release / Trivy scan (push) Skipped
CI & Release / Semantic Release (push) Skipped
CI & Release / Verify simulator (pull_request) Failing after 4s
CI & Release / Trivy scan (pull_request) Skipped
CI & Release / Semantic Release (pull_request) Skipped
docs: audit links, glossary T0-T4, readability pass
Extend glossary with storage floors, source of truth, and linkable anchors.
Fix broken links, pose frame drift, rsync/offload wording, and README tone.
Add docs/improvement audit records and live demo links in design journey.
2026-07-10 10:46:59 +01:00

5.6 KiB

05 — Network & security

Zero trust, fully air-gapped, everything provisioned before wheels-up.

Decision: ADR-0005 — WireGuard beneath SSH.

Trust model

  • Nothing joins the swarm at runtime. Every device receives its identity (key pair + certificate) during ground provisioning, signed by the fleet's offline CA. There is no trust-on-first-use, no runtime enrollment endpoint, no exception path.
  • Network position grants nothing. Being inside the mesh does not authorize anything; every connection authenticates mutually.
  • Two layers of cryptography, by design:
    1. WireGuard mesh overlay — every drone holds the public keys of every fleet member (distributed at provisioning). All swarm traffic runs inside these tunnels; a device without a provisioned key cannot even complete a handshake.
    2. Authenticated channels inside the overlay — the bulk-sync and peer-query channel is SSH with ed25519 keys and pinned known_hosts (no first-use prompts, no runtime key acceptance); every permitted operation is a separate key pair bound to a forced command, so a stolen key authorizes exactly one narrow action. Services that speak TLS (MinIO, ground APIs) present per-service certificates from the fleet PKI (mTLS). Compromising the network layer alone still yields nothing readable — and compromising one credential yields one operation, not a shell.
graph TB
    subgraph ground [Ground provisioning, before deployment]
        CA["offline fleet CA"]
        PROV["provisioning station"]
        CA -->|"sign device + service certs"| PROV
    end
    subgraph mesh [In-flight ad-hoc mesh]
        A["drone A<br/>wg key + certs"]
        B["drone B<br/>wg key + certs"]
        C["drone C<br/>wg key + certs"]
        A <-->|"WireGuard tunnel"| B
        B <-->|"WireGuard tunnel"| C
        A <-->|"WireGuard tunnel"| C
    end
    PROV -->|"per-device identity, peer list"| A
    PROV --> B
    PROV --> C

Radio reality

  • Transport is assumed to be ad-hoc Wi-Fi class (2.4/5 GHz), with channel hopping expected. The platform treats the link as lossy, variable, and adversarial — all sync mechanisms already tolerate partitions (04).
  • RSSI is data. Per-peer signal strength is captured into telemetry like any other sensor — it feeds relative-positioning estimates and post-flight link-quality analysis, and it is free.
  • Electromagnetic environment sensing (whatever the radio can observe) is likewise recorded — cheap in flight, valuable in replay.

Why not SSH alone?

SSH and WireGuard solve different problems. SSH is the authorization layer for narrow, point-to-point operations (bulk sync, read-only SQL). WireGuard is the membership and transport encryption layer for everything on the mesh, including traffic SSH cannot carry.

Concern SSH alone WireGuard + SSH (this design)
Pose broadcast (UDP, ~5 Hz, compact frame) Cannot carry subnet broadcast; would need a separate app protocol Encrypted inside the mesh overlay; any peer on the tunnel can receive
Broadcast confidentiality without WG Payloads traverse the radio in cleartext — any receiver in range reads swarm positions Only provisioned fleet members complete a handshake; outsiders see noise
Lossy ad-hoc links TCP head-of-line blocking; sessions stall and reconnect on packet loss UDP transport survives loss and roaming; SSH sessions over WG are more stable than SSH directly on Wi-Fi
Network membership Any host that reaches the port gets an SSH banner — a probe surface Devices without a provisioned key get no handshake response; the port is effectively silent

Rejected alternative: encrypt each broadcast frame in application code with a fleet-wide AEAD key. That reinvents a crypto layer the OS already provides, still leaves TCP head-of-line blocking for peer queries, and does not answer the membership question (who is allowed on the mesh at all).

Keep both layers: WireGuard for who is on the network and whether the wire is readable; SSH forced commands for what a peer is allowed to do once connected (04).

Key lifecycle

Phase Action
Fleet build Offline CA generates device identities; keys injected at provisioning, never transmitted over any network
Mission prep Peer lists and certificates refreshed as part of the fleet release bundle (11)
Rotation Standard cadence between missions; emergency rotation = new fleet release
Loss of a drone Its keys are revoked in the next release; mesh peers drop the revoked identity at the next mission load. Data-at-rest exposure is bounded by NVMe encryption (below)

Data at rest

  • On-board NVMe is encrypted (LUKS) with keys held in the device's secure element / TPM where the hardware provides one; the disk alone is unreadable.
  • The ground warehouse applies standard at-rest encryption plus role-based access; it is the source of truth and the single most valuable asset in the system (every flight ever flown).

Attack surface, deliberately shortened

  • The dev/debug plane does not exist in production builds (02) — not firewalled, absent.
  • No inbound listeners except the authenticated mesh services; no management SSH in production radio profiles (bench access is wired, at the dock).
  • Images are scanned (Trivy) and signed in CI; drones verify signatures against the pinned digests in the fleet release manifest before running anything (11).