mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-25 15:12:43 +00:00
add ws rate limiter
This commit is contained in:
Generated
+7
@@ -43,6 +43,7 @@
|
||||
"protobufjs": "^7.3.2",
|
||||
"pureimage": "^0.4.13",
|
||||
"raphael": "^2.3.0",
|
||||
"rate-limiter-flexible": "^5.0.5",
|
||||
"twemoji": "^14.0.2",
|
||||
"uuid": "^10.0.0",
|
||||
"wheelnav": "^1.7.1",
|
||||
@@ -13674,6 +13675,12 @@
|
||||
"eve-raphael": "0.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rate-limiter-flexible": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-5.0.5.tgz",
|
||||
"integrity": "sha512-+/dSQfo+3FYwYygUs/V2BBdwGa9nFtakDwKt4l0bnvNB53TNT++QSFewwHX9qXrZJuMe9j+TUaU21lm5ARgqdQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/raw-body": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
"protobufjs": "^7.3.2",
|
||||
"pureimage": "^0.4.13",
|
||||
"raphael": "^2.3.0",
|
||||
"rate-limiter-flexible": "^5.0.5",
|
||||
"twemoji": "^14.0.2",
|
||||
"uuid": "^10.0.0",
|
||||
"wheelnav": "^1.7.1",
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
</g>
|
||||
</svg>
|
||||
<div class="flex justify-center text-sm font-bold mt-[-5px] logo-version">
|
||||
v0.15.2
|
||||
v0.15.3
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import WebSocket from "ws";
|
||||
import { slog } from "./StructuredLog";
|
||||
import { CreateGameRecord } from "../core/Util";
|
||||
import { archive } from "./Archive";
|
||||
import { RateLimiterMemory } from "rate-limiter-flexible";
|
||||
|
||||
export enum GamePhase {
|
||||
Lobby = "LOBBY",
|
||||
@@ -26,6 +27,11 @@ export enum GamePhase {
|
||||
}
|
||||
|
||||
export class GameServer {
|
||||
private rateLimiter = new RateLimiterMemory({
|
||||
points: 20, // 20 messages
|
||||
duration: 1, // per 1 second
|
||||
});
|
||||
|
||||
private maxGameDuration = 5 * 60 * 60 * 1000; // 5 hours
|
||||
|
||||
private turns: Turn[] = [];
|
||||
@@ -98,7 +104,13 @@ export class GameServer {
|
||||
|
||||
this.allClients.set(client.clientID, client);
|
||||
|
||||
client.ws.on("message", (message: string) => {
|
||||
client.ws.on("message", async (message: string) => {
|
||||
try {
|
||||
await this.rateLimiter.consume(client.ip);
|
||||
} catch (error) {
|
||||
console.warn(`Rate limit exceeded for ${client.ip}`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const clientMsg: ClientMessage = ClientMessageSchema.parse(
|
||||
JSON.parse(message),
|
||||
|
||||
+18
-1
@@ -23,6 +23,7 @@ import {
|
||||
} from "../core/validations/username";
|
||||
import { Request, Response } from "express";
|
||||
import rateLimit from "express-rate-limit";
|
||||
import { RateLimiterMemory } from "rate-limiter-flexible";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
@@ -43,6 +44,11 @@ app.use(
|
||||
}),
|
||||
);
|
||||
|
||||
const rateLimiter = new RateLimiterMemory({
|
||||
points: 20, // 20 messages
|
||||
duration: 1, // per 1 second
|
||||
});
|
||||
|
||||
const gm = new GameManager(getServerConfig());
|
||||
|
||||
const bot = new DiscordBot();
|
||||
@@ -153,7 +159,18 @@ app.get("*", function (req, res) {
|
||||
});
|
||||
|
||||
wss.on("connection", (ws, req) => {
|
||||
ws.on("message", (message: string) => {
|
||||
ws.on("message", async (message: string) => {
|
||||
let ip = "";
|
||||
try {
|
||||
const forwarded = req.headers["x-forwarded-for"];
|
||||
ip = Array.isArray(forwarded)
|
||||
? forwarded[0]
|
||||
: forwarded || req.socket.remoteAddress;
|
||||
await rateLimiter.consume(ip);
|
||||
} catch (error) {
|
||||
console.warn(`rate limit exceede for ${ip}`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const clientMsg: ClientMessage = ClientMessageSchema.parse(
|
||||
JSON.parse(message),
|
||||
|
||||
Reference in New Issue
Block a user