backend: add gateway ratelimit

This commit is contained in:
hippoz 2022-04-14 17:17:54 +03:00
parent 2f19cb211d
commit 9c9f764e6d
Signed by: hippoz
GPG key ID: 7C52899193467641
3 changed files with 12 additions and 2 deletions

View file

@ -12,4 +12,5 @@ export const gatewayErrors = {
BAD_AUTH: { code: 4002, message: "Bad authentication" },
AUTHENTICATION_TIMEOUT: { code: 4003, message: "Authentication timeout" },
NO_PING: { code: 4004, message: "No ping" },
FLOODING: { code: 4005, message: "Flooding (exceeded maximum messages per batch)" },
};

View file

@ -9,6 +9,7 @@ import { GatewayPayloadType } from "./gatewaypayloadtype";
const GATEWAY_BATCH_INTERVAL = 50000;
const GATEWAY_PING_INTERVAL = 40000;
const MAX_CLIENT_MESSAGES_PER_BATCH = 6; // TODO: how well does this work for weak connections?
// mapping between a dispatch id and a websocket client
const dispatchChannels = new Map<string, Set<WebSocket>>();
@ -128,6 +129,7 @@ export default function(server: Server) {
if (!e.state.alive) {
return closeWithError(e, gatewayErrors.NO_PING);
}
e.state.messagesSinceLastCheck = 0;
}
});
}, GATEWAY_BATCH_INTERVAL);
@ -144,7 +146,8 @@ export default function(server: Server) {
alive: false,
ready: false,
lastAliveCheck: performance.now(),
dispatchChannels: new Set()
dispatchChannels: new Set(),
messagesSinceLastCheck: 0
};
sendPayload(ws, {
@ -163,6 +166,11 @@ export default function(server: Server) {
return closeWithBadPayload(ws, "Binary messages are not supported");
}
ws.state.messagesSinceLastCheck++;
if (ws.state.messagesSinceLastCheck > MAX_CLIENT_MESSAGES_PER_BATCH) {
return closeWithError(ws, gatewayErrors.FLOODING);
}
const payload = ensureFormattedGatewayPayload(parseJsonOrNull(rawData.toString()));
if (!payload) {
return closeWithBadPayload(ws, "Invalid JSON or message does not match schema");

View file

@ -3,5 +3,6 @@ interface GatewayClientState {
ready: boolean,
alive: boolean,
lastAliveCheck: number,
dispatchChannels: Set<string>
dispatchChannels: Set<string>,
messagesSinceLastCheck: number
}