feat(federation): add in-memory nonce store with TTL eviction (FED-008)
This commit is contained in:
@@ -121,6 +121,24 @@ function isRelayRateLimited(peerOrigin: string): boolean {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── In-memory nonce store for replay protection (per-peer) ──────────────────
|
||||||
|
// Maps peerOrigin → (nonce → insertion timestamp). Nonces are evicted after
|
||||||
|
// NONCE_MAX_AGE_MS (15 min) to match the HMAC timestamp window.
|
||||||
|
const NONCE_MAX_AGE_MS = 15 * 60 * 1000;
|
||||||
|
const nonceStore = new Map<string, Map<string, number>>();
|
||||||
|
|
||||||
|
/** Returns true if the nonce is a duplicate (already seen for this peer). */
|
||||||
|
function isNonceDuplicate(peerOrigin: string, nonce: string): boolean {
|
||||||
|
let peerNonces = nonceStore.get(peerOrigin);
|
||||||
|
if (!peerNonces) {
|
||||||
|
peerNonces = new Map();
|
||||||
|
nonceStore.set(peerOrigin, peerNonces);
|
||||||
|
}
|
||||||
|
if (peerNonces.has(nonce)) return true;
|
||||||
|
peerNonces.set(nonce, Date.now());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Periodically clean stale buckets to prevent unbounded memory growth
|
// Periodically clean stale buckets to prevent unbounded memory growth
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
const cutoff = Date.now() - ACCEPT_RATE_WINDOW_MS;
|
const cutoff = Date.now() - ACCEPT_RATE_WINDOW_MS;
|
||||||
@@ -141,6 +159,14 @@ setInterval(() => {
|
|||||||
relayRateBuckets.delete(origin);
|
relayRateBuckets.delete(origin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Evict expired nonces
|
||||||
|
const nonceCutoff = Date.now() - NONCE_MAX_AGE_MS;
|
||||||
|
for (const [origin, nonces] of nonceStore) {
|
||||||
|
for (const [nonce, ts] of nonces) {
|
||||||
|
if (ts < nonceCutoff) nonces.delete(nonce);
|
||||||
|
}
|
||||||
|
if (nonces.size === 0) nonceStore.delete(origin);
|
||||||
|
}
|
||||||
}, ACCEPT_RATE_WINDOW_MS).unref();
|
}, ACCEPT_RATE_WINDOW_MS).unref();
|
||||||
|
|
||||||
export async function federationRoutes(app: FastifyInstance): Promise<void> {
|
export async function federationRoutes(app: FastifyInstance): Promise<void> {
|
||||||
|
|||||||
Reference in New Issue
Block a user