sync to upstream

This commit is contained in:
2026-02-24 14:44:48 +01:00
parent 8a53bf1027
commit 648ef00bed
10 changed files with 93 additions and 15 deletions
+33 -7
View File
@@ -3,12 +3,19 @@ const { serverConfig } = require('./server_config');
const { logChat } = require('./console');
const helpers = require('./helpers');
function heartbeat() { // WebSocket heartbeat helper
this.isAlive = true;
}
function createChatServer(storage) {
if (!serverConfig.webserver.chatEnabled) return null;
const chatWss = new WebSocket.Server({ noServer: true });
chatWss.on('connection', (ws, request) => {
ws.isAlive = true;
ws.on('pong', heartbeat);
const clientIp = request.headers['x-forwarded-for'] || request.socket.remoteAddress;
const userCommandHistory = {};
@@ -25,19 +32,18 @@ function createChatServer(storage) {
ws.send(JSON.stringify(historyMessage));
});
const ipMessage = {
ws.send(JSON.stringify({
type: 'clientIp',
ip: clientIp,
admin: request.session?.isAdminAuthenticated
};
}));
ws.send(JSON.stringify(ipMessage));
const userCommands = {};
let lastWarn = { time: 0 };
ws.on('message', (message) => {
helpers.antispamProtection(
message = helpers.antispamProtection(
message,
clientIp,
ws,
@@ -45,9 +51,12 @@ function createChatServer(storage) {
lastWarn,
userCommandHistory,
'5',
'chat'
'chat',
512
);
if(!message) return;
let messageData;
try {
@@ -57,8 +66,6 @@ function createChatServer(storage) {
return;
}
console.log("Chat message:", messageData);
delete messageData.admin;
delete messageData.ip;
delete messageData.time;
@@ -90,6 +97,25 @@ function createChatServer(storage) {
}
});
});
ws.on('close', () => {
ws.isAlive = false;
});
});
/**
* We will not always be receiving data, so some proxies may terminate the connection, this prevents it.
*/
const interval = setInterval(() => {
chatWss.clients.forEach((ws) => {
if (ws.isAlive === false) return ws.terminate();
ws.isAlive = false;
ws.ping();
});
}, 30000);
chatWss.on('close', () => {
clearInterval(interval);
});
return chatWss;
+8 -2
View File
@@ -250,12 +250,18 @@ function checkLatency(host, port = 80, timeout = 2000) {
});
}
function antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, lengthCommands, endpointName) {
const command = message.toString();
function antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, lengthCommands, endpointName, maxPayloadSize = 1024 * 1024) {
const rawCommand = message.toString();
const command = rawCommand.replace(/[\r\n]+/g, '');
const now = Date.now();
const normalizedClientIp = clientIp?.replace(/^::ffff:/, '');
if (endpointName === 'text') consoleCmd.logDebug(`Command received from \x1b[90m${clientIp}\x1b[0m: ${command}`);
if (command.length > maxPayloadSize) {
consoleCmd.logWarn(`Command from \x1b[90m${normalizedClientIp}\x1b[0m on \x1b[90m/${endpointName}\x1b[0m exceeded maximum payload size (${parseInt(command.length / 1024)} KB / ${parseInt(maxPayloadSize / 1024)} KB).`);
return "";
}
// Initialize user command history if not present
if (!userCommandHistory[clientIp]) userCommandHistory[clientIp] = [];
+1 -1
View File
@@ -356,7 +356,7 @@ wss.on('connection', (ws, request) => {
let lastWarn = { time: 0 };
ws.on('message', (message) => {
const command = helpers.antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, '18', 'text');
const command = helpers.antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, '18', 'text', 16 * 1024);
if (!clientIp.includes("127.0.0.1")) {
if (((command.startsWith('X') || command.startsWith('Y')) && !request.session.isAdminAuthenticated) ||