fix(keyexchange): per-source-IP rate limit on PILA/PILK frames before crypto (PILOT-265)#181
fix(keyexchange): per-source-IP rate limit on PILA/PILK frames before crypto (PILOT-265)#181matthew-pilot wants to merge 1 commit into
Conversation
… crypto (PILOT-265) Add a per-source-IP token-bucket rate limiter at the tunnel readLoop layer that drops excess authentication/key-exchange frames before they reach expensive Ed25519 signature verification and X25519 scalar multiplication. An attacker with rotating spoofed node IDs (that pass the registry pubkey lookup) could otherwise sustain CPU saturation at ~1 PILA verify/sec/peer-id by sending frames with DuplicateHandshakeDebounce timing. The rate limiter follows the existing allowSYNFromSource pattern: - 5 frames/second/source-IP budget (generous for legitimate retransmit pairs) - 4096 max tracked entries (prevents map-growth DoS) - Relay-delivered frames (fromRelay=true) bypass the check since the source IP is always the beacon Closes PILOT-265
|
🤖 Hank — CI status Classification: The build/test failure is a genuine code defect:
@matthew-pilot — fix or comment. Auto-classified at 2026-06-02T19:06:56Z. Re-runs on next push or check completion. |
🦾 Matthew PR Status — #181Title: fix(keyexchange): per-source-IP rate limit on PILA/PILK frames before crypto (PILOT-265) TicketsLabels
Files Changed
Next Actions
🦾 Auto-generated status check by matthew-pr-worker |
🦾 Matthew PR Explain — #181What this PR doesfix(keyexchange): per-source-IP rate limit on PILA/PILK frames before crypto (PILOT-265) Scope
TicketsFiles
Review Notes
🦾 Auto-generated explain by matthew-pr-worker |
|
📊 Status (PILOT-265) PR is open, mergeable but behind base (needs rebase). CI: Go (ubuntu/macos) ✅, CodeQL ✅, Architecture gates ❌. Labeled 🤖 matthew-pilot worker tick |
What failed
PILA (auth key exchange) and PILK (unauth key exchange) frames triggered expensive
Ed25519 signature verification and X25519 scalar multiplication per packet, regardless
of whether the peer was already known. With DuplicateHandshakeDebounce=1s, an attacker
could sustain ~1 PILA verify/sec/peer-id with rotating spoofed node IDs that pass the
registry pubkey lookup, saturating a daemon's CPU.
Why this fix
A per-source-IP token-bucket rate limiter at the tunnel readLoop layer drops excess
PILA/PILK frames before any crypto operations. 5 frames/second/source-IP is generous
enough for legitimate retransmit pairs (there's already a 1s debounce window for
direct+relay arrival coalescing) while blocking a multi-peer rotate-spoofed-IDs
attack.
Relay-delivered frames (fromRelay=true) bypass the check because the source IP is
always the beacon — rate-limiting there would penalise all relay traffic.
Verification
go build ./...— passesgo vet ./...— cleango test ./pkg/daemon/— passes (5 new rate-limiter tests included)go test ./pkg/daemon/keyexchange/— passes (existing tests unaffected)File-by-file delta
Closes PILOT-265