From 4fbd2e5c5e21ab0d26bb16245dd656557f87765b Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sun, 27 Sep 2026 22:20:14 +0200 Subject: fix(hub): rate-limit per client, not per proxy Behind Caddy every request's TCP peer is loopback, and the limiter was keyed on that peer (slowapi's get_remote_address), so each limit was one bucket for the whole internet: ten node sign-ins a minute shared by every node. A node starting while others signed in got 429 and sat in waiting_for_hub, which the desktop app took for no node at all. Key it on client_ip, which already resolves X-Forwarded-For from a trusted proxy and was written for this. Co-Authored-By: Claude Opus 5.5 --- packages/meshbay-hub/src/meshbay_hub/api/middleware.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'packages/meshbay-hub/src') diff --git a/packages/meshbay-hub/src/meshbay_hub/api/middleware.py b/packages/meshbay-hub/src/meshbay_hub/api/middleware.py index bed7b54..3a2a5c3 100644 --- a/packages/meshbay-hub/src/meshbay_hub/api/middleware.py +++ b/packages/meshbay-hub/src/meshbay_hub/api/middleware.py @@ -7,7 +7,11 @@ to mitigate credential stuffing and registration floods. """ from slowapi import Limiter -from slowapi.util import get_remote_address -# Rate limiter instance — mounted on the FastAPI app in app.py -limiter = Limiter(key_func=get_remote_address) +from meshbay_hub.api.netutil import client_ip + +# Rate limiter instance — mounted on the FastAPI app in app.py. +# Keyed on client_ip, not slowapi's get_remote_address: behind Caddy every +# request's peer is loopback, so the peer address put the whole internet in one +# bucket — ten node sign-ins a minute, shared by every node there is. +limiter = Limiter(key_func=client_ip) -- cgit v1.2.3