mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 13:20:43 +00:00
add ws rate limiter
This commit is contained in:
Generated
+7
@@ -44,6 +44,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",
|
||||
@@ -13895,6 +13896,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",
|
||||
|
||||
@@ -108,6 +108,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",
|
||||
|
||||
@@ -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),
|
||||
|
||||
+24
-8
@@ -32,6 +32,7 @@ import dotenv from "dotenv";
|
||||
import crypto from "crypto";
|
||||
dotenv.config();
|
||||
import rateLimit from "express-rate-limit";
|
||||
import { RateLimiterMemory } from "rate-limiter-flexible";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
@@ -61,15 +62,19 @@ app.use(
|
||||
}),
|
||||
);
|
||||
|
||||
app.set("trust proxy", 2);
|
||||
app.use(
|
||||
rateLimit({
|
||||
windowMs: 1000, // 1 second
|
||||
max: 20, // 20 requests per IP per second
|
||||
}),
|
||||
);
|
||||
const rateLimiter = new RateLimiterMemory({
|
||||
points: 20, // 20 messages
|
||||
duration: 1, // per 1 second
|
||||
});
|
||||
|
||||
const gm = new GameManager(serverConfig);
|
||||
const gm = new GameManager(getServerConfig());
|
||||
|
||||
const bot = new DiscordBot();
|
||||
try {
|
||||
await bot.start();
|
||||
} catch (error) {
|
||||
console.error("Failed to start bot:", error);
|
||||
}
|
||||
|
||||
let lobbiesString = "";
|
||||
|
||||
@@ -241,6 +246,17 @@ app.get("*", function (req, res) {
|
||||
|
||||
wss.on("connection", (ws, req) => {
|
||||
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