fix(fips): P0 uptime fixes — open peer port 5679, allow /blob+/dwn, fix LAN anchor port, un-deaden direct peering, fast-fail budgets

Phase A1 of docs/FIPS-UPTIME-AND-UI-STATE-PLAN.md — the five changes that
made FIPS fall back to Tor even when a FIPS path existed:

- RC0: the fips.d drop-in now opens PEER_PORT 5679 (was 80+8443 only, so
  every hardened node firewalled peers' FIPS dials; 28k drops on .198)
- RC4: /blob/ and /dwn/ added to the peer-path allowlist — mesh file
  sharing and DWN sync were 404 → 100% Tor by construction
- RC2-G2: lan_fips_anchors dials PUBLISHED_UDP_PORT (2121) instead of the
  dead 8668, with a drift-guard test against the rendered daemon config
- RC2-G1: direct LAN peering actually runs now — mDNS TXT advertises the
  FIPS npub, discovery calls set_fips_npub, and the anchor tick hydrates
  npubs from federation storage for peers on older builds
- RC3: FIPS attempt budget is a hard cap (retry no longer doubles it) and
  the 12 hot call sites get explicit fips_timeout fast-fail so Tor keeps
  its full budget (browse-peer, preview, /blob, DWN, node-message,
  rotation notifies)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-07-27 16:42:44 -04:00
co-authored by Claude Fable 5
parent 94b5374f66
commit eb2fc0f37b
12 changed files with 176 additions and 23 deletions
+37 -2
View File
@@ -290,12 +290,12 @@ pub struct ApplyResult {
/// FIPS UDP transport port (matches `transports.udp.bind_addr` in the generated
/// `fips.yaml`). Direct peer links dial this, NOT the HTTP/LAN messaging port.
const FIPS_UDP_PORT: u16 = 8668;
const FIPS_UDP_PORT: u16 = crate::fips::PUBLISHED_UDP_PORT;
/// Build transient seed-anchor entries that dial LAN-discovered federation peers
/// directly over their FIPS UDP transport. For each peer the registry knows both
/// a LAN socket address AND a FIPS npub for, point a `udp` anchor at
/// `<lan-ip>:8668`. This lets co-located federation nodes form a DIRECT FIPS link
/// `<lan-ip>:<FIPS_UDP_PORT>`. This lets co-located federation nodes form a DIRECT FIPS link
/// instead of depending on the global anchor's spanning tree to route between
/// them (the cause of every dial falling back to Tor when the anchor link flaps).
///
@@ -448,4 +448,39 @@ mod tests {
assert_eq!(a.transport, "udp");
assert_eq!(a.label, "");
}
#[test]
fn lan_fips_anchor_port_matches_daemon_bind() {
// Drift guard: direct LAN anchors must dial the UDP port the
// generated fips.yaml actually binds. These were out of sync for
// months (anchors dialed 8668, the daemon bound 2121), making the
// whole direct-peering feature dial a dead port.
let yaml = crate::fips::config::render_config_yaml();
assert!(
yaml.contains(&format!("0.0.0.0:{FIPS_UDP_PORT}")),
"lan_fips_anchors dials :{FIPS_UDP_PORT} but the daemon config binds elsewhere"
);
}
#[test]
fn lan_fips_anchors_builds_direct_entry() {
let peer = crate::transport::PeerRecord {
did: "did:key:zpeer".to_string(),
lan_address: Some("192.168.63.198:5678".to_string()),
fips_npub: Some("npub1peer".to_string()),
..Default::default()
};
let out = lan_fips_anchors(&[peer]);
assert_eq!(out.len(), 1);
assert_eq!(out[0].address, format!("192.168.63.198:{FIPS_UDP_PORT}"));
assert_eq!(out[0].transport, "udp");
// Peers missing either the LAN address or the npub produce nothing.
let no_npub = crate::transport::PeerRecord {
did: "did:key:zother".to_string(),
lan_address: Some("192.168.63.199:5678".to_string()),
..Default::default()
};
assert!(lan_fips_anchors(&[no_npub]).is_empty());
}
}