mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-22 07:48:26 +00:00
Restructures /docs/ by reader purpose (tutorials, how-to, reference, design), adds the new-user-progression and operator-recipe content the prior layout lacked, runs an accuracy pass against current source across the pre-existing design docs, and rewrites the gateway feature-set documentation end-to-end around its actual operational profile (a niche feature designed for systems already serving DHCP/DNS to a LAN, with two independent halves — outbound LAN→mesh, inbound mesh→LAN — sharing one nftables table, one binary, and one control socket). Top-level README and getting-started rewritten around two equally-weighted deployment modes (overlay on existing IP networks; ground-up over non-IP transports). ## Additions - 11 new tutorials in docs/tutorials/: an 8-step new-user progression from single-daemon test-mesh peering through to a ground-up two-device mesh, an IPv6-adapter side-trip walkthrough, an Advanced Tutorials index, and a hand-held OpenWrt walk-through for fips-gateway deployment that exercises both halves of the feature. - 12 new how-tos in docs/how-to/: firewall activation, Nostr discovery (resolve / advertise / open across five scenarios), Tor onion (directory + control_port modes), UDP buffer tuning, unprivileged-user setup, persistent identity, host aliases, Bluetooth LE peering, MTU diagnostics, manual Linux-host gateway deployment (covers both halves), gateway troubleshooting (organised by half), and a section index. - 9 new reference docs in docs/reference/: configuration, wire formats, control-socket protocol, four CLI references (fips, fipsctl, fipstop, fips-gateway), security posture matrix, and Nostr events catalog. Configuration and wire-formats are renamed-and-extended from prior design/ versions; the other seven are net-new. - 6 new design docs: fips-concepts, fips-architecture, and fips-prior-work split out of the deleted fips-intro.md; consolidated fips-mmp and fips-mtu aggregations; and a new generic port-advertisement-and-nat-traversal doc (Nostr-signaled port advertisement plus UDP NAT-traversal protocol, FIPS as an example implementation, suitable for eventual NIP submission). - Top-level docs/getting-started.md walking through the binary-installer-only Install story. - packaging/common/hosts pre-populated with the eight public test-mesh nodes so shortnames resolve out of the box on every fresh install. ## Changes - 23 wire-format diagrams relocated to reference/diagrams/ alongside the wire-formats move. - 4 design diagrams corrected against source code (fips-protocol-stack, fips-identity-derivation, fips-coordinate-discovery, fips-routing-decision). - 10 pre-existing design docs reconciled with current source. Numeric corrections: stale link-MMP report bounds (now [1s, 5s] with 200 ms cold-start floor); UDP default MTU (now 1280, IPv6 minimum); node_addr formula (SHA-256(pubkey)[..16]); Noise patterns (IK at link, XK at session); peer-ACL semantics (strict allowlist requires ALL in peers.deny); daemon DNS upstream ([::1]:5354); on-the-wire bloom-filter size (1,071 bytes); obsolete Cargo-feature references (PR #79 dropped them) removed. - Transport framing tightened across the docs: TCP is for UDP-filtered networks (not NAT traversal); Tor is a deployment mode (not failover); WebSocket dropped (not a shipped FIPS transport); WiFi promoted to Implemented via Ethernet in infrastructure mode; classic-Bluetooth row removed (BLE is the only Bluetooth-mode transport). - docs/design/fips-gateway.md rewritten end-to-end to lead with the niche-feature framing and the two-halves structure. Title moved from "FIPS Outbound LAN Gateway" to "FIPS Gateway"; architecture section describes the common machinery (the fips-gateway service, the nftables table, the control socket) before splitting into separate "Outbound Half" and "Inbound Half" sections of equal weight; security considerations split per-half; no Future Work section (speculative directions live in the project tracker, not in protocol design docs). Inbound port forwarding is a first-class half rather than a buried "Implemented Extensions" subsection. - Gateway terminology unified across all gateway docs as a separate Linux service running alongside the fips daemon (its own systemd unit / OpenWrt init script). Container- pattern terms (sidecar) are reserved for the Docker/Kubernetes sidecar deployment examples — the testing/sidecar/ tree, examples/k8s-sidecar/, examples/sidecar-nostr-relay/, examples/wireguard-sidecar-macos/, and the related CHANGELOG / top-level README entries — where the term carries its standard container meaning. - Net-new design body content: rekey section in fips-mesh-layer (Noise IK msg1/msg2 over the established link, K-bit cutover, drain window, smaller-NodeAddr-wins tie-breaker on dual-init); Mesh Size Estimation and Antipoison FPR Cap sections in fips-bloom-filters; Mesh-Interface Query Filter subsection in fips-ipv6-adapter; failure-suppression knobs and clock- skew tolerance in fips-nostr-discovery; loop-rejection and mid-chain ancestor swap added to spanning-tree propagation / stability rules; Priority Chain in fips-mesh-operation renumbered to match the routing-decision diagram. - Top-level README: dropped the stale nostr-discovery cargo-feature parenthetical. docs/README.md and the four section READMEs (tutorials, how-to, reference, design) refreshed for the new structure; index rows reflect both halves of the gateway feature and the new fips-gateway CLI reference. - Cargo.toml [package.metadata.deb] assets path updated for the fips-security.md move; .gitignore /reference/ rule anchored to repo root so docs/reference/ is trackable. - packaging/openwrt-ipk/files/etc/fips/fips.yaml configuration-doc URL updated to the new docs/reference/configuration.md location. ## Deletions - docs/design/fips-intro.md (split into the three new intro design docs). - docs/design/document-relationships.svg (orphan, no longer referenced). - docs/proposals/ tree removed; the only proposal it contained (the Nostr UDP hole-punch protocol) was rewritten as the new generic design/port-advertisement-and-nat-traversal.md.
513 lines
23 KiB
Markdown
513 lines
23 KiB
Markdown
# FIPS Session Protocol (FSP)
|
|
|
|
The FIPS Session Protocol is the topmost layer of the FIPS protocol stack.
|
|
It sits above the FIPS Mesh Protocol (FMP) and below applications (native
|
|
FIPS API or IPv6 adapter). FSP provides end-to-end authenticated, encrypted
|
|
datagram delivery between any two FIPS nodes, regardless of how many
|
|
intermediate hops separate them.
|
|
|
|
## Role
|
|
|
|
FSP manages end-to-end communication sessions between FIPS nodes identified by
|
|
their public keys (npubs). Each session provides:
|
|
|
|
- **End-to-end encryption**: Payload confidentiality independent of how many
|
|
intermediate nodes handle the traffic
|
|
- **Mutual authentication**: Both parties prove they control the private key
|
|
for their claimed identity
|
|
- **Replay protection**: Counter-based nonces with sliding window, tolerant of
|
|
UDP packet loss and reordering
|
|
- **Transport independence**: Sessions survive transport changes, route
|
|
changes, and address changes — they are bound to npub identities, not to
|
|
transport paths
|
|
|
|
FSP is a datagram session protocol. It provides encrypted datagrams, not
|
|
reliable streams. There is no FIPS equivalent of TCP; if applications need
|
|
reliability, ordering, or flow control, they provide it themselves (typically
|
|
by running TCP over the FIPS IPv6 adapter).
|
|
|
|
## Services Provided to Applications
|
|
|
|
Applications access the FIPS mesh through two interfaces, both served by FSP:
|
|
|
|
### Native FIPS API
|
|
|
|
Applications address destinations directly by npub or public key. The FIPS
|
|
stack resolves the destination's node_addr, establishes or reuses a session,
|
|
encrypts the payload, and routes through FMP. No DNS involvement.
|
|
|
|
### IPv6 Adapter
|
|
|
|
Unmodified IPv6 applications use a TUN device with `fd00::/8` routing. A local
|
|
DNS service maps npub → IPv6 address and primes the identity cache. Packets
|
|
arriving at the TUN are translated to FIPS datagrams and routed through FSP.
|
|
|
|
See [fips-ipv6-adapter.md](fips-ipv6-adapter.md) for the IPv6 adaptation
|
|
layer.
|
|
|
|
### Port-Based Service Dispatch
|
|
|
|
FSP DataPackets carry a 4-byte port header (source and destination port) inside
|
|
the AEAD envelope, enabling multiple services to share a single session. The
|
|
IPv6 adapter runs on port 256; the native FIPS API and future services
|
|
(gateways, application protocols) register on other ports. Port dispatch is
|
|
internal to the FSP layer — services see only their payload, not the port
|
|
header.
|
|
|
|
### What Applications Get
|
|
|
|
- **Authenticated datagram delivery**: Each datagram is encrypted and
|
|
authenticated with session keys bound to both parties' npubs
|
|
- **Session transparency**: Sessions are established on demand and maintained
|
|
automatically. Applications send packets; FSP handles session setup,
|
|
encryption, and teardown.
|
|
- **Endpoint identity**: Applications address destinations by npub. The FIPS
|
|
address is the public key.
|
|
|
|
### What Applications Do Not Get
|
|
|
|
- **Reliability**: Datagrams may be lost, duplicated, or delivered out of
|
|
order. FSP provides no retransmission or ordering.
|
|
- **Path MTU discovery**: FSP does not signal MTU to applications. The IPv6
|
|
adapter handles MTU enforcement via ICMP Packet Too Big and TCP MSS
|
|
clamping.
|
|
- **Congestion control**: FSP does not throttle traffic. Applications running
|
|
TCP over IPv6 get TCP's congestion control; native API applications must
|
|
manage their own sending rate.
|
|
|
|
## Services Required from FMP
|
|
|
|
FSP treats FMP as a black box providing three services. FSP knows nothing about
|
|
transports, transport addresses, links, peers, spanning trees, coordinates,
|
|
bloom filters, hop counts, or network topology.
|
|
|
|
### SessionDatagram Forwarding
|
|
|
|
FMP accepts a SessionDatagram (source node_addr, destination node_addr, TTL,
|
|
path MTU, payload) and delivers it best-effort toward the destination. Delivery
|
|
may traverse multiple hops, each with independent link encryption.
|
|
|
|
### Error Signaling
|
|
|
|
FMP signals routing failures asynchronously:
|
|
|
|
- **CoordsRequired**: A transit node lacks the destination's tree coordinates.
|
|
FSP responds by sending a standalone CoordsWarmup (0x14) message
|
|
(rate-limited), re-initiating discovery, and resetting the coordinate warmup
|
|
counter.
|
|
- **PathBroken**: Greedy routing reached a dead end. FSP responds by sending
|
|
a standalone CoordsWarmup (rate-limited), re-discovering the destination's
|
|
current coordinates, and resetting the warmup counter.
|
|
- **MtuExceeded**: A transit node cannot forward a SessionDatagram because
|
|
the packet exceeds the next-hop link MTU; FSP adjusts its
|
|
session-layer path MTU estimate from the reported bottleneck. See
|
|
[fips-mtu.md](fips-mtu.md) for the full forward/reverse MTU model.
|
|
|
|
All three signals are generated by transit nodes (not the destination) and
|
|
travel back to the source inside a new SessionDatagram. They are plaintext
|
|
(not end-to-end encrypted) because transit nodes have no session with the
|
|
source.
|
|
|
|
### Local Delivery
|
|
|
|
When a SessionDatagram arrives with a destination node_addr matching the local
|
|
node, FMP delivers it to FSP for session-layer processing.
|
|
|
|
## Session Lifecycle
|
|
|
|
### Session Establishment
|
|
|
|
Sessions are established on demand when the first datagram needs to be sent to
|
|
a destination with no existing session.
|
|
|
|
FSP uses Noise XK for session key agreement (Noise Protocol Framework;
|
|
Perrin 2018). The initiator knows the destination's npub (required for
|
|
XK's pre-message `s` token); the responder learns the initiator's
|
|
identity from msg3 (not msg1, unlike IK at the link layer). This
|
|
provides stronger initiator identity hiding — the initiator's static
|
|
key is encrypted under the established shared secret rather than under
|
|
only the responder's static key.
|
|
|
|
The handshake is a three-message flow carried in SessionSetup, SessionAck,
|
|
and SessionMsg3:
|
|
|
|
1. **Initiator** sends SessionSetup containing Noise XK msg1 (ephemeral key
|
|
only) and both parties' tree coordinates
|
|
2. **Responder** processes msg1, sends SessionAck containing Noise XK msg2
|
|
(ephemeral key + encrypted epoch) and both parties' tree coordinates.
|
|
The responder transitions to AwaitingMsg3 state.
|
|
3. **Initiator** processes msg2, sends SessionMsg3 containing the encrypted
|
|
static key and encrypted epoch. Both parties derive identical symmetric
|
|
session keys and the session is established.
|
|
|
|
Each side's epoch (an 8-byte random value generated at startup) is
|
|
exchanged encrypted in msg2 and msg3. On subsequent handshakes, an epoch
|
|
mismatch indicates the peer has restarted, triggering session
|
|
re-establishment — similar to IKEv2's INITIAL_CONTACT notification for
|
|
peer restart detection (RFC 7296 §2.4).
|
|
|
|
Packets that trigger session establishment are queued (with bounded buffer)
|
|
and transmitted after the session is established.
|
|
|
|
### Self-Bootstrapping
|
|
|
|
SessionSetup is self-bootstrapping for routing. It carries the source's and
|
|
destination's tree coordinates in the clear (not inside the Noise payload).
|
|
As the message transits intermediate nodes, each node caches these coordinates,
|
|
warming the path for subsequent data packets that carry only addresses (no
|
|
coordinates).
|
|
|
|
SessionAck carries both the responder's and initiator's coordinates back
|
|
along the reverse path, warming caches in the other direction. This ensures
|
|
return-path transit nodes can route even when the reverse path diverges from
|
|
the forward path (e.g., after tree reconvergence).
|
|
|
|
### Simultaneous Initiation
|
|
|
|
When both nodes attempt to establish a session simultaneously ("crossing
|
|
hellos"), a deterministic tie-breaker resolves the conflict, mirroring
|
|
IKEv2's simultaneous initiation resolution (RFC 7296 §2.8):
|
|
|
|
- If `local_node_addr < remote_node_addr`: Continue as initiator, ignore
|
|
incoming setup
|
|
- If `local_node_addr > remote_node_addr`: Abort own initiation, switch to
|
|
responder role
|
|
|
|
This lowest-address-wins approach ensures exactly one handshake completes.
|
|
|
|
### Data Transfer
|
|
|
|
Once established, sessions carry encrypted data using the FSP pipeline. Each
|
|
encrypted message includes:
|
|
|
|
- A 12-byte cleartext header (used as AEAD AAD) containing the counter and
|
|
flags (including the CP flag for coordinate cache warming)
|
|
- Optional cleartext coordinates when the CP flag is set
|
|
- An AEAD-encrypted payload containing a 6-byte inner header (session-relative
|
|
timestamp, message type, inner flags) followed by DataPacket content: a 4-byte
|
|
port header (src_port, dst_port) and the service payload. The receiver
|
|
dispatches by destination port to the registered service handler.
|
|
|
|
### Session Idle Timeout
|
|
|
|
Sessions that see no traffic for a configurable duration (default 90s) are
|
|
torn down. When traffic resumes, a new session is established automatically.
|
|
|
|
Only DataPacket (message type 0x10) send/receive and session establishment
|
|
reset `last_activity`. MMP traffic — SenderReport, ReceiverReport, and
|
|
PathMtuNotification — does not reset the idle timer. This means a session
|
|
carrying only MMP reports and no application data will still tear down after
|
|
`node.session.idle_timeout_secs`. MMP reports continue flowing until the
|
|
session is torn down, providing final measurement data for the teardown log.
|
|
|
|
The idle timeout is deliberately shorter than the coordinate cache TTL (300s).
|
|
This ordering ensures that when traffic stops and the session tears down, the
|
|
transit node coordinate caches are still warm when a new session is established.
|
|
The fresh SessionSetup re-warms the caches, maintaining routing continuity.
|
|
|
|
### Session Independence from Transport
|
|
|
|
Sessions exist above the routing layer and are bound to npub identities, not
|
|
transport addresses or routing paths — following WireGuard's approach
|
|
(Donenfeld 2017) of binding cryptographic sessions to identity keys rather
|
|
than network addresses. A session survives:
|
|
|
|
- Transport failover (UDP → Ethernet → back to UDP)
|
|
- Route changes (different intermediate hops)
|
|
- Transport address changes (IP address or port changes)
|
|
- Topology changes (direct peer becomes multi-hop or vice versa)
|
|
|
|
## End-to-End Encryption
|
|
|
|
### Noise XK Pattern
|
|
|
|
FSP uses Noise XK for session encryption, distinct from the Noise IK
|
|
pattern used at the link layer. The full Noise descriptor is
|
|
`Noise_XK_secp256k1_ChaChaPoly_SHA256`.
|
|
|
|
The XK pattern (pre-message: `← s`):
|
|
|
|
- **msg1** (`→ e, es`): Initiator sends ephemeral key only. The initiator's
|
|
static identity is not revealed in this message.
|
|
- **msg2** (`← e, ee`): Responder sends ephemeral key and encrypted epoch.
|
|
- **msg3** (`→ s, se`): Initiator sends encrypted static key and encrypted
|
|
epoch. Both parties now share identical session keys.
|
|
|
|
After the handshake, Noise produces two directional symmetric keys
|
|
(`send_key`, `recv_key`) used with ChaCha20-Poly1305 for all subsequent data.
|
|
|
|
The XK pattern requires the initiator to know the responder's static key
|
|
in advance (the `← s` pre-message), which is satisfied by the discovery
|
|
or DNS lookup that precedes session establishment. In exchange, XK
|
|
provides stronger initiator identity protection than IK — the initiator's
|
|
static key is encrypted under the full shared secret (after three DH
|
|
operations) rather than under only the responder's static key.
|
|
|
|
### Cryptographic Primitives
|
|
|
|
FSP uses ChaCha20-Poly1305 with secp256k1 ECDH; see
|
|
[../reference/security.md](../reference/security.md) for the full
|
|
primitive table shared with the link layer.
|
|
|
|
### secp256k1 Parity Normalization
|
|
|
|
Nostr npubs encode x-only public keys (32 bytes, no y-coordinate parity). The
|
|
Noise XK pre-message mixes the responder's static key as a 33-byte compressed
|
|
key, and the default secp256k1 ECDH hash includes a parity-dependent version
|
|
byte.
|
|
|
|
Both operations are normalized to be parity-independent: the pre-message hash
|
|
uses even parity (`0x02` prefix), and ECDH hashes only the x-coordinate of the
|
|
result point. This ensures handshakes succeed regardless of the responder's
|
|
actual key parity.
|
|
|
|
### Privacy Note
|
|
|
|
Noise XK provides stronger initiator identity protection than IK. In XK, the
|
|
initiator's static key is encrypted in msg3 under the full shared secret
|
|
(derived from three DH operations), so an attacker who compromises only the
|
|
responder's nsec cannot decrypt the initiator's identity from captured
|
|
handshake messages (they would also need the responder's ephemeral key).
|
|
This is the primary reason FSP uses XK rather than IK — session-layer
|
|
traffic traverses untrusted intermediate nodes, making initiator identity
|
|
protection more valuable than at the link layer.
|
|
|
|
### Data Packet Authentication
|
|
|
|
FSP uses AEAD authentication only — no per-packet signatures. The Noise
|
|
handshake binds session keys to both parties' static keys, so only holders of
|
|
the corresponding nsecs can derive the session keys. This provides implicit
|
|
authentication for every packet, matching WireGuard and Lightning's approach.
|
|
|
|
### Forward Secrecy
|
|
|
|
Ephemeral keys in the Noise handshake provide forward secrecy — a standard
|
|
property of Noise handshake patterns that include ephemeral key exchange.
|
|
Compromise of static keys (nsec) does not reveal past session keys, because
|
|
session keys are derived in part from ephemeral-ephemeral DH (`ee`), and
|
|
ephemeral keys are discarded after the handshake.
|
|
|
|
## Replay Protection
|
|
|
|
FSP uses explicit 8-byte counters on the wire for replay protection, adapted
|
|
from the DTLS anti-replay mechanism (Rescorla & Modadugu, RFC 6347). Each side
|
|
maintains a monotonically increasing send counter, included in the 12-byte
|
|
cleartext header of every encrypted message. The receiver maintains a sliding
|
|
window (2048-entry bitmap) tracking which counters have been seen.
|
|
|
|
This design is critical for operation over unreliable transports. Under UDP
|
|
packet loss or reordering, implicit nonce counters (where the receiver
|
|
increments on each decrypt attempt) would desynchronize permanently — a failed
|
|
`decrypt()` increments the nonce, and the desync grows with each lost packet.
|
|
Explicit counters with a sliding bitmap window — the standard DTLS approach —
|
|
allow the receiver to decrypt any packet independently, regardless of what
|
|
packets were lost or reordered.
|
|
|
|
The same `ReplayWindow` and `decrypt_with_replay_check()` implementation is
|
|
used at both the link and session layers.
|
|
|
|
## Hybrid Coordinate Warmup Strategy
|
|
|
|
Session establishment (SessionSetup/SessionAck) warms transit node coordinate
|
|
caches along the path. But coordinate caches have a finite TTL (default 300s),
|
|
and entries may be evicted under memory pressure. When a transit node's cache
|
|
entry expires, it cannot forward data packets (which carry only addresses, not
|
|
coordinates) and sends a CoordsRequired error.
|
|
|
|
FSP uses a hybrid warmup strategy combining proactive piggybacking with
|
|
reactive standalone messages to keep transit caches populated (Yggdrasil
|
|
uses a similar approach of embedding coordinates in session traffic to
|
|
warm transit node caches):
|
|
|
|
### Proactive Warmup Phase
|
|
|
|
After session establishment, the first N data packets (configurable, default 5)
|
|
per session attempt to piggyback source and destination coordinates via the CP
|
|
flag in the FSP common prefix. The coordinates appear in cleartext between the
|
|
12-byte header and the ciphertext, allowing transit nodes to cache them without
|
|
decryption.
|
|
|
|
If piggybacking coordinates would cause the total packet to exceed the
|
|
transport MTU, the source sends a standalone **CoordsWarmup** message (0x14)
|
|
first, followed by the data packet without the CP flag. This ensures transit
|
|
caches are warmed even when data packets are near the MTU limit.
|
|
|
|
### CoordsWarmup Message (0x14)
|
|
|
|
CoordsWarmup is an encrypted FSP message (phase 0x0) with the CP flag set and
|
|
inner msg_type 0x14. It carries cleartext source and destination coordinates
|
|
between the FSP header and the AEAD ciphertext, using the same format as
|
|
CP-flagged data packets. The inner body is empty — the message exists solely
|
|
to deliver coordinates to transit nodes.
|
|
|
|
Transit nodes extract coordinates via the existing `try_warm_coord_cache()`
|
|
code path with zero changes to the transit forwarding logic. CoordsWarmup is
|
|
indistinguishable from any other CP-flagged message at the transit layer.
|
|
|
|
On the wire, a CoordsWarmup message consists of the standard 12-byte FSP
|
|
header (used as AEAD AAD) with ver=0, phase=0, flags=CP, followed by
|
|
cleartext source and destination coordinates (same encoding as any
|
|
CP-flagged packet), followed by 22 bytes of AEAD ciphertext (6-byte inner
|
|
header and 16-byte Poly1305 tag). The total FSP payload is 12 bytes of
|
|
header, the coordinate data, and 22 bytes of ciphertext.
|
|
|
|
### Steady State
|
|
|
|
After the warmup count is reached, FSP clears the CP flag and sends minimal
|
|
data packets (12-byte header + ciphertext). Transit nodes serve from their
|
|
coordinate caches.
|
|
|
|
### Reactive Re-Warm
|
|
|
|
When FSP receives a CoordsRequired or PathBroken signal:
|
|
|
|
1. A standalone CoordsWarmup message is sent immediately to re-warm transit
|
|
caches, rate-limited at one per destination per configurable interval
|
|
(default 2000ms, `node.session.coords_response_interval_ms`)
|
|
2. The warmup counter resets — subsequent data packets piggyback coordinates
|
|
again when possible (or send additional CoordsWarmup messages when the
|
|
data packet would exceed the MTU)
|
|
3. A new LookupRequest may be initiated to rediscover the destination's
|
|
current coordinates (always for PathBroken; optionally for CoordsRequired)
|
|
4. When the LookupResponse arrives for an established session, the warmup
|
|
counter resets again (handling the timing gap where warmup packets might
|
|
fire before transit caches are repopulated by discovery)
|
|
|
|
The source-side rate limiting prevents amplification: at most one standalone
|
|
CoordsWarmup response per destination per `coords_response_interval_ms`
|
|
(default 2s). This is independent of the transit-node rate limiting on error
|
|
signal generation (100ms per destination).
|
|
|
|
### Warmup State Machine
|
|
|
|

|
|
|
|
## Identity Cache
|
|
|
|
The IPv6 adapter requires an identity cache to map `fd00::/8` addresses
|
|
back to `(NodeAddr, PublicKey)` for routing; see
|
|
[fips-ipv6-adapter.md](fips-ipv6-adapter.md#identity-cache) for the
|
|
cache rationale, eviction policy, and population mechanics.
|
|
|
|
## Coordinate Cache
|
|
|
|
The coordinate cache maps `NodeAddr → TreeCoordinate` and is the critical
|
|
data structure that enables efficient multi-hop routing. Without cached
|
|
coordinates for a destination, FMP cannot make forwarding decisions and must
|
|
either fall back to bloom-filter-only routing or signal CoordsRequired.
|
|
|
|
### Unified Cache
|
|
|
|
The coordinate cache is a single unified cache (merged from previously
|
|
separate coord_cache and route_cache). All coordinate sources — SessionSetup
|
|
transit, CP-flagged data packets, LookupResponse — write to the same cache.
|
|
|
|
### Eviction Policy
|
|
|
|
- **TTL-based expiration**: Entries expire after a configurable duration
|
|
(default 300s)
|
|
- **Refresh on use**: Active routing through a cache entry resets its TTL,
|
|
keeping hot entries alive
|
|
- **LRU eviction**: When the cache is full, least recently used entries are
|
|
evicted first
|
|
- **Flush on parent change**: When the local node's tree parent changes, the
|
|
entire coordinate cache is flushed. Tree parent changes mean the node's own
|
|
coordinates have changed, making cached coordinates for other nodes
|
|
potentially stale for routing purposes.
|
|
|
|
### Timer Ordering
|
|
|
|
Cache and session timers are ordered so that idle sessions tear down before
|
|
transit caches expire:
|
|
|
|
| Timer | Default | Purpose |
|
|
| ----- | ------- | ------- |
|
|
| Session idle timeout | 90s | Tear down unused sessions |
|
|
| Coordinate cache TTL | 300s | Expire stale coordinates |
|
|
| DNS TTL | 300s | Expire DNS resolutions |
|
|
|
|
When traffic stops: the session tears down at 90s. When traffic resumes: DNS
|
|
re-resolves the identity, a fresh SessionSetup carries coordinates, and transit
|
|
node caches (still within their 300s TTL) are re-warmed.
|
|
|
|
## Session-Layer MMP
|
|
|
|
FSP runs an MMP instance per established session for end-to-end metrics
|
|
independent of hop count. Reports are encrypted and forwarded through
|
|
every transit link, so bandwidth cost is proportional to path length;
|
|
the session-layer report intervals are correspondingly higher than the
|
|
link-layer intervals (clamped to `[500ms, 10s]` vs. `[1s, 5s]`).
|
|
|
|
The session-layer instance shares its algorithms (SRTT, jitter, loss,
|
|
ETX) and report wire format with link-layer MMP. The differences —
|
|
configuration namespace (`node.session_mmp.*`), routing scope,
|
|
send-failure backoff, idle-timeout interaction, and the
|
|
PathMtuNotification mechanism — are documented in the unified MMP
|
|
treatment at [fips-mmp.md](fips-mmp.md). For the end-to-end path-MTU
|
|
echo specifically, see [fips-mtu.md](fips-mtu.md). Reports and
|
|
PathMtuNotification do **not** reset the session idle timer, so a
|
|
session carrying only MMP traffic still tears down at the configured
|
|
idle threshold.
|
|
|
|
### MtuExceeded Handling
|
|
|
|
When FMP signals MtuExceeded (a transit node could not forward a
|
|
SessionDatagram because it exceeded the next-hop link MTU), FSP uses
|
|
the reported bottleneck MTU to adjust its session-layer path MTU
|
|
estimate immediately. See [fips-mtu.md](fips-mtu.md) for the full
|
|
reactive PMTUD mechanism.
|
|
|
|
## Implementation Status
|
|
|
|
| Feature | Status |
|
|
| ------- | ------ |
|
|
| Session establishment (Noise XK) | **Implemented** |
|
|
| Peer restart detection (epoch exchange) | **Implemented** |
|
|
| MtuExceeded handling | **Implemented** |
|
|
| End-to-end encryption (ChaCha20-Poly1305) | **Implemented** |
|
|
| Explicit counter replay protection | **Implemented** |
|
|
| Hybrid coordinate warmup (CP + CoordsWarmup) | **Implemented** |
|
|
| FSP wire format (prefix, AAD, inner header) | **Implemented** |
|
|
| Session-layer MMP (with send-failure backoff) | **Implemented** |
|
|
| Identity cache (LRU-only) | **Implemented** |
|
|
| Coordinate cache (unified, TTL + refresh) | **Implemented** |
|
|
| Session idle timeout | **Implemented** |
|
|
| CoordsRequired handling | **Implemented** |
|
|
| PathBroken handling | **Implemented** |
|
|
| Simultaneous initiation tie-breaker | **Implemented** |
|
|
| Flush coord cache on parent change | **Implemented** |
|
|
| Rekey | **Implemented** |
|
|
| Port-based service multiplexing | **Implemented** |
|
|
| IPv6 header compression (shim on port 256) | **Implemented** |
|
|
| Path MTU tracking (FMP SessionDatagram field) | **Implemented** |
|
|
| Path MTU notification (end-to-end echo) | **Implemented** |
|
|
|
|
## References
|
|
|
|
### FIPS Internal Documentation
|
|
|
|
- [fips-concepts.md](fips-concepts.md) — Protocol overview
|
|
- [fips-architecture.md](fips-architecture.md) — Layer architecture and
|
|
identity model
|
|
- [fips-mesh-layer.md](fips-mesh-layer.md) — FMP specification (below FSP)
|
|
- [fips-ipv6-adapter.md](fips-ipv6-adapter.md) — IPv6 adaptation layer
|
|
(above FSP)
|
|
- [fips-mesh-operation.md](fips-mesh-operation.md) — Routing, discovery,
|
|
and error recovery
|
|
- [fips-mmp.md](fips-mmp.md) — Metrics Measurement Protocol (link + session)
|
|
- [fips-mtu.md](fips-mtu.md) — Path MTU model (PathMtuNotification,
|
|
MtuExceeded, hysteresis)
|
|
- [fips-prior-work.md](fips-prior-work.md) — Noise XK, WireGuard,
|
|
DTLS replay window, IKEv2 simultaneous initiation, hybrid coordinate
|
|
warmup citations
|
|
- [../reference/wire-formats.md](../reference/wire-formats.md) — Wire
|
|
format reference for all session message types
|
|
- [../reference/security.md](../reference/security.md) — Cryptographic
|
|
primitives and rekey defaults
|
|
|
|
### External References
|
|
|
|
- Mogul, J., Deering, S. [RFC 1191](https://datatracker.ietf.org/doc/html/rfc1191):
|
|
"Path MTU Discovery". 1990. *End-to-end path MTU discovery; FSP adapts this for
|
|
overlay networks using transit-node min() propagation.*
|