Federation: screen peer addresses before admitting a relay to the network #58

Closed
opened 2026-09-06 15:46:23 +00:00 by paulhitt · 2 comments
paulhitt commented 2026-09-06 15:46:23 +00:00 (Migrated from gitlab.com)

What this is for

Keep hostile operators — state actors, known abuse networks — from attaching a
relay to our federated network. Anyone may still run an isolated relay;
that is the product working as intended and must not change.

What already exists (read this before building anything)

Federation is not open by default, so the door this issue guards is not
currently standing open:

  • FN_FEDERATION defaults to closed (Config.swift:316). Modes are
    closed / allowlist / open.
  • The fleet and the docs both run allowlist — the operator names every
    peer, and an unnamed one is refused with peerNotAllowed.
  • Federation.isFetchableHost already rejects peers named by IP literal, which
    is the SSRF-shaped version of this problem.

So a hostile relay cannot join today without an operator explicitly adding it.
What is missing is help making that decision, and a guard for open.

Proposed work

1. A peer reputation check at allowlist-admission time (the useful half).
When an operator adds a peer, resolve it and screen the resulting addresses
before the peer goes live — not silently, but as a warning the operator has to
acknowledge. Sources worth combining:

  • ASN / org lookup — flag hosting providers known for abuse, and government
    ranges where those are published
  • Existing blocklists we already pay attention to (CrowdSec is deployed on the
    box; its decisions are a free signal)
  • Country of registration, cross-checked against the peer's stated identity

2. Screening on open mode, if open is ever recommended. Under open the
peer name arrives in a header from anyone. The existing note in
Federation.swift already says DNS resolution and pinning must land before
open is recommended to anyone; address screening belongs in the same pass.

3. Log and expose, do not silently drop. A refused peer should be visible to
the operator with the reason. Silent refusal makes a misclassification
indistinguishable from a network fault.

Honest limits — worth stating in the code, not just here

⚠️ This is whack-a-mole and should be built as such. IP addresses are cheap,
rotatable, and rentable by anyone; an adversary who wants a relay on the network
will get an address that screens clean. That is a reason to build it as an
advisory signal supporting a human allowlist decision, not as the gate.

🔴 The gate is and should remain cryptographic: the allowlist plus the
pinned federation key. Those are the things an adversary cannot rent. If IP
screening ever becomes the thing standing between a hostile relay and the
network, the design has regressed.

⚠️ False positives land on legitimate self-hosters. Someone running a relay
from a VPS in a flagged range is the common case, not the adversary. There must
be an override, and the override must be easy, or this quietly makes
self-hosting worse — which is the opposite of the point.

⚠️ "Government IP ranges" are not reliably enumerable. Published allocations
cover a small fraction; most state activity comes from commercial hosting like
everyone else's. Treat the claim in any data source as low-confidence.

Definition of done

  • Screening runs at peer-admission time and surfaces a reason to the operator
  • An operator can override any verdict, in one documented step
  • Refusals are logged with the reason, never silent
  • Isolated self-hosted relays are unaffected — covered by a test
  • allowlist remains the gate; screening is advisory and documented as such
## What this is for Keep hostile operators — state actors, known abuse networks — from attaching a relay to **our** federated network. Anyone may still run an **isolated** relay; that is the product working as intended and must not change. ## What already exists (read this before building anything) Federation is **not open by default**, so the door this issue guards is not currently standing open: - `FN_FEDERATION` defaults to **`closed`** (`Config.swift:316`). Modes are `closed` / `allowlist` / `open`. - The fleet and the docs both run **`allowlist`** — the operator names every peer, and an unnamed one is refused with `peerNotAllowed`. - `Federation.isFetchableHost` already rejects peers named by IP literal, which is the SSRF-shaped version of this problem. So a hostile relay cannot join today without an operator explicitly adding it. **What is missing is help making that decision, and a guard for `open`.** ## Proposed work **1. A peer reputation check at allowlist-admission time (the useful half).** When an operator adds a peer, resolve it and screen the resulting addresses before the peer goes live — not silently, but as a warning the operator has to acknowledge. Sources worth combining: - ASN / org lookup — flag hosting providers known for abuse, and government ranges where those are published - Existing blocklists we already pay attention to (CrowdSec is deployed on the box; its decisions are a free signal) - Country of registration, cross-checked against the peer's stated identity **2. Screening on `open` mode, if `open` is ever recommended.** Under `open` the peer name arrives in a header from anyone. The existing note in `Federation.swift` already says DNS resolution and pinning must land before `open` is recommended to anyone; address screening belongs in the same pass. **3. Log and expose, do not silently drop.** A refused peer should be visible to the operator with the reason. Silent refusal makes a misclassification indistinguishable from a network fault. ## Honest limits — worth stating in the code, not just here ⚠️ **This is whack-a-mole and should be built as such.** IP addresses are cheap, rotatable, and rentable by anyone; an adversary who wants a relay on the network will get an address that screens clean. That is a reason to build it as an *advisory signal supporting a human allowlist decision*, not as the gate. 🔴 **The gate is and should remain cryptographic**: the allowlist plus the pinned federation key. Those are the things an adversary cannot rent. If IP screening ever becomes the thing standing between a hostile relay and the network, the design has regressed. ⚠️ **False positives land on legitimate self-hosters.** Someone running a relay from a VPS in a flagged range is the common case, not the adversary. There must be an override, and the override must be easy, or this quietly makes self-hosting worse — which is the opposite of the point. ⚠️ **"Government IP ranges" are not reliably enumerable.** Published allocations cover a small fraction; most state activity comes from commercial hosting like everyone else's. Treat the claim in any data source as low-confidence. ## Definition of done - [ ] Screening runs at peer-admission time and surfaces a reason to the operator - [ ] An operator can override any verdict, in one documented step - [ ] Refusals are logged with the reason, never silent - [ ] Isolated self-hosted relays are unaffected — covered by a test - [ ] `allowlist` remains the gate; screening is advisory and documented as such
paulhitt commented 2026-09-07 13:19:36 +00:00 (Migrated from gitlab.com)

mentioned in merge request !76

mentioned in merge request !76
paulhitt commented 2026-09-07 16:31:09 +00:00 (Migrated from gitlab.com)

mentioned in commit 058a897f52

mentioned in commit 058a897f52412c31b93d201f6d1f9f80c65998f0
paulhitt (Migrated from gitlab.com) closed this issue 2026-09-07 16:31:09 +00:00
Sign in to join this conversation.