/* * CSB Fake Player Guard * Copyright (C) 2026 counter-strike-boost.com * * Mitigates fake-player / FakeFull floods: caps concurrent connections per IP, * and drops clients that connect but never finish the handshake or send any * usercmds within a timeout (counted from CmdStart). * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. It is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See for details. */ #include #include new const PLUGIN[] = "CSB Fake Player Guard" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" #define TASK_BASE 31337 new g_pEnabled, g_pTimeout, g_pMaxPerIp new g_iCmds[33] new bool:g_bInGame[33] new g_szIp[33][24] public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) g_pEnabled = register_cvar("csb_fpg_enabled", "1") g_pTimeout = register_cvar("csb_fpg_timeout", "12") g_pMaxPerIp = register_cvar("csb_fpg_maxperip", "3") register_forward(FM_CmdStart, "fwCmdStart") } public client_connect(id) { g_iCmds[id] = 0 g_bInGame[id] = false get_user_ip(id, g_szIp[id], charsmax(g_szIp[]), 1) if (!get_pcvar_num(g_pEnabled)) return // concurrent connections from the same address new same = countIp(g_szIp[id], id) if (same >= get_pcvar_num(g_pMaxPerIp)) { log_amx("[CSB FakeGuard] %s already has %d connections - dropping new one", g_szIp[id], same) dropClient(id, "too many connections from your address") return } set_task(float(get_pcvar_num(g_pTimeout)), "taskHandshake", TASK_BASE + id) } public client_putinserver(id) { g_bInGame[id] = true } public fwCmdStart(id) { if (id >= 1 && id <= 32) g_iCmds[id]++ return FMRES_IGNORED } public taskHandshake(taskid) { new id = taskid - TASK_BASE if (id < 1 || id > 32 || !is_user_connected(id)) return // a genuine client is in the game and has produced input by now if (!g_bInGame[id] && g_iCmds[id] == 0) { new authid[35] get_user_authid(id, authid, charsmax(authid)) log_amx("[CSB FakeGuard] slot %d from %s <%s> never finished the handshake - dropping", id, g_szIp[id], authid) dropClient(id, "incomplete connection") } } countIp(const ip[], exclude) { new players[32], num get_players(players, num) new c = 0 for (new i = 0; i < num; i++) { new pid = players[i] if (pid == exclude) continue new pip[24] get_user_ip(pid, pip, charsmax(pip), 1) if (equal(pip, ip)) c++ } return c } dropClient(id, const reason[]) { server_cmd("kick #%d ^"CSB Fake Guard: %s^"", get_user_userid(id), reason) server_exec() }